Merge "Additional dialog API updates" into androidx-main
diff --git a/appfunctions/appfunctions-agent-compiler/build.gradle b/appfunctions/appfunctions-agent-compiler/build.gradle
deleted file mode 100644
index 3cfe406..0000000
--- a/appfunctions/appfunctions-agent-compiler/build.gradle
+++ /dev/null
@@ -1,41 +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.
- */
-
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.LibraryType
-
-plugins {
-    id("AndroidXPlugin")
-    id("kotlin")
-}
-
-dependencies {
-    api(libs.kotlinStdlib)
-    // Add dependencies here
-}
-
-androidx {
-    name = "androidx.appfunctions:appfunctions-agent-compiler"
-    type = LibraryType.ANNOTATION_PROCESSOR
-    inceptionYear = "2024"
-    description = "AppFunction Agent Compiler"
-}
diff --git a/appfunctions/appfunctions-agent-runtime/src/main/java/androidx/appfunctions/androidx-appfunctions-appfunctions-agent-runtime-documentation.md b/appfunctions/appfunctions-agent-runtime/src/main/java/androidx/appfunctions/androidx-appfunctions-appfunctions-agent-runtime-documentation.md
deleted file mode 100644
index fc08b37..0000000
--- a/appfunctions/appfunctions-agent-runtime/src/main/java/androidx/appfunctions/androidx-appfunctions-appfunctions-agent-runtime-documentation.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# Module root
-
-androidx.appfunctions appfunctions-agent-runtime
-
-# Package androidx.appfunctions.agent.runtime
-
-Insert package level documentation here
diff --git a/appfunctions/appfunctions-app-compiler/build.gradle b/appfunctions/appfunctions-app-compiler/build.gradle
index bd11ef3..c30d349 100644
--- a/appfunctions/appfunctions-app-compiler/build.gradle
+++ b/appfunctions/appfunctions-app-compiler/build.gradle
@@ -36,14 +36,14 @@
     implementation(libs.kspApi)
     implementation(libs.kotlinPoet)
 
-    testImplementationAarAsJar(project(":appfunctions:appfunctions-app-runtime"))
+    testImplementationAarAsJar(project(":appfunctions:appfunctions-runtime"))
     testImplementation(libs.googleCompileTesting)
     testImplementation(project(":room:room-compiler-processing-testing"))
     testImplementation(libs.junit)
     testImplementation(libs.truth)
 }
 
-def testGeneratedSourcesPath = "${project.buildDir}/testGeneratedSources"
+def testGeneratedSourcesPath = "${layout.buildDirectory.get().asFile}/testGeneratedSources"
 tasks.withType(Test).configureEach { test ->
     test.doFirst {
         systemProperty("test_output_dir", testGeneratedSourcesPath)
diff --git a/appfunctions/appfunctions-app-runtime/api/current.txt b/appfunctions/appfunctions-app-runtime/api/current.txt
index 12618c3..e6f50d0 100644
--- a/appfunctions/appfunctions-app-runtime/api/current.txt
+++ b/appfunctions/appfunctions-app-runtime/api/current.txt
@@ -1,10 +1 @@
 // Signature format: 4.0
-package androidx.appfunctions.app {
-
-  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.SOURCE) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface AppFunction {
-    method public abstract boolean isEnabled() default true;
-    property public abstract boolean isEnabled;
-  }
-
-}
-
diff --git a/appfunctions/appfunctions-app-runtime/api/restricted_current.txt b/appfunctions/appfunctions-app-runtime/api/restricted_current.txt
index 12618c3..e6f50d0 100644
--- a/appfunctions/appfunctions-app-runtime/api/restricted_current.txt
+++ b/appfunctions/appfunctions-app-runtime/api/restricted_current.txt
@@ -1,10 +1 @@
 // Signature format: 4.0
-package androidx.appfunctions.app {
-
-  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.SOURCE) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface AppFunction {
-    method public abstract boolean isEnabled() default true;
-    property public abstract boolean isEnabled;
-  }
-
-}
-
diff --git a/appfunctions/appfunctions-common/build.gradle b/appfunctions/appfunctions-common/build.gradle
index 8bfffe4..f950ea4 100644
--- a/appfunctions/appfunctions-common/build.gradle
+++ b/appfunctions/appfunctions-common/build.gradle
@@ -38,14 +38,14 @@
     implementation("androidx.annotation:annotation:1.8.1")
 
     // Compile only dependencies
-    compileOnly(fileTree(dir: "../appfunctions-stubs", include: ["com.android.extensions.appfunctions-stubs.jar"]))
+    compileOnly(project(":appfunctions:appfunctions-stubs"))
 
     // Test dependencies
     androidTestImplementation(libs.testCore)
     androidTestImplementation(libs.testRules)
     androidTestImplementation(libs.truth)
     androidTestImplementation(libs.junit)
-    androidTestCompileOnly(fileTree(dir: "../appfunctions-stubs", include: ["com.android.extensions.appfunctions-stubs.jar"]))
+    androidTestCompileOnly(project(":appfunctions:appfunctions-stubs"))
 }
 
 android {
diff --git a/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/common/metadata/AppFunctionMetadataTest.kt b/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/metadata/AppFunctionMetadataTest.kt
similarity index 97%
rename from appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/common/metadata/AppFunctionMetadataTest.kt
rename to appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/metadata/AppFunctionMetadataTest.kt
index d6406be..3dd7c6f 100644
--- a/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/common/metadata/AppFunctionMetadataTest.kt
+++ b/appfunctions/appfunctions-common/src/androidTest/java/androidx/appfunctions/metadata/AppFunctionMetadataTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 The Android Open Source Project
+ * Copyright 2025 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.appfunctions.common.metadata
+package androidx.appfunctions.metadata
 
-import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth
 import org.junit.Test
 
 class AppFunctionMetadataTest {
@@ -44,11 +44,12 @@
                 components = AppFunctionComponentsMetadata(dataTypes = emptyList())
             )
 
-        assertThat(appFunctionMetadata.id).isEqualTo("androidx.appfunctions.common.metadata#empty")
-        assertThat(appFunctionMetadata.isEnabledByDefault).isTrue()
-        assertThat(appFunctionMetadata.isRestrictToTrustedCaller).isFalse()
-        assertThat(appFunctionMetadata.displayNameRes).isEqualTo(100)
-        assertThat(appFunctionMetadata.schema)
+        Truth.assertThat(appFunctionMetadata.id)
+            .isEqualTo("androidx.appfunctions.common.metadata#empty")
+        Truth.assertThat(appFunctionMetadata.isEnabledByDefault).isTrue()
+        Truth.assertThat(appFunctionMetadata.isRestrictToTrustedCaller).isFalse()
+        Truth.assertThat(appFunctionMetadata.displayNameRes).isEqualTo(100)
+        Truth.assertThat(appFunctionMetadata.schema)
             .isEqualTo(
                 AppFunctionSchemaMetadata(
                     schemaCategory = "exampleCategory",
@@ -56,15 +57,15 @@
                     schemaVersion = 200L
                 )
             )
-        assertThat(appFunctionMetadata.parameters).isEmpty()
-        assertThat(appFunctionMetadata.response)
+        Truth.assertThat(appFunctionMetadata.parameters).isEmpty()
+        Truth.assertThat(appFunctionMetadata.response)
             .isEqualTo(
                 AppFunctionResponseMetadata(
                     isNullable = false,
                     dataType = AppFunctionDataTypeMetadata(type = AppFunctionDataTypeMetadata.UNIT)
                 )
             )
-        assertThat(appFunctionMetadata.components)
+        Truth.assertThat(appFunctionMetadata.components)
             .isEqualTo(AppFunctionComponentsMetadata(dataTypes = emptyList()))
     }
 
@@ -181,7 +182,7 @@
                     ),
             )
 
-        assertThat(appFunctionMetadata.parameters)
+        Truth.assertThat(appFunctionMetadata.parameters)
             .containsExactly(
                 AppFunctionParameterMetadata(
                     name = "requiredInt",
@@ -495,7 +496,7 @@
                     )
             )
 
-        assertThat(appFunctionMetadata.parameters)
+        Truth.assertThat(appFunctionMetadata.parameters)
             .containsExactly(
                 AppFunctionParameterMetadata(
                     name = "nonNullIntList",
@@ -760,7 +761,7 @@
                     )
             )
 
-        assertThat(appFunctionMetadata.components.dataTypes)
+        Truth.assertThat(appFunctionMetadata.components.dataTypes)
             .containsExactly(
                 AppFunctionDataTypeMetadata(
                     id = "androidx.appfunctions.common.TestClass",
@@ -778,7 +779,7 @@
                         )
                 )
             )
-        assertThat(appFunctionMetadata.parameters)
+        Truth.assertThat(appFunctionMetadata.parameters)
             .containsExactly(
                 AppFunctionParameterMetadata(
                     name = "testClass",
@@ -834,7 +835,7 @@
                     )
             )
 
-        assertThat(appFunctionMetadata.components.dataTypes)
+        Truth.assertThat(appFunctionMetadata.components.dataTypes)
             .containsExactly(
                 AppFunctionDataTypeMetadata(
                     id = "androidx.appfunctions.common.TestClass",
@@ -852,7 +853,7 @@
                         )
                 )
             )
-        assertThat(appFunctionMetadata.parameters)
+        Truth.assertThat(appFunctionMetadata.parameters)
             .containsExactly(
                 AppFunctionParameterMetadata(
                     name = "testClass",
diff --git a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/AppFunctionException.kt b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/AppFunctionException.kt
index 35dbf20..cf82d12 100644
--- a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/AppFunctionException.kt
+++ b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/AppFunctionException.kt
@@ -105,6 +105,7 @@
 
     public companion object {
         @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+        @SuppressWarnings("WrongConstant")
         public fun fromPlatformExtensionsClass(
             exception: com.android.extensions.appfunctions.AppFunctionException
         ): AppFunctionException {
diff --git a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionComponentsMetadata.kt b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionComponentsMetadata.kt
similarity index 97%
rename from appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionComponentsMetadata.kt
rename to appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionComponentsMetadata.kt
index a407d8b..854a6e5 100644
--- a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionComponentsMetadata.kt
+++ b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionComponentsMetadata.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.appfunctions.common.metadata
+package androidx.appfunctions.metadata
 
 import androidx.annotation.RestrictTo
 import androidx.appsearch.annotation.Document
diff --git a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionDataTypeMetadata.kt b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionDataTypeMetadata.kt
similarity index 98%
rename from appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionDataTypeMetadata.kt
rename to appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionDataTypeMetadata.kt
index 369f109..01997cb 100644
--- a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionDataTypeMetadata.kt
+++ b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionDataTypeMetadata.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.appfunctions.common.metadata
+package androidx.appfunctions.metadata
 
 import androidx.annotation.IntDef
 import androidx.annotation.RestrictTo
diff --git a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionItemTypeMetadata.kt b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionItemTypeMetadata.kt
similarity index 98%
rename from appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionItemTypeMetadata.kt
rename to appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionItemTypeMetadata.kt
index bb6ca96..792fb62 100644
--- a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionItemTypeMetadata.kt
+++ b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionItemTypeMetadata.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.appfunctions.common.metadata
+package androidx.appfunctions.metadata
 
 import androidx.annotation.RestrictTo
 import androidx.appsearch.annotation.Document
diff --git a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionMetadata.kt b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionMetadata.kt
similarity index 98%
rename from appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionMetadata.kt
rename to appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionMetadata.kt
index 583148b..2b45e72 100644
--- a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionMetadata.kt
+++ b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionMetadata.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.appfunctions.common.metadata
+package androidx.appfunctions.metadata
 
 import androidx.annotation.RestrictTo
 import androidx.appsearch.annotation.Document
diff --git a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionParameterMetadata.kt b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionParameterMetadata.kt
similarity index 98%
rename from appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionParameterMetadata.kt
rename to appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionParameterMetadata.kt
index 14aa32c..6d449e8 100644
--- a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionParameterMetadata.kt
+++ b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionParameterMetadata.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.appfunctions.common.metadata
+package androidx.appfunctions.metadata
 
 import androidx.annotation.RestrictTo
 import androidx.appsearch.annotation.Document
diff --git a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionResponseMetadata.kt b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionResponseMetadata.kt
similarity index 98%
rename from appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionResponseMetadata.kt
rename to appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionResponseMetadata.kt
index 7447820..cdabcdf 100644
--- a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionResponseMetadata.kt
+++ b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionResponseMetadata.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.appfunctions.common.metadata
+package androidx.appfunctions.metadata
 
 import androidx.annotation.RestrictTo
 import androidx.appsearch.annotation.Document
diff --git a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionSchemaMetadata.kt b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionSchemaMetadata.kt
similarity index 98%
rename from appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionSchemaMetadata.kt
rename to appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionSchemaMetadata.kt
index 62cb03d..d30f6eb 100644
--- a/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/common/metadata/AppFunctionSchemaMetadata.kt
+++ b/appfunctions/appfunctions-common/src/main/java/androidx/appfunctions/metadata/AppFunctionSchemaMetadata.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.appfunctions.common.metadata
+package androidx.appfunctions.metadata
 
 import androidx.annotation.RestrictTo
 import androidx.appsearch.annotation.Document
diff --git a/appfunctions/appfunctions-compiler/build.gradle b/appfunctions/appfunctions-compiler/build.gradle
new file mode 100644
index 0000000..bc0e999
--- /dev/null
+++ b/appfunctions/appfunctions-compiler/build.gradle
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This file was created using the `create_project.py` script located in the
+ * `<AndroidX root>/development/project-creator` directory.
+ *
+ * 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 {
+    id("AndroidXPlugin")
+    id("kotlin")
+}
+
+androidx.configureAarAsJarForConfiguration("testImplementation")
+
+dependencies {
+    api(libs.kotlinStdlib)
+    implementation(libs.kspApi)
+    implementation(libs.kotlinPoet)
+
+    testImplementationAarAsJar(project(":appfunctions:appfunctions-runtime"))
+    testImplementation(libs.googleCompileTesting)
+    testImplementation(project(":room:room-compiler-processing-testing"))
+    testImplementation(libs.junit)
+    testImplementation(libs.truth)
+}
+
+def testGeneratedSourcesPath = "${layout.buildDirectory.get().asFile}/testGeneratedSources"
+tasks.withType(Test).configureEach { test ->
+    test.doFirst {
+        systemProperty("test_output_dir", testGeneratedSourcesPath)
+    }
+}
+
+androidx {
+    name = "androidx.appfunctions:appfunctions-compiler"
+    type = LibraryType.ANNOTATION_PROCESSOR
+    inceptionYear = "2025"
+    description = "AppFunction Compiler"
+    kotlinTarget = KotlinTarget.KOTLIN_1_9
+}
diff --git a/appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/app/AppFunctionAppCompiler.kt b/appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/AppFunctionCompiler.kt
similarity index 88%
rename from appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/app/AppFunctionAppCompiler.kt
rename to appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/AppFunctionCompiler.kt
index b5370b8..81f6291 100644
--- a/appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/app/AppFunctionAppCompiler.kt
+++ b/appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/AppFunctionCompiler.kt
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package androidx.appfunctions.compiler.app
+package androidx.appfunctions.compiler
 
-import androidx.appfunctions.compiler.app.processors.AppFunctionIdProcessor
 import androidx.appfunctions.compiler.core.ProcessingException
 import androidx.appfunctions.compiler.core.logException
+import androidx.appfunctions.compiler.processors.AppFunctionIdProcessor
 import com.google.devtools.ksp.processing.KSPLogger
 import com.google.devtools.ksp.processing.Resolver
 import com.google.devtools.ksp.processing.SymbolProcessor
@@ -29,7 +29,7 @@
 import javax.annotation.processing.Generated
 
 /** The compiler to process AppFunction implementations. */
-class AppFunctionAppCompiler(
+class AppFunctionCompiler(
     private val processors: List<SymbolProcessor>,
     private val logger: KSPLogger,
 ) : SymbolProcessor {
@@ -51,7 +51,7 @@
 
         override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
             val idProcessor = AppFunctionIdProcessor(environment.codeGenerator)
-            return AppFunctionAppCompiler(
+            return AppFunctionCompiler(
                 listOf(
                     idProcessor,
                 ),
@@ -63,7 +63,7 @@
     companion object {
         internal val GENERATED_ANNOTATION =
             AnnotationSpec.builder(Generated::class)
-                .addMember("%S", AppFunctionAppCompiler::class.java.canonicalName)
+                .addMember("%S", AppFunctionCompiler::class.java.canonicalName)
                 .build()
     }
 }
diff --git a/appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/core/AppFunctionSymbolResolver.kt b/appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/core/AppFunctionSymbolResolver.kt
similarity index 91%
rename from appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/core/AppFunctionSymbolResolver.kt
rename to appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/core/AppFunctionSymbolResolver.kt
index cf7dfdc..5e55efef 100644
--- a/appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/core/AppFunctionSymbolResolver.kt
+++ b/appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/core/AppFunctionSymbolResolver.kt
@@ -60,9 +60,15 @@
      * functions.
      */
     data class AnnotatedAppFunctions(
-        /** The [KSClassDeclaration] of the class that contains the annotated app functions. */
+        /**
+         * The [com.google.devtools.ksp.symbol.KSClassDeclaration] of the class that contains the
+         * annotated app functions.
+         */
         val classDeclaration: KSClassDeclaration,
-        /** The list of [KSFunctionDeclaration] that annotated as app function. */
+        /**
+         * The list of [com.google.devtools.ksp.symbol.KSFunctionDeclaration] that annotated as app
+         * function.
+         */
         val appFunctionDeclarations: List<KSFunctionDeclaration>
     ) {
         fun validate(): AnnotatedAppFunctions {
diff --git a/appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/core/IntrospectionHelper.kt b/appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/core/IntrospectionHelper.kt
similarity index 82%
rename from appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/core/IntrospectionHelper.kt
rename to appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/core/IntrospectionHelper.kt
index 284735b..7c0fe98 100644
--- a/appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/core/IntrospectionHelper.kt
+++ b/appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/core/IntrospectionHelper.kt
@@ -21,10 +21,10 @@
 /** Helper class to introspect AppFunction symbols. */
 object IntrospectionHelper {
     // Package names
-    private const val APP_FUNCTIONS_APP_RUNTIME_PACKAGE_NAME = "androidx.appfunctions.app"
+    private const val APP_FUNCTIONS_PACKAGE_NAME = "androidx.appfunctions"
 
     // Annotation classes
     object AppFunctionAnnotation {
-        val CLASS_NAME = ClassName(APP_FUNCTIONS_APP_RUNTIME_PACKAGE_NAME, "AppFunction")
+        val CLASS_NAME = ClassName(APP_FUNCTIONS_PACKAGE_NAME, "AppFunction")
     }
 }
diff --git a/appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/core/KSPLoggerUtils.kt b/appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/core/KSPLoggerUtils.kt
similarity index 100%
rename from appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/core/KSPLoggerUtils.kt
rename to appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/core/KSPLoggerUtils.kt
diff --git a/appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/core/ProcessingException.kt b/appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/core/ProcessingException.kt
similarity index 100%
rename from appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/core/ProcessingException.kt
rename to appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/core/ProcessingException.kt
diff --git a/appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/core/StringUtils.kt b/appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/core/StringUtils.kt
similarity index 100%
rename from appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/core/StringUtils.kt
rename to appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/core/StringUtils.kt
diff --git a/appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/app/processors/AppFunctionIdProcessor.kt b/appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/processors/AppFunctionIdProcessor.kt
similarity index 95%
rename from appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/app/processors/AppFunctionIdProcessor.kt
rename to appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/processors/AppFunctionIdProcessor.kt
index 8909898..06cc21b 100644
--- a/appfunctions/appfunctions-app-compiler/src/main/java/androidx/appfunctions/compiler/app/processors/AppFunctionIdProcessor.kt
+++ b/appfunctions/appfunctions-compiler/src/main/java/androidx/appfunctions/compiler/processors/AppFunctionIdProcessor.kt
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.appfunctions.compiler.app.processors
+package androidx.appfunctions.compiler.processors
 
-import androidx.appfunctions.compiler.app.AppFunctionAppCompiler
+import androidx.appfunctions.compiler.AppFunctionCompiler
 import androidx.appfunctions.compiler.core.AppFunctionSymbolResolver
 import androidx.appfunctions.compiler.core.AppFunctionSymbolResolver.AnnotatedAppFunctions
 import androidx.appfunctions.compiler.core.fromCamelCaseToScreamingSnakeCase
@@ -69,7 +69,7 @@
         val idClassName = getAppFunctionIdClassName(originalClassName)
         val classBuilder =
             TypeSpec.objectBuilder(idClassName).apply {
-                addAnnotation(AppFunctionAppCompiler.GENERATED_ANNOTATION)
+                addAnnotation(AppFunctionCompiler.GENERATED_ANNOTATION)
                 addAppFunctionIdProperties(appFunctionClass)
             }
 
diff --git a/appfunctions/appfunctions-app-compiler/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider b/appfunctions/appfunctions-compiler/src/main/resources/META-INF.services/com.google.devtools.ksp.processing.SymbolProcessorProvider
similarity index 89%
rename from appfunctions/appfunctions-app-compiler/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider
rename to appfunctions/appfunctions-compiler/src/main/resources/META-INF.services/com.google.devtools.ksp.processing.SymbolProcessorProvider
index 2452fa2..19f55be 100644
--- a/appfunctions/appfunctions-app-compiler/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider
+++ b/appfunctions/appfunctions-compiler/src/main/resources/META-INF.services/com.google.devtools.ksp.processing.SymbolProcessorProvider
@@ -13,4 +13,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-androidx.appfunctions.compiler.app.AppFunctionAppCompiler$Provider
\ No newline at end of file
+androidx.appfunctions.compiler.AppFunctionCompiler$Provider
\ No newline at end of file
diff --git a/appfunctions/appfunctions-app-compiler/src/test/java/androidx/appfunctions/compiler/app/AppFunctionAppCompilerTest.kt b/appfunctions/appfunctions-compiler/src/test/java/androidx/appfunctions/compiler/AppFunctionCompilerTest.kt
similarity index 85%
rename from appfunctions/appfunctions-app-compiler/src/test/java/androidx/appfunctions/compiler/app/AppFunctionAppCompilerTest.kt
rename to appfunctions/appfunctions-compiler/src/test/java/androidx/appfunctions/compiler/AppFunctionCompilerTest.kt
index 59de771..9c6b856 100644
--- a/appfunctions/appfunctions-app-compiler/src/test/java/androidx/appfunctions/compiler/app/AppFunctionAppCompilerTest.kt
+++ b/appfunctions/appfunctions-compiler/src/test/java/androidx/appfunctions/compiler/AppFunctionCompilerTest.kt
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package androidx.appfunctions.compiler.app
+package androidx.appfunctions.compiler
 
 import androidx.appfunctions.compiler.testings.CompilationTestHelper
-import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth
 import java.io.File
 import org.junit.Before
 import org.junit.Test
 
-class AppFunctionAppCompilerTest {
+class AppFunctionCompilerTest {
     private lateinit var compilationTestHelper: CompilationTestHelper
 
     @Before
@@ -31,7 +31,7 @@
             CompilationTestHelper(
                 testFileSrcDir = File("src/test/test-data/input"),
                 goldenFileSrcDir = File("src/test/test-data/output"),
-                symbolProcessorProviders = listOf(AppFunctionAppCompiler.Provider())
+                symbolProcessorProviders = listOf(AppFunctionCompiler.Provider())
             )
     }
 
@@ -39,7 +39,7 @@
     fun testEmpty() {
         val report = compilationTestHelper.compileAll(sourceFileNames = emptyList())
 
-        assertThat(report.isSuccess).isTrue()
+        Truth.assertThat(report.isSuccess).isTrue()
     }
 
     @Test
diff --git a/appfunctions/appfunctions-app-compiler/src/test/java/androidx/appfunctions/compiler/testings/CompilationTestHelper.kt b/appfunctions/appfunctions-compiler/src/test/java/androidx/appfunctions/compiler/testings/CompilationTestHelper.kt
similarity index 96%
rename from appfunctions/appfunctions-app-compiler/src/test/java/androidx/appfunctions/compiler/testings/CompilationTestHelper.kt
rename to appfunctions/appfunctions-compiler/src/test/java/androidx/appfunctions/compiler/testings/CompilationTestHelper.kt
index c7ce3d0..a616921 100644
--- a/appfunctions/appfunctions-app-compiler/src/test/java/androidx/appfunctions/compiler/testings/CompilationTestHelper.kt
+++ b/appfunctions/appfunctions-compiler/src/test/java/androidx/appfunctions/compiler/testings/CompilationTestHelper.kt
@@ -38,7 +38,7 @@
     private val testFileSrcDir: File,
     /** The root directory containing the source golden files. */
     private val goldenFileSrcDir: File,
-    /** A list of [SymbolProcessorProvider] under test. */
+    /** A list of [com.google.devtools.ksp.processing.SymbolProcessorProvider] under test. */
     private val symbolProcessorProviders: List<SymbolProcessorProvider>,
 ) {
 
@@ -69,7 +69,10 @@
         val sources =
             sourceFileNames.map { sourceFileName ->
                 val sourceFile = getTestSourceFile(sourceFileName)
-                Source.kotlin(ensureKotlinFileNameFormat(sourceFileName), sourceFile.readText())
+                Source.Companion.kotlin(
+                    ensureKotlinFileNameFormat(sourceFileName),
+                    sourceFile.readText()
+                )
             }
 
         val workingDir =
diff --git a/appfunctions/appfunctions-app-compiler/src/test/test-data/input/SimpleFunction.KT b/appfunctions/appfunctions-compiler/src/test/test-data/input/SimpleFunction.KT
similarity index 67%
rename from appfunctions/appfunctions-app-compiler/src/test/test-data/input/SimpleFunction.KT
rename to appfunctions/appfunctions-compiler/src/test/test-data/input/SimpleFunction.KT
index a091c9a..f2a27d5 100644
--- a/appfunctions/appfunctions-app-compiler/src/test/test-data/input/SimpleFunction.KT
+++ b/appfunctions/appfunctions-compiler/src/test/test-data/input/SimpleFunction.KT
@@ -1,6 +1,6 @@
 package com.testdata
 
-import androidx.appfunctions.app.AppFunction
+import androidx.appfunctions.AppFunction
 
 class SimpleFunction {
     @AppFunction
diff --git a/appfunctions/appfunctions-app-compiler/src/test/test-data/output/SimpleFunctionIds.KT b/appfunctions/appfunctions-compiler/src/test/test-data/output/SimpleFunctionIds.KT
similarity index 75%
rename from appfunctions/appfunctions-app-compiler/src/test/test-data/output/SimpleFunctionIds.KT
rename to appfunctions/appfunctions-compiler/src/test/test-data/output/SimpleFunctionIds.KT
index d177418..0243614 100644
--- a/appfunctions/appfunctions-app-compiler/src/test/test-data/output/SimpleFunctionIds.KT
+++ b/appfunctions/appfunctions-compiler/src/test/test-data/output/SimpleFunctionIds.KT
@@ -3,7 +3,7 @@
 import javax.`annotation`.processing.Generated
 import kotlin.String
 
-@Generated("androidx.appfunctions.compiler.app.AppFunctionAppCompiler")
+@Generated("androidx.appfunctions.compiler.AppFunctionCompiler")
 public object SimpleFunctionIds {
   public const val SIMPLE_FUNCTION_ID: String = "com.testdata.SimpleFunction#simpleFunction"
 }
diff --git a/appfunctions/appfunctions-runtime/api/current.txt b/appfunctions/appfunctions-runtime/api/current.txt
new file mode 100644
index 0000000..7394582
--- /dev/null
+++ b/appfunctions/appfunctions-runtime/api/current.txt
@@ -0,0 +1,10 @@
+// Signature format: 4.0
+package androidx.appfunctions {
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.SOURCE) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface AppFunction {
+    method public abstract boolean isEnabled() default true;
+    property public abstract boolean isEnabled;
+  }
+
+}
+
diff --git a/appfunctions/appfunctions-agent-runtime/api/res-current.txt b/appfunctions/appfunctions-runtime/api/res-current.txt
similarity index 100%
rename from appfunctions/appfunctions-agent-runtime/api/res-current.txt
rename to appfunctions/appfunctions-runtime/api/res-current.txt
diff --git a/appfunctions/appfunctions-runtime/api/restricted_current.txt b/appfunctions/appfunctions-runtime/api/restricted_current.txt
new file mode 100644
index 0000000..7394582
--- /dev/null
+++ b/appfunctions/appfunctions-runtime/api/restricted_current.txt
@@ -0,0 +1,10 @@
+// Signature format: 4.0
+package androidx.appfunctions {
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.SOURCE) @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.FUNCTION) public @interface AppFunction {
+    method public abstract boolean isEnabled() default true;
+    property public abstract boolean isEnabled;
+  }
+
+}
+
diff --git a/appfunctions/appfunctions-agent-runtime/build.gradle b/appfunctions/appfunctions-runtime/build.gradle
similarity index 70%
copy from appfunctions/appfunctions-agent-runtime/build.gradle
copy to appfunctions/appfunctions-runtime/build.gradle
index cce847f..3b37e08 100644
--- a/appfunctions/appfunctions-agent-runtime/build.gradle
+++ b/appfunctions/appfunctions-runtime/build.gradle
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 The Android Open Source Project
+ * Copyright (C) 2025 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.
@@ -31,16 +31,20 @@
 
 dependencies {
     api(libs.kotlinStdlib)
-    // Add dependencies here
+
+    // Internal dependencies
+    implementation("androidx.annotation:annotation:1.9.0-rc01")
+    implementation project(":appfunctions:appfunctions-common")
 }
 
 android {
-    namespace = "androidx.appfunctions.agent.runtime"
+    compileSdk = 35
+    namespace = "androidx.appfunctions.runtime"
 }
 
 androidx {
-    name = "androidx.appfunctions:appfunctions-agent-runtime"
+    name = "androidx.appfunctions:appfunctions-runtime"
     type = LibraryType.PUBLISHED_LIBRARY
-    inceptionYear = "2024"
-    description = "Provides a set of helper classes for the agent to interact with AppFunctions."
+    inceptionYear = "2025"
+    description = "Runtime library for the app to provide and interact with AppFunctions"
 }
diff --git a/appfunctions/appfunctions-app-runtime/src/main/java/androidx/appfunctions/app/AppFunction.kt b/appfunctions/appfunctions-runtime/src/main/java/androidx/appfunctions/AppFunction.kt
similarity index 98%
rename from appfunctions/appfunctions-app-runtime/src/main/java/androidx/appfunctions/app/AppFunction.kt
rename to appfunctions/appfunctions-runtime/src/main/java/androidx/appfunctions/AppFunction.kt
index 12def30..6b9a534 100644
--- a/appfunctions/appfunctions-app-runtime/src/main/java/androidx/appfunctions/app/AppFunction.kt
+++ b/appfunctions/appfunctions-runtime/src/main/java/androidx/appfunctions/AppFunction.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.appfunctions.app
+package androidx.appfunctions
 
 /**
  * Marks a function within a class as callable by other applications.
diff --git a/appfunctions/appfunctions-runtime/src/main/java/androidx/appfunctions/androidx-appfunctions-appfunctions-runtime-documentation.md b/appfunctions/appfunctions-runtime/src/main/java/androidx/appfunctions/androidx-appfunctions-appfunctions-runtime-documentation.md
new file mode 100644
index 0000000..5749274
--- /dev/null
+++ b/appfunctions/appfunctions-runtime/src/main/java/androidx/appfunctions/androidx-appfunctions-appfunctions-runtime-documentation.md
@@ -0,0 +1,7 @@
+# Module root
+
+androidx.appfunctions appfunctions-runtime
+
+# Package androidx.appfunctions.runtime
+
+Insert package level documentation here
diff --git a/appfunctions/appfunctions-runtime/src/main/java/androidx/appfunctions/internal/AppFunctionInventory.kt b/appfunctions/appfunctions-runtime/src/main/java/androidx/appfunctions/internal/AppFunctionInventory.kt
new file mode 100644
index 0000000..63cab1f
--- /dev/null
+++ b/appfunctions/appfunctions-runtime/src/main/java/androidx/appfunctions/internal/AppFunctionInventory.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2025 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.appfunctions.internal
+
+import androidx.annotation.RestrictTo
+import androidx.appfunctions.metadata.AppFunctionMetadata
+
+/**
+ * An interface providing access to metadata for a set of registered AppFunctions.
+ *
+ * This interface defines a contract for accessing metadata associated with AppFunctions. Each
+ * AppFunction implementation class has a corresponding generated inventory class that implements
+ * this interface. This inventory class provides a mapping between AppFunction IDs and their
+ * respective [AppFunctionMetadata].
+ *
+ * For example, consider the following AppFunction implementation:
+ * ```kotlin
+ * package com.example.imageeditor
+ *
+ * class ImageFunctions : RotateImage, BlurImage {
+ *   @AppFunction
+ *   override suspend fun rotateImage(...): Image { ... }
+ *
+ *   @AppFunction
+ *   override suspend fun blurImage(...): Image? { ... }
+ * }
+ * ```
+ *
+ * The generated inventory class for `ImageFunctions` would implement this interface and provide a
+ * map containing metadata for both `rotateImage` and `blurImage`.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+public interface AppFunctionInventory {
+    /** A map of function IDs to their corresponding [AppFunctionMetadata]. */
+    public val functionIdToMetadataMap: Map<String, AppFunctionMetadata>
+}
diff --git a/appfunctions/appfunctions-agent-runtime/api/current.txt b/appfunctions/appfunctions-stubs/api/current.txt
similarity index 100%
rename from appfunctions/appfunctions-agent-runtime/api/current.txt
rename to appfunctions/appfunctions-stubs/api/current.txt
diff --git a/appfunctions/appfunctions-agent-runtime/api/res-current.txt b/appfunctions/appfunctions-stubs/api/res-current.txt
similarity index 100%
copy from appfunctions/appfunctions-agent-runtime/api/res-current.txt
copy to appfunctions/appfunctions-stubs/api/res-current.txt
diff --git a/appfunctions/appfunctions-stubs/api/restricted_current.txt b/appfunctions/appfunctions-stubs/api/restricted_current.txt
new file mode 100644
index 0000000..fb5cb08
--- /dev/null
+++ b/appfunctions/appfunctions-stubs/api/restricted_current.txt
@@ -0,0 +1,77 @@
+// Signature format: 4.0
+package com.android.extensions.appfunctions {
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class AppFunctionException extends java.lang.Exception {
+    ctor public AppFunctionException(int, String?);
+    ctor public AppFunctionException(int, String?, android.os.Bundle);
+    method @com.android.extensions.appfunctions.AppFunctionException.ErrorCategory public int getErrorCategory();
+    method @com.android.extensions.appfunctions.AppFunctionException.ErrorCode public int getErrorCode();
+    method public String? getErrorMessage();
+    method public android.os.Bundle getExtras();
+    field public static final int ERROR_APP_UNKNOWN_ERROR = 3000; // 0xbb8
+    field public static final int ERROR_CANCELLED = 2001; // 0x7d1
+    field public static final int ERROR_CATEGORY_APP = 3; // 0x3
+    field public static final int ERROR_CATEGORY_REQUEST_ERROR = 1; // 0x1
+    field public static final int ERROR_CATEGORY_SYSTEM = 2; // 0x2
+    field public static final int ERROR_CATEGORY_UNKNOWN = 0; // 0x0
+    field public static final int ERROR_DENIED = 1000; // 0x3e8
+    field public static final int ERROR_DISABLED = 1002; // 0x3ea
+    field public static final int ERROR_ENTERPRISE_POLICY_DISALLOWED = 2002; // 0x7d2
+    field public static final int ERROR_FUNCTION_NOT_FOUND = 1003; // 0x3eb
+    field public static final int ERROR_INVALID_ARGUMENT = 1001; // 0x3e9
+    field public static final int ERROR_SYSTEM_ERROR = 2000; // 0x7d0
+  }
+
+  @IntDef({com.android.extensions.appfunctions.AppFunctionException.ERROR_CATEGORY_UNKNOWN, com.android.extensions.appfunctions.AppFunctionException.ERROR_CATEGORY_REQUEST_ERROR, com.android.extensions.appfunctions.AppFunctionException.ERROR_CATEGORY_APP, com.android.extensions.appfunctions.AppFunctionException.ERROR_CATEGORY_SYSTEM}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface AppFunctionException.ErrorCategory {
+  }
+
+  @IntDef({com.android.extensions.appfunctions.AppFunctionException.ERROR_DENIED, com.android.extensions.appfunctions.AppFunctionException.ERROR_APP_UNKNOWN_ERROR, com.android.extensions.appfunctions.AppFunctionException.ERROR_FUNCTION_NOT_FOUND, com.android.extensions.appfunctions.AppFunctionException.ERROR_SYSTEM_ERROR, com.android.extensions.appfunctions.AppFunctionException.ERROR_INVALID_ARGUMENT, com.android.extensions.appfunctions.AppFunctionException.ERROR_DISABLED, com.android.extensions.appfunctions.AppFunctionException.ERROR_CANCELLED, com.android.extensions.appfunctions.AppFunctionException.ERROR_ENTERPRISE_POLICY_DISALLOWED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface AppFunctionException.ErrorCode {
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class AppFunctionManager {
+    ctor public AppFunctionManager(android.content.Context);
+    method public void executeAppFunction(com.android.extensions.appfunctions.ExecuteAppFunctionRequest, java.util.concurrent.Executor, android.os.CancellationSignal, android.os.OutcomeReceiver<com.android.extensions.appfunctions.ExecuteAppFunctionResponse!,com.android.extensions.appfunctions.AppFunctionException!>);
+    method public void isAppFunctionEnabled(String, String, java.util.concurrent.Executor, android.os.OutcomeReceiver<java.lang.Boolean!,java.lang.Exception!>);
+    method public void isAppFunctionEnabled(String, java.util.concurrent.Executor, android.os.OutcomeReceiver<java.lang.Boolean!,java.lang.Exception!>);
+    method public void setAppFunctionEnabled(String, @com.android.extensions.appfunctions.AppFunctionManager.EnabledState int, java.util.concurrent.Executor, android.os.OutcomeReceiver<java.lang.Void!,java.lang.Exception!>);
+    field public static final int APP_FUNCTION_STATE_DEFAULT = 0; // 0x0
+    field public static final int APP_FUNCTION_STATE_DISABLED = 2; // 0x2
+    field public static final int APP_FUNCTION_STATE_ENABLED = 1; // 0x1
+  }
+
+  @IntDef({com.android.extensions.appfunctions.AppFunctionManager.APP_FUNCTION_STATE_DEFAULT, com.android.extensions.appfunctions.AppFunctionManager.APP_FUNCTION_STATE_ENABLED, com.android.extensions.appfunctions.AppFunctionManager.APP_FUNCTION_STATE_DISABLED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface AppFunctionManager.EnabledState {
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public abstract class AppFunctionService extends android.app.Service {
+    ctor public AppFunctionService();
+    method public final android.os.IBinder onBind(android.content.Intent?);
+    method @MainThread public abstract void onExecuteFunction(com.android.extensions.appfunctions.ExecuteAppFunctionRequest, String, android.os.CancellationSignal, android.os.OutcomeReceiver<com.android.extensions.appfunctions.ExecuteAppFunctionResponse!,com.android.extensions.appfunctions.AppFunctionException!>);
+    field public static final String BIND_APP_FUNCTION_SERVICE = "android.permission.BIND_APP_FUNCTION_SERVICE";
+    field public static final String SERVICE_INTERFACE = "android.app.appfunctions.AppFunctionService";
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class ExecuteAppFunctionRequest {
+    ctor public ExecuteAppFunctionRequest();
+    method public android.os.Bundle getExtras();
+    method public String getFunctionIdentifier();
+    method public android.app.appsearch.GenericDocument getParameters();
+    method public String getTargetPackageName();
+  }
+
+  public static final class ExecuteAppFunctionRequest.Builder {
+    ctor public ExecuteAppFunctionRequest.Builder(String, String);
+    method public com.android.extensions.appfunctions.ExecuteAppFunctionRequest build();
+    method public com.android.extensions.appfunctions.ExecuteAppFunctionRequest.Builder setExtras(android.os.Bundle);
+    method public com.android.extensions.appfunctions.ExecuteAppFunctionRequest.Builder setParameters(android.app.appsearch.GenericDocument);
+  }
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class ExecuteAppFunctionResponse {
+    ctor public ExecuteAppFunctionResponse(android.app.appsearch.GenericDocument);
+    ctor public ExecuteAppFunctionResponse(android.app.appsearch.GenericDocument, android.os.Bundle);
+    method public android.os.Bundle getExtras();
+    method public android.app.appsearch.GenericDocument getResultDocument();
+    field public static final String PROPERTY_RETURN_VALUE = "androidAppfunctionsReturnValue";
+  }
+
+}
+
diff --git a/appfunctions/appfunctions-agent-runtime/build.gradle b/appfunctions/appfunctions-stubs/build.gradle
similarity index 72%
rename from appfunctions/appfunctions-agent-runtime/build.gradle
rename to appfunctions/appfunctions-stubs/build.gradle
index cce847f..a5616f9 100644
--- a/appfunctions/appfunctions-agent-runtime/build.gradle
+++ b/appfunctions/appfunctions-stubs/build.gradle
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2024 The Android Open Source Project
+ * Copyright (C) 2025 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.
@@ -26,21 +26,21 @@
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
-    id("org.jetbrains.kotlin.android")
 }
 
 dependencies {
-    api(libs.kotlinStdlib)
-    // Add dependencies here
+    annotationProcessor(libs.nullaway)
+    api(libs.jspecify)
+    implementation("androidx.annotation:annotation:1.8.1")
 }
 
 android {
-    namespace = "androidx.appfunctions.agent.runtime"
+    namespace = "com.android.extensions.appfunctions"
 }
 
 androidx {
-    name = "androidx.appfunctions:appfunctions-agent-runtime"
+    name = "Android AppFunctions Extensions Stub"
     type = LibraryType.PUBLISHED_LIBRARY
-    inceptionYear = "2024"
-    description = "Provides a set of helper classes for the agent to interact with AppFunctions."
+    inceptionYear = "2025"
+    description = "Stub implementation of the Android AppFunctions Extensions."
 }
diff --git a/appfunctions/appfunctions-stubs/com.android.extensions.appfunctions-stubs.jar b/appfunctions/appfunctions-stubs/com.android.extensions.appfunctions-stubs.jar
deleted file mode 100644
index 4b08c41..0000000
--- a/appfunctions/appfunctions-stubs/com.android.extensions.appfunctions-stubs.jar
+++ /dev/null
Binary files differ
diff --git a/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/AppFunctionException.java b/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/AppFunctionException.java
new file mode 100644
index 0000000..50f04d2
--- /dev/null
+++ b/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/AppFunctionException.java
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+package com.android.extensions.appfunctions;
+
+import android.os.Bundle;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.RestrictTo;
+
+import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** Represents an app function related errors. */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+public final class AppFunctionException extends Exception {
+    /**
+     * The caller does not have the permission to execute an app function.
+     *
+     * <p>This error is in the {@link #ERROR_CATEGORY_REQUEST_ERROR} category.
+     */
+    public static final int ERROR_DENIED = 1000;
+
+    /**
+     * The caller supplied invalid arguments to the execution request.
+     *
+     * <p>This error may be considered similar to {@link IllegalArgumentException}.
+     *
+     * <p>This error is in the {@link #ERROR_CATEGORY_REQUEST_ERROR} category.
+     */
+    public static final int ERROR_INVALID_ARGUMENT = 1001;
+
+    /**
+     * The caller tried to execute a disabled app function.
+     *
+     * <p>This error is in the {@link #ERROR_CATEGORY_REQUEST_ERROR} category.
+     */
+    public static final int ERROR_DISABLED = 1002;
+
+    /**
+     * The caller tried to execute a function that does not exist.
+     *
+     * <p>This error is in the {@link #ERROR_CATEGORY_REQUEST_ERROR} category.
+     */
+    public static final int ERROR_FUNCTION_NOT_FOUND = 1003;
+
+    /**
+     * An internal unexpected error coming from the system.
+     *
+     * <p>This error is in the {@link #ERROR_CATEGORY_SYSTEM} category.
+     */
+    public static final int ERROR_SYSTEM_ERROR = 2000;
+
+    /**
+     * The operation was cancelled. Use this error code to report that a cancellation is done after
+     * receiving a cancellation signal.
+     *
+     * <p>This error is in the {@link #ERROR_CATEGORY_SYSTEM} category.
+     */
+    public static final int ERROR_CANCELLED = 2001;
+
+    /**
+     * The operation was disallowed by enterprise policy.
+     *
+     * <p>This error is in the {@link #ERROR_CATEGORY_SYSTEM} category.
+     */
+    public static final int ERROR_ENTERPRISE_POLICY_DISALLOWED = 2002;
+
+    /**
+     * An unknown error occurred while processing the call in the AppFunctionService.
+     *
+     * <p>This error is thrown when the service is connected in the remote application but an
+     * unexpected error is thrown from the bound application.
+     *
+     * <p>This error is in the {@link #ERROR_CATEGORY_APP} category.
+     */
+    public static final int ERROR_APP_UNKNOWN_ERROR = 3000;
+
+    /**
+     * The error category is unknown.
+     *
+     * <p>This is the default value for {@link #getErrorCategory}.
+     */
+    public static final int ERROR_CATEGORY_UNKNOWN = 0;
+
+    /**
+     * The error is caused by the app requesting a function execution.
+     *
+     * <p>For example, the caller provided invalid parameters in the execution request e.g. an
+     * invalid function ID.
+     *
+     * <p>Errors in the category fall in the range 1000-1999 inclusive.
+     */
+    public static final int ERROR_CATEGORY_REQUEST_ERROR = 1;
+
+    /**
+     * The error is caused by an issue in the system.
+     *
+     * <p>For example, the AppFunctionService implementation is not found by the system.
+     *
+     * <p>Errors in the category fall in the range 2000-2999 inclusive.
+     */
+    public static final int ERROR_CATEGORY_SYSTEM = 2;
+
+    /**
+     * The error is caused by the app providing the function.
+     *
+     * <p>For example, the app crashed when the system is executing the request.
+     *
+     * <p>Errors in the category fall in the range 3000-3999 inclusive.
+     */
+    public static final int ERROR_CATEGORY_APP = 3;
+
+    public AppFunctionException(int errorCode, @Nullable String errorMessage) {
+        throw new RuntimeException("Stub!");
+    }
+
+    public AppFunctionException(
+            int errorCode, @Nullable String errorMessage, @NonNull Bundle extras) {
+        throw new RuntimeException("Stub!");
+    }
+
+    /** Returns one of the {@code ERROR} constants. */
+    @ErrorCode
+    public int getErrorCode() {
+        throw new RuntimeException("Stub!");
+    }
+
+    /** Returns the error message. */
+    @Nullable
+    public String getErrorMessage() {
+        throw new RuntimeException("Stub!");
+    }
+
+    /**
+     * Returns the error category.
+     *
+     * <p>This method categorizes errors based on their underlying cause, allowing developers to
+     * implement targeted error handling and provide more informative error messages to users. It
+     * maps ranges of error codes to specific error categories.
+     *
+     * <p>This method returns {@code ERROR_CATEGORY_UNKNOWN} if the error code does not belong to
+     * any error category.
+     *
+     * <p>See {@link ErrorCategory} for a complete list of error categories and their corresponding
+     * error code ranges.
+     */
+    @ErrorCategory
+    public int getErrorCategory() {
+        throw new RuntimeException("Stub!");
+    }
+
+    /** The extra payload of this exception. */
+    @NonNull
+    public Bundle getExtras() {
+        throw new RuntimeException("Stub!");
+    }
+
+    /**
+     * Error codes.
+     */
+    @IntDef(
+            value = {
+                    ERROR_DENIED,
+                    ERROR_APP_UNKNOWN_ERROR,
+                    ERROR_FUNCTION_NOT_FOUND,
+                    ERROR_SYSTEM_ERROR,
+                    ERROR_INVALID_ARGUMENT,
+                    ERROR_DISABLED,
+                    ERROR_CANCELLED,
+                    ERROR_ENTERPRISE_POLICY_DISALLOWED
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ErrorCode {
+    }
+
+    /**
+     * Error categories.
+     */
+    @IntDef(
+            value = {
+                    ERROR_CATEGORY_UNKNOWN,
+                    ERROR_CATEGORY_REQUEST_ERROR,
+                    ERROR_CATEGORY_APP,
+                    ERROR_CATEGORY_SYSTEM
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ErrorCategory {
+    }
+}
diff --git a/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/AppFunctionManager.java b/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/AppFunctionManager.java
new file mode 100644
index 0000000..925fd27
--- /dev/null
+++ b/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/AppFunctionManager.java
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ */
+
+package com.android.extensions.appfunctions;
+
+import android.content.Context;
+import android.os.CancellationSignal;
+import android.os.OutcomeReceiver;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.RestrictTo;
+
+import org.jspecify.annotations.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
+
+/**
+ * Provides access to app functions.
+ *
+ * <p>An app function is a piece of functionality that apps expose to the system for cross-app
+ * orchestration.
+ *
+ * <p>**Building App Functions:**
+ *
+ * <p>Most developers should build app functions through the AppFunctions SDK. This SDK library
+ * offers a more convenient and type-safe way to build app functions. The SDK provides predefined
+ * function schemas for common use cases and associated data classes for function parameters and
+ * return values. Apps only have to implement the provided interfaces. Internally, the SDK converts
+ * these data classes into {@link ExecuteAppFunctionRequest#getParameters()} and {@link
+ * ExecuteAppFunctionResponse#getResultDocument()}.
+ *
+ * <p>**Discovering App Functions:**
+ *
+ * <p>When there is a package change or the device starts up, the metadata of available functions is
+ * indexed on-device by AppSearch. AppSearch stores the indexed information as an
+ * {@code AppFunctionStaticMetadata} document. This document contains the {@code functionIdentifier}
+ * and the schema information that the app function implements. This allows other apps and the app
+ * itself to discover these functions using the AppSearch search APIs. Visibility to this metadata
+ * document is based on the packages that have visibility to the app providing the app functions.
+ * AppFunction SDK provides a convenient way to achieve this and is the preferred method.
+ *
+ * <p>**Executing App Functions:**
+ *
+ * <p>To execute an app function, the caller app can retrieve the {@code functionIdentifier} from
+ * the {@code AppFunctionStaticMetadata} document and use it to build an {@link
+ * ExecuteAppFunctionRequest}. Then, invoke {@link #executeAppFunction} with the request to execute
+ * the app function. Callers need the {@code android.permission.EXECUTE_APP_FUNCTIONS} or {@code
+ * android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} permission to execute app functions from other
+ * apps. An app can always execute its own app functions and doesn't need these permissions.
+ * AppFunction SDK provides a convenient way to achieve this and is the preferred method.
+ *
+ * <p>**Example:**
+ *
+ * <p>An assistant app is trying to fulfill the user request "Save XYZ into my note". The assistant
+ * app should first list all available app functions as {@code AppFunctionStaticMetadata} documents
+ * from AppSearch. Then, it should identify an app function that implements the {@code CreateNote}
+ * schema. Finally, the assistant app can invoke {@link #executeAppFunction} with the {@code
+ * functionIdentifier} of the chosen function.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+public final class AppFunctionManager {
+    /**
+     * The default state of the app function. Call {@link #setAppFunctionEnabled} with this to reset
+     * enabled state to the default value.
+     */
+    public static final int APP_FUNCTION_STATE_DEFAULT = 0;
+
+    /**
+     * The app function is enabled. To enable an app function, call {@link #setAppFunctionEnabled}
+     * with this value.
+     */
+    public static final int APP_FUNCTION_STATE_ENABLED = 1;
+
+    /**
+     * The app function is disabled. To disable an app function, call {@link #setAppFunctionEnabled}
+     * with this value.
+     */
+    public static final int APP_FUNCTION_STATE_DISABLED = 2;
+
+    /**
+     * The enabled state of the app function.
+     */
+    @IntDef(
+            value = {
+                    APP_FUNCTION_STATE_DEFAULT,
+                    APP_FUNCTION_STATE_ENABLED,
+                    APP_FUNCTION_STATE_DISABLED
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface EnabledState {
+    }
+
+    /**
+     * Creates an instance.
+     *
+     * @param context A {@link Context}.
+     */
+    public AppFunctionManager(@NonNull Context context) {
+        throw new RuntimeException("Stub!");
+    }
+
+    /**
+     * Executes the app function.
+     *
+     * <p>Proxies request and response to the underlying
+     * {@link AppFunctionManager#executeAppFunction}, converting the request and
+     * response in the appropriate type required by the function.
+     *
+     * <p>See {@link AppFunctionManager#executeAppFunction} for the
+     * documented behaviour of this method.
+     */
+    public void executeAppFunction(
+            @NonNull ExecuteAppFunctionRequest sidecarRequest,
+            @NonNull Executor executor,
+            @NonNull CancellationSignal cancellationSignal,
+            @NonNull
+            OutcomeReceiver<ExecuteAppFunctionResponse, AppFunctionException>
+                    callback) {
+        throw new RuntimeException("Stub!");
+    }
+
+    /**
+     * Returns a boolean through a callback, indicating whether the app function is enabled.
+     *
+     * <p>See {@link AppFunctionManager#isAppFunctionEnabled} for the documented behaviour of
+     * this method.
+     */
+    public void isAppFunctionEnabled(
+            @NonNull String functionIdentifier,
+            @NonNull String targetPackage,
+            @NonNull Executor executor,
+            @NonNull OutcomeReceiver<Boolean, Exception> callback) {
+        throw new RuntimeException("Stub!");
+    }
+
+    /**
+     * Returns a boolean through a callback, indicating whether the app function is enabled.
+     *
+     * <p>See {@link AppFunctionManager#isAppFunctionEnabled} for the documented behaviour of
+     * this method.
+     */
+    public void isAppFunctionEnabled(
+            @NonNull String functionIdentifier,
+            @NonNull Executor executor,
+            @NonNull OutcomeReceiver<Boolean, Exception> callback) {
+        throw new RuntimeException("Stub!");
+    }
+
+    /**
+     * Sets the enabled state of the app function owned by the calling package.
+     *
+     * <p>See {@link AppFunctionManager#isAppFunctionEnabled} for the documented behaviour of
+     * this method.
+     */
+    public void setAppFunctionEnabled(
+            @NonNull String functionIdentifier,
+            @EnabledState int newEnabledState,
+            @NonNull Executor executor,
+            @NonNull OutcomeReceiver<Void, Exception> callback) {
+        throw new RuntimeException("Stub!");
+    }
+}
diff --git a/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/AppFunctionService.java b/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/AppFunctionService.java
new file mode 100644
index 0000000..b32dc7f
--- /dev/null
+++ b/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/AppFunctionService.java
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+package com.android.extensions.appfunctions;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.CancellationSignal;
+import android.os.IBinder;
+import android.os.OutcomeReceiver;
+
+import androidx.annotation.MainThread;
+import androidx.annotation.RestrictTo;
+
+import org.jspecify.annotations.NonNull;
+import org.jspecify.annotations.Nullable;
+
+/**
+ * Abstract base class to provide app functions to the system.
+ *
+ * <p>Include the following in the manifest:
+ *
+ * <pre>
+ * {@literal
+ * <service android:name=".YourService"
+ *       android:permission="android.permission.BIND_APP_FUNCTION_SERVICE">
+ *    <intent-filter>
+ *      <action android:name="android.app.appfunctions.AppFunctionService" />
+ *    </intent-filter>
+ * </service>
+ * }
+ * </pre>
+ *
+ * @see AppFunctionManager
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+public abstract class AppFunctionService extends Service {
+    /**
+     * The permission to only allow system access to the functions through the system.
+     */
+    @NonNull
+    public static final String BIND_APP_FUNCTION_SERVICE =
+            "android.permission.BIND_APP_FUNCTION_SERVICE";
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service. To be supported, the
+     * service must also require the {@link #BIND_APP_FUNCTION_SERVICE} permission so that other
+     * applications can not abuse it.
+     */
+    @NonNull
+    public static final String SERVICE_INTERFACE = "android.app.appfunctions.AppFunctionService";
+
+    @NonNull
+    @Override
+    public final IBinder onBind(@Nullable Intent intent) {
+        throw new RuntimeException("Stub!");
+    }
+
+    /**
+     * Called by the system to execute a specific app function.
+     *
+     * <p>This method is the entry point for handling all app function requests in an app. When the
+     * system needs your AppFunctionService to perform a function, it will invoke this method.
+     *
+     * <p>Each function you've registered is identified by a unique identifier. This identifier
+     * doesn't need to be globally unique, but it must be unique within your app. For example, a
+     * function to order food could be identified as "orderFood". In most cases, this identifier is
+     * automatically generated by the AppFunctions SDK.
+     *
+     * <p>You can determine which function to execute by calling {@link
+     * ExecuteAppFunctionRequest#getFunctionIdentifier()}. This allows your service to route the
+     * incoming request to the appropriate logic for handling the specific function.
+     *
+     * <p>This method is always triggered in the main thread. You should run heavy tasks on a worker
+     * thread and dispatch the result with the given callback. You should always report back the
+     * result using the callback, no matter if the execution was successful or not.
+     *
+     * <p>This method also accepts a {@link CancellationSignal} that the app should listen to cancel
+     * the execution of function if requested by the system.
+     *
+     * @param request            The function execution request.
+     * @param callingPackage     The package name of the app that is requesting the execution.
+     * @param cancellationSignal A signal to cancel the execution.
+     * @param callback           A callback to report back the result or error.
+     */
+    @MainThread
+    public abstract void onExecuteFunction(
+            @NonNull ExecuteAppFunctionRequest request,
+            @NonNull String callingPackage,
+            @NonNull CancellationSignal cancellationSignal,
+            @NonNull OutcomeReceiver<ExecuteAppFunctionResponse, AppFunctionException> callback);
+}
diff --git a/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/ExecuteAppFunctionRequest.java b/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/ExecuteAppFunctionRequest.java
new file mode 100644
index 0000000..5ad74f5
--- /dev/null
+++ b/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/ExecuteAppFunctionRequest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+package com.android.extensions.appfunctions;
+
+import android.app.appsearch.GenericDocument;
+import android.os.Bundle;
+
+import androidx.annotation.RestrictTo;
+
+import org.jspecify.annotations.NonNull;
+
+/**
+ * A request to execute an app function.
+ *
+ * <p>The {@link ExecuteAppFunctionRequest#getParameters()} contains the parameters for the function
+ * to be executed in a GenericDocument. Structured classes defined in the AppFunction SDK can be
+ * converted into GenericDocuments.
+ *
+ * <p>The {@link ExecuteAppFunctionRequest#getExtras()} provides any extra metadata for the request.
+ * Structured APIs can be exposed in the SDK by packing and unpacking this Bundle.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+public final class ExecuteAppFunctionRequest {
+    /** Returns the package name of the app that hosts the function. */
+    @NonNull
+    public String getTargetPackageName() {
+        throw new RuntimeException("Stub!");
+    }
+
+    /**
+     * Returns the unique string identifier of the app function to be executed.
+     *
+     * <p>When there is a package change or the device starts up, the metadata of available
+     * functions is indexed by AppSearch. AppSearch stores the indexed information as {@code
+     * AppFunctionStaticMetadata} document.
+     *
+     * <p>The ID can be obtained by querying the {@code AppFunctionStaticMetadata} documents from
+     * AppSearch.
+     *
+     * <p>If the {@code functionId} provided is invalid, the caller will get an invalid argument
+     * response.
+     */
+    @NonNull
+    public String getFunctionIdentifier() {
+        throw new RuntimeException("Stub!");
+    }
+
+    /**
+     * Returns the function parameters. The key is the parameter name, and the value is the
+     * parameter value.
+     *
+     * <p>The {@link GenericDocument} may have missing parameters. Developers are advised to
+     * implement defensive handling measures.
+     *
+     * <p>Similar to {@link #getFunctionIdentifier()} the parameters required by a function can be
+     * obtained by querying AppSearch for the corresponding {@code AppFunctionStaticMetadata}. This
+     * metadata will contain enough information for the caller to resolve the required parameters
+     * either using information from the metadata itself or using the AppFunction SDK for function
+     * callers.
+     */
+    @NonNull
+    public GenericDocument getParameters() {
+        throw new RuntimeException("Stub!");
+    }
+
+    /** Returns the additional data relevant to this function execution. */
+    @NonNull
+    public Bundle getExtras() {
+        throw new RuntimeException("Stub!");
+    }
+
+    /** Builder for {@link ExecuteAppFunctionRequest}. */
+    public static final class Builder {
+        public Builder(@NonNull String targetPackageName, @NonNull String functionIdentifier) {
+            throw new RuntimeException("Stub!");
+        }
+
+        /** Sets the additional data relevant to this function execution. */
+        @NonNull
+        public Builder setExtras(@NonNull Bundle extras) {
+            throw new RuntimeException("Stub!");
+        }
+
+        /** Sets the function parameters. */
+        @NonNull
+        public Builder setParameters(@NonNull GenericDocument parameters) {
+            throw new RuntimeException("Stub!");
+        }
+
+        /** Builds the {@link ExecuteAppFunctionRequest}. */
+        @NonNull
+        public ExecuteAppFunctionRequest build() {
+            throw new RuntimeException("Stub!");
+        }
+    }
+}
diff --git a/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/ExecuteAppFunctionResponse.java b/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/ExecuteAppFunctionResponse.java
new file mode 100644
index 0000000..07f6e46
--- /dev/null
+++ b/appfunctions/appfunctions-stubs/src/main/java/com/android/extensions/appfunctions/ExecuteAppFunctionResponse.java
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+package com.android.extensions.appfunctions;
+
+import android.app.appsearch.GenericDocument;
+import android.os.Bundle;
+
+import androidx.annotation.RestrictTo;
+
+import org.jspecify.annotations.NonNull;
+
+/**
+ * The response to an app function execution.
+ *
+ * <p>The {@link ExecuteAppFunctionResponse#getResultDocument()} contains the function's return
+ * value as a GenericDocument. This can be converted back into a structured class using the
+ * AppFunction SDK.
+ *
+ * <p>The {@link ExecuteAppFunctionResponse#getExtras()} provides any extra metadata returned by the
+ * function. The AppFunction SDK can expose structured APIs by packing and unpacking this Bundle.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
+public final class ExecuteAppFunctionResponse {
+    /**
+     * The name of the property that stores the function return value within the {@code
+     * resultDocument}.
+     *
+     * <p>See {@link GenericDocument#getProperty(String)} for more information.
+     *
+     * <p>If the function returns {@code void} or throws an error, the {@code resultDocument} will
+     * be empty {@link GenericDocument}.
+     *
+     * <p>If the {@code resultDocument} is empty, {@link GenericDocument#getProperty(String)} will
+     * return {@code null}.
+     *
+     * <p>See {@link #getResultDocument} for more information on extracting the return value.
+     */
+    public static final String PROPERTY_RETURN_VALUE = "androidAppfunctionsReturnValue";
+
+    /**
+     * @param resultDocument The return value of the executed function.
+     */
+    public ExecuteAppFunctionResponse(@NonNull GenericDocument resultDocument) {
+        throw new RuntimeException("Stub!");
+    }
+
+    /**
+     * @param resultDocument The return value of the executed function.
+     * @param extras         The additional metadata for this function execution response.
+     */
+    public ExecuteAppFunctionResponse(
+            @NonNull GenericDocument resultDocument, @NonNull Bundle extras) {
+        throw new RuntimeException("Stub!");
+    }
+
+    /**
+     * Returns a generic document containing the return value of the executed function.
+     *
+     * <p>The {@link #PROPERTY_RETURN_VALUE} key can be used to obtain the return value.
+     *
+     * <p>Sample code for extracting the return value:
+     *
+     * <pre>
+     *     GenericDocument resultDocument = response.getResultDocument();
+     *     Object returnValue = resultDocument.getProperty(PROPERTY_RETURN_VALUE);
+     *     if (returnValue != null) {
+     *       // Cast returnValue to expected type, or use {@link GenericDocument#getPropertyString},
+     *       // {@link GenericDocument#getPropertyLong} etc.
+     *       // Do something with the returnValue
+     *     }
+     * </pre>
+     *
+     * @see AppFunctionManager on how to determine the expected function return.
+     */
+    @NonNull
+    public GenericDocument getResultDocument() {
+        throw new RuntimeException("Stub!");
+    }
+
+    /** Returns the additional metadata for this function execution response. */
+    @NonNull
+    public Bundle getExtras() {
+        throw new RuntimeException("Stub!");
+    }
+}
diff --git a/appsearch/appsearch-builtin-types/api/1.1.0-beta01.txt b/appsearch/appsearch-builtin-types/api/1.1.0-beta01.txt
index 911bcf5..eb040cf 100644
--- a/appsearch/appsearch-builtin-types/api/1.1.0-beta01.txt
+++ b/appsearch/appsearch-builtin-types/api/1.1.0-beta01.txt
@@ -126,6 +126,22 @@
     method public androidx.appsearch.builtintypes.ContactPoint.Builder setUrl(String?);
   }
 
+  @SuppressCompatibility @RequiresFeature(enforcement="androidx.appsearch.app.Features#isFeatureSupported", name=androidx.appsearch.app.Features.VERBATIM_SEARCH) @androidx.appsearch.annotation.Document(name="builtin:GlobalSearchApplicationInfo") @androidx.appsearch.app.ExperimentalAppSearchApi public final class GlobalSearchApplicationInfo {
+    method public int getApplicationType();
+    method public String getId();
+    method public String getNamespace();
+    method public java.util.List<java.lang.String> getSchemaTypes();
+    field public static final int APPLICATION_TYPE_CONSUMER = 1; // 0x1
+    field public static final int APPLICATION_TYPE_PRODUCER = 0; // 0x0
+  }
+
+  public static final class GlobalSearchApplicationInfo.Builder {
+    ctor public GlobalSearchApplicationInfo.Builder(String, String, int);
+    method public androidx.appsearch.builtintypes.GlobalSearchApplicationInfo build();
+    method public androidx.appsearch.builtintypes.GlobalSearchApplicationInfo.Builder setDocumentClasses(java.util.List<java.lang.Class<? extends java.lang.Object!>>) throws androidx.appsearch.exceptions.AppSearchException;
+    method public androidx.appsearch.builtintypes.GlobalSearchApplicationInfo.Builder setSchemaTypes(java.util.List<java.lang.String>);
+  }
+
   @androidx.appsearch.annotation.Document(name="builtin:ImageObject") public final class ImageObject extends androidx.appsearch.builtintypes.Thing {
     method public byte[]? getBytes();
     method public java.util.List<androidx.appsearch.builtintypes.properties.Keyword!> getKeywords();
diff --git a/appsearch/appsearch-builtin-types/api/current.txt b/appsearch/appsearch-builtin-types/api/current.txt
index 911bcf5..eb040cf 100644
--- a/appsearch/appsearch-builtin-types/api/current.txt
+++ b/appsearch/appsearch-builtin-types/api/current.txt
@@ -126,6 +126,22 @@
     method public androidx.appsearch.builtintypes.ContactPoint.Builder setUrl(String?);
   }
 
+  @SuppressCompatibility @RequiresFeature(enforcement="androidx.appsearch.app.Features#isFeatureSupported", name=androidx.appsearch.app.Features.VERBATIM_SEARCH) @androidx.appsearch.annotation.Document(name="builtin:GlobalSearchApplicationInfo") @androidx.appsearch.app.ExperimentalAppSearchApi public final class GlobalSearchApplicationInfo {
+    method public int getApplicationType();
+    method public String getId();
+    method public String getNamespace();
+    method public java.util.List<java.lang.String> getSchemaTypes();
+    field public static final int APPLICATION_TYPE_CONSUMER = 1; // 0x1
+    field public static final int APPLICATION_TYPE_PRODUCER = 0; // 0x0
+  }
+
+  public static final class GlobalSearchApplicationInfo.Builder {
+    ctor public GlobalSearchApplicationInfo.Builder(String, String, int);
+    method public androidx.appsearch.builtintypes.GlobalSearchApplicationInfo build();
+    method public androidx.appsearch.builtintypes.GlobalSearchApplicationInfo.Builder setDocumentClasses(java.util.List<java.lang.Class<? extends java.lang.Object!>>) throws androidx.appsearch.exceptions.AppSearchException;
+    method public androidx.appsearch.builtintypes.GlobalSearchApplicationInfo.Builder setSchemaTypes(java.util.List<java.lang.String>);
+  }
+
   @androidx.appsearch.annotation.Document(name="builtin:ImageObject") public final class ImageObject extends androidx.appsearch.builtintypes.Thing {
     method public byte[]? getBytes();
     method public java.util.List<androidx.appsearch.builtintypes.properties.Keyword!> getKeywords();
diff --git a/appsearch/appsearch-builtin-types/api/restricted_1.1.0-beta01.txt b/appsearch/appsearch-builtin-types/api/restricted_1.1.0-beta01.txt
index c61ebfd..3d0db8d 100644
--- a/appsearch/appsearch-builtin-types/api/restricted_1.1.0-beta01.txt
+++ b/appsearch/appsearch-builtin-types/api/restricted_1.1.0-beta01.txt
@@ -128,6 +128,22 @@
     method public androidx.appsearch.builtintypes.ContactPoint.Builder setUrl(String?);
   }
 
+  @SuppressCompatibility @RequiresFeature(enforcement="androidx.appsearch.app.Features#isFeatureSupported", name=androidx.appsearch.app.Features.VERBATIM_SEARCH) @androidx.appsearch.annotation.Document(name="builtin:GlobalSearchApplicationInfo") @androidx.appsearch.app.ExperimentalAppSearchApi public final class GlobalSearchApplicationInfo {
+    method public int getApplicationType();
+    method public String getId();
+    method public String getNamespace();
+    method public java.util.List<java.lang.String> getSchemaTypes();
+    field public static final int APPLICATION_TYPE_CONSUMER = 1; // 0x1
+    field public static final int APPLICATION_TYPE_PRODUCER = 0; // 0x0
+  }
+
+  public static final class GlobalSearchApplicationInfo.Builder {
+    ctor public GlobalSearchApplicationInfo.Builder(String, String, int);
+    method public androidx.appsearch.builtintypes.GlobalSearchApplicationInfo build();
+    method public androidx.appsearch.builtintypes.GlobalSearchApplicationInfo.Builder setDocumentClasses(java.util.List<java.lang.Class<? extends java.lang.Object!>>) throws androidx.appsearch.exceptions.AppSearchException;
+    method public androidx.appsearch.builtintypes.GlobalSearchApplicationInfo.Builder setSchemaTypes(java.util.List<java.lang.String>);
+  }
+
   @androidx.appsearch.annotation.Document(name="builtin:ImageObject") public final class ImageObject extends androidx.appsearch.builtintypes.Thing {
     method public byte[]? getBytes();
     method public java.util.List<androidx.appsearch.builtintypes.properties.Keyword!> getKeywords();
diff --git a/appsearch/appsearch-builtin-types/api/restricted_current.txt b/appsearch/appsearch-builtin-types/api/restricted_current.txt
index c61ebfd..3d0db8d 100644
--- a/appsearch/appsearch-builtin-types/api/restricted_current.txt
+++ b/appsearch/appsearch-builtin-types/api/restricted_current.txt
@@ -128,6 +128,22 @@
     method public androidx.appsearch.builtintypes.ContactPoint.Builder setUrl(String?);
   }
 
+  @SuppressCompatibility @RequiresFeature(enforcement="androidx.appsearch.app.Features#isFeatureSupported", name=androidx.appsearch.app.Features.VERBATIM_SEARCH) @androidx.appsearch.annotation.Document(name="builtin:GlobalSearchApplicationInfo") @androidx.appsearch.app.ExperimentalAppSearchApi public final class GlobalSearchApplicationInfo {
+    method public int getApplicationType();
+    method public String getId();
+    method public String getNamespace();
+    method public java.util.List<java.lang.String> getSchemaTypes();
+    field public static final int APPLICATION_TYPE_CONSUMER = 1; // 0x1
+    field public static final int APPLICATION_TYPE_PRODUCER = 0; // 0x0
+  }
+
+  public static final class GlobalSearchApplicationInfo.Builder {
+    ctor public GlobalSearchApplicationInfo.Builder(String, String, int);
+    method public androidx.appsearch.builtintypes.GlobalSearchApplicationInfo build();
+    method public androidx.appsearch.builtintypes.GlobalSearchApplicationInfo.Builder setDocumentClasses(java.util.List<java.lang.Class<? extends java.lang.Object!>>) throws androidx.appsearch.exceptions.AppSearchException;
+    method public androidx.appsearch.builtintypes.GlobalSearchApplicationInfo.Builder setSchemaTypes(java.util.List<java.lang.String>);
+  }
+
   @androidx.appsearch.annotation.Document(name="builtin:ImageObject") public final class ImageObject extends androidx.appsearch.builtintypes.Thing {
     method public byte[]? getBytes();
     method public java.util.List<androidx.appsearch.builtintypes.properties.Keyword!> getKeywords();
diff --git a/appsearch/appsearch-builtin-types/src/androidTest/java/androidx/appsearch/builtintypes/GlobalSearchApplicationInfoTest.java b/appsearch/appsearch-builtin-types/src/androidTest/java/androidx/appsearch/builtintypes/GlobalSearchApplicationInfoTest.java
new file mode 100644
index 0000000..581d29c
--- /dev/null
+++ b/appsearch/appsearch-builtin-types/src/androidTest/java/androidx/appsearch/builtintypes/GlobalSearchApplicationInfoTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.appsearch.builtintypes;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Test;
+
+public class GlobalSearchApplicationInfoTest {
+    @Test
+    public void testBuilder_defaultValues() {
+        GlobalSearchApplicationInfo appInfo = new GlobalSearchApplicationInfo.Builder(
+                "namespace", "id", GlobalSearchApplicationInfo.APPLICATION_TYPE_CONSUMER)
+                .build();
+        assertThat(appInfo.getNamespace()).isEqualTo("namespace");
+        assertThat(appInfo.getId()).isEqualTo("id");
+        assertThat(appInfo.getApplicationType())
+                .isEqualTo(GlobalSearchApplicationInfo.APPLICATION_TYPE_CONSUMER);
+        assertThat(appInfo.getSchemaTypes()).isEmpty();
+    }
+
+    @Test
+    public void testBuilder_setAllValues() {
+        GlobalSearchApplicationInfo appInfo = new GlobalSearchApplicationInfo.Builder(
+                "namespace", "id", GlobalSearchApplicationInfo.APPLICATION_TYPE_PRODUCER)
+                .setSchemaTypes(ImmutableList.of("Type1", "Type2"))
+                .build();
+        assertThat(appInfo.getNamespace()).isEqualTo("namespace");
+        assertThat(appInfo.getId()).isEqualTo("id");
+        assertThat(appInfo.getApplicationType())
+                .isEqualTo(GlobalSearchApplicationInfo.APPLICATION_TYPE_PRODUCER);
+        assertThat(appInfo.getSchemaTypes()).containsExactly("Type1", "Type2").inOrder();
+    }
+
+    @Test
+    public void testBuilder_setDocumentClasses() throws Exception {
+        GlobalSearchApplicationInfo appInfo = new GlobalSearchApplicationInfo.Builder(
+                "namespace", "id", GlobalSearchApplicationInfo.APPLICATION_TYPE_PRODUCER)
+                .setSchemaTypes(ImmutableList.of("Type1", "Type2"))
+                .setSchemaTypes(ImmutableList.of("Type3", "Type4"))
+                .setDocumentClasses(ImmutableList.of(Person.class, MobileApplication.class))
+                .build();
+        assertThat(appInfo.getNamespace()).isEqualTo("namespace");
+        assertThat(appInfo.getId()).isEqualTo("id");
+        assertThat(appInfo.getApplicationType())
+                .isEqualTo(GlobalSearchApplicationInfo.APPLICATION_TYPE_PRODUCER);
+        assertThat(appInfo.getSchemaTypes())
+                .containsExactly("builtin:Person", "builtin:MobileApplication").inOrder();
+    }
+
+    @Test
+    public void testBuilder_setNull() {
+        GlobalSearchApplicationInfo.Builder builder = new GlobalSearchApplicationInfo.Builder(
+                "namespace", "id", GlobalSearchApplicationInfo.APPLICATION_TYPE_PRODUCER);
+        assertThrows(NullPointerException.class, () -> builder.setSchemaTypes(null));
+        assertThrows(NullPointerException.class, () -> builder.setDocumentClasses(null));
+        assertThrows(
+                NullPointerException.class,
+                () -> builder.setSchemaTypes(ImmutableList.of("Type1", null, "Type2")));
+        assertThrows(
+                NullPointerException.class,
+                () -> builder.setDocumentClasses(
+                        ImmutableList.of(Person.class, null, MobileApplication.class)));
+    }
+
+    @Test
+    public void testBuilder_modifiedAfterBuild_doesNotAffectBuiltObjects() {
+        GlobalSearchApplicationInfo.Builder builder = new GlobalSearchApplicationInfo.Builder(
+                "namespace", "id", GlobalSearchApplicationInfo.APPLICATION_TYPE_CONSUMER);
+
+        // First build with default values
+        GlobalSearchApplicationInfo appInfo1 = builder.build();
+        assertThat(appInfo1.getNamespace()).isEqualTo("namespace");
+        assertThat(appInfo1.getId()).isEqualTo("id");
+        assertThat(appInfo1.getApplicationType())
+                .isEqualTo(GlobalSearchApplicationInfo.APPLICATION_TYPE_CONSUMER);
+        assertThat(appInfo1.getSchemaTypes()).isEmpty();
+
+        // Modify the builder and build again
+        GlobalSearchApplicationInfo appInfo2 = builder
+                .setSchemaTypes(ImmutableList.of("Type1", "Type2"))
+                .build();
+
+        // Check the second object has the new values
+        assertThat(appInfo2.getNamespace()).isEqualTo("namespace");
+        assertThat(appInfo2.getId()).isEqualTo("id");
+        assertThat(appInfo2.getApplicationType())
+                .isEqualTo(GlobalSearchApplicationInfo.APPLICATION_TYPE_CONSUMER);
+        assertThat(appInfo2.getSchemaTypes()).containsExactly("Type1", "Type2").inOrder();
+
+        // Check the first object is not affected
+        assertThat(appInfo1.getNamespace()).isEqualTo("namespace");
+        assertThat(appInfo1.getId()).isEqualTo("id");
+        assertThat(appInfo1.getApplicationType())
+                .isEqualTo(GlobalSearchApplicationInfo.APPLICATION_TYPE_CONSUMER);
+        assertThat(appInfo1.getSchemaTypes()).isEmpty();
+    }
+}
diff --git a/appsearch/appsearch-builtin-types/src/main/java/androidx/appsearch/app/ShortcutAdapter.java b/appsearch/appsearch-builtin-types/src/main/java/androidx/appsearch/app/ShortcutAdapter.java
index e01597b..b7af7db 100644
--- a/appsearch/appsearch-builtin-types/src/main/java/androidx/appsearch/app/ShortcutAdapter.java
+++ b/appsearch/appsearch-builtin-types/src/main/java/androidx/appsearch/app/ShortcutAdapter.java
@@ -102,6 +102,7 @@
      * published. i.e. Any shortcut returned from queries toward
      * {@link androidx.core.content.pm.ShortcutManagerCompat} would not carry any document at all.
      *
+     * @param context the context used to provide the package and resources
      * @param document a document object annotated with
      *                 {@link androidx.appsearch.annotation.Document} that carries structured
      *                 data in a pre-defined format.
diff --git a/appsearch/appsearch-builtin-types/src/main/java/androidx/appsearch/builtintypes/GlobalSearchApplicationInfo.java b/appsearch/appsearch-builtin-types/src/main/java/androidx/appsearch/builtintypes/GlobalSearchApplicationInfo.java
new file mode 100644
index 0000000..d2ee813
--- /dev/null
+++ b/appsearch/appsearch-builtin-types/src/main/java/androidx/appsearch/builtintypes/GlobalSearchApplicationInfo.java
@@ -0,0 +1,226 @@
+/*
+ * 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.appsearch.builtintypes;
+
+import static androidx.appsearch.app.AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS;
+import static androidx.appsearch.app.AppSearchSchema.StringPropertyConfig.TOKENIZER_TYPE_VERBATIM;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.RequiresFeature;
+import androidx.annotation.RestrictTo;
+import androidx.appsearch.annotation.Document;
+import androidx.appsearch.app.DocumentClassFactory;
+import androidx.appsearch.app.DocumentClassFactoryRegistry;
+import androidx.appsearch.app.ExperimentalAppSearchApi;
+import androidx.appsearch.app.Features;
+import androidx.appsearch.app.SearchResult;
+import androidx.appsearch.exceptions.AppSearchException;
+import androidx.core.util.Preconditions;
+
+import org.jspecify.annotations.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * An indexable document class which indicates that an app is capable of producing, or capable of
+ * consuming, certain AppSearch schema types.
+ *
+ * <p>This class represents optional metadata about an app's data interchange, and is not part of
+ * the schema.org types that model object schemas.
+ *
+ * <p>A producer can check for the existence of ready consumers by querying for
+ * {@link GlobalSearchApplicationInfo} documents that ask for a type that producer produces.
+ * Once a matching {@link androidx.appsearch.app.SearchResult} is retrieved, the producer can set a
+ * schema with access permissions granted to the package that owns this
+ * {@link GlobalSearchApplicationInfo} and index documents of that type.
+ *
+ * <p>The package name of the app which is producing or consuming data is not part of this class --
+ * it can be obtained from {@link SearchResult#getPackageName()}.
+ */
+@ExperimentalAppSearchApi
+@RequiresFeature(
+        enforcement = "androidx.appsearch.app.Features#isFeatureSupported",
+        name = Features.VERBATIM_SEARCH)
+@Document(name = "builtin:GlobalSearchApplicationInfo")
+public final class GlobalSearchApplicationInfo {
+    /**
+     * Used with {@link #getApplicationType()} to indicate this application is ready and able to
+     * index a certain type of data.
+     */
+    public static final int APPLICATION_TYPE_PRODUCER = 0;
+
+    /**
+     * Used with {@link #getApplicationType()} to indicate this application is able and interested
+     * in querying a certain type of data.
+     */
+    public static final int APPLICATION_TYPE_CONSUMER = 1;
+
+    @IntDef(
+            value = {
+                APPLICATION_TYPE_PRODUCER,
+                APPLICATION_TYPE_CONSUMER,
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public @interface ApplicationType {}
+
+    @Document.Namespace private final String mNamespace;
+
+    @Document.Id private final String mId;
+
+    @Document.LongProperty @ApplicationType private final int mApplicationType;
+
+    /**
+     * The list of all unprefixed schema types this app can produce (if #mApplicationType ==
+     * {@link #APPLICATION_TYPE_PRODUCER}) or consume (if #mApplicationType ==
+     * {@link #APPLICATION_TYPE_CONSUMER}).
+     */
+    @Document.StringProperty(
+            indexingType = INDEXING_TYPE_EXACT_TERMS,
+            tokenizerType = TOKENIZER_TYPE_VERBATIM)
+    private final List<String> mSchemaTypes;
+
+    /** Constructs a new {@link GlobalSearchApplicationInfo}. */
+    GlobalSearchApplicationInfo(
+            @NonNull String namespace,
+            @NonNull String id,
+            @ApplicationType int applicationType,
+            @NonNull List<String> schemaTypes) {
+        mNamespace = Preconditions.checkNotNull(namespace);
+        mId = Preconditions.checkNotNull(id);
+        mApplicationType = applicationType;
+        mSchemaTypes = Collections.unmodifiableList(schemaTypes);
+    }
+
+    /** Returns the namespace (or logical grouping) for this {@link GlobalSearchApplicationInfo}. */
+    public @NonNull String getNamespace() {
+        return mNamespace;
+    }
+
+    /** Returns the unique identifier for this {@link GlobalSearchApplicationInfo}. */
+    public @NonNull String getId() {
+        return mId;
+    }
+
+    /**
+     * Returns whether this app is interested in either producing or consuming the schema types
+     * listed in {@link #getSchemaTypes()}.
+     */
+    @ApplicationType
+    public int getApplicationType() {
+        return mApplicationType;
+    }
+
+    /**
+     * Returns the list of schema type names this app is capable of producing (if {@link
+     * #getApplicationType()} is {@link #APPLICATION_TYPE_PRODUCER}) or interested in consuming (if
+     * {@link #getApplicationType() is #APPLICATION_TYPE_CONSUMER}).
+     */
+    public @NonNull List<@NonNull String> getSchemaTypes() {
+        return mSchemaTypes;
+    }
+
+    /** Builder class for {@link GlobalSearchApplicationInfo}. */
+    public static final class Builder {
+        private final String mNamespace;
+        private final String mId;
+        private final @ApplicationType int mApplicationType;
+        private List<String> mSchemaTypes = Collections.emptyList();
+
+        /**
+         * Constructs a new {@link Builder}.
+         *
+         * @param namespace       an arbitrary string corresponding to a logical grouping for this
+         *                        {@link GlobalSearchApplicationInfo}. All AppSearch documents
+         *                        must have a namespace.
+         * @param id              the identifier for this GlobalSearchApplicationInfo. AppSearch
+         *                        IDs are unique within their combination of package, database and
+         *                        namespace.
+         * @param applicationType whether the application is capable of producing, or interested in
+         *                        consuming, the schema types configured by {@link #setSchemaTypes}
+         *                        or {@link #setDocumentClasses}.
+         */
+        public Builder(
+                @NonNull String namespace,
+                @NonNull String id,
+                @ApplicationType int applicationType) {
+            mNamespace = Preconditions.checkNotNull(namespace);
+            mId = Preconditions.checkNotNull(id);
+            mApplicationType = Preconditions.checkArgumentInRange(
+                    applicationType,
+                    APPLICATION_TYPE_PRODUCER,
+                    APPLICATION_TYPE_CONSUMER,
+                    "applicationType");
+        }
+
+        /**
+         * Sets the list of schema type names this app is capable of producing (if {@link
+         * #getApplicationType()} is {@link #APPLICATION_TYPE_PRODUCER}) or interested in consuming
+         * (if {@link #getApplicationType() is #APPLICATION_TYPE_CONSUMER}).
+         *
+         * <p>This method is equivalent to {@link #setDocumentClasses} but accepts schema name
+         * strings instead of extracting schema information from document classes.
+         */
+        public @NonNull Builder setSchemaTypes(@NonNull List<@NonNull String> schemaTypes) {
+            Preconditions.checkNotNull(schemaTypes);
+            for (int i = 0; i < schemaTypes.size(); i++) {
+                Preconditions.checkNotNull(schemaTypes.get(i));
+            }
+            mSchemaTypes = schemaTypes;
+            return this;
+        }
+
+        /**
+         * Sets the list of schemas this app is capable of producing (if {@link
+         * #getApplicationType()} is {@link #APPLICATION_TYPE_PRODUCER}) or interested in consuming
+         * (if {@link #getApplicationType() is #APPLICATION_TYPE_CONSUMER}).
+         *
+         * <p>This method is equivalent to {@link #setSchemaTypes} but accepts document classes
+         * instead of schema name strings.
+         *
+         * @param schemaClasses A list of classes annotated with the @{@link Document} annotation
+         *                      which correspond to the schemas this app produces or consumes.
+         * @throws AppSearchException if the schemaClasses are not @{@link Document}-annotated
+         *                            classes or extraction of the schema name fails.
+         */
+        @SuppressWarnings("MissingGetterMatchingBuilder")  // See getSchemaTypes
+        public @NonNull Builder setDocumentClasses(@NonNull List<@NonNull Class<?>> schemaClasses)
+                throws AppSearchException {
+            Preconditions.checkNotNull(schemaClasses);
+            DocumentClassFactoryRegistry documentClassFactoryRegistry =
+                    DocumentClassFactoryRegistry.getInstance();
+            List<String> schemaTypes = new ArrayList<>(schemaClasses.size());
+            for (int i = 0; i < schemaClasses.size(); i++) {
+                Class<?> schemaClass = Preconditions.checkNotNull(schemaClasses.get(i));
+                DocumentClassFactory<?> documentClassFactory =
+                        documentClassFactoryRegistry.getOrCreateFactory(schemaClass);
+                schemaTypes.add(documentClassFactory.getSchemaName());
+            }
+            mSchemaTypes = schemaTypes;
+            return this;
+        }
+
+        /** Constructs a new {@link GlobalSearchApplicationInfo}. */
+        public @NonNull GlobalSearchApplicationInfo build() {
+            return new GlobalSearchApplicationInfo(mNamespace, mId, mApplicationType, mSchemaTypes);
+        }
+    }
+}
diff --git a/appsearch/appsearch-local-storage/src/main/java/androidx/appsearch/localstorage/LocalStorage.java b/appsearch/appsearch-local-storage/src/main/java/androidx/appsearch/localstorage/LocalStorage.java
index ffd1d28..5938407 100644
--- a/appsearch/appsearch-local-storage/src/main/java/androidx/appsearch/localstorage/LocalStorage.java
+++ b/appsearch/appsearch-local-storage/src/main/java/androidx/appsearch/localstorage/LocalStorage.java
@@ -118,6 +118,7 @@
              *
              * <p>The database name cannot contain {@code '/'}.
              *
+             * @param context The context used as the parent of the created SearchContext
              * @param databaseName The name of the database.
              * @throws IllegalArgumentException if the databaseName contains {@code '/'}.
              */
diff --git a/appsearch/appsearch-platform-storage/src/main/java/androidx/appsearch/platformstorage/FeaturesImpl.java b/appsearch/appsearch-platform-storage/src/main/java/androidx/appsearch/platformstorage/FeaturesImpl.java
index 78853af..6def22a8 100644
--- a/appsearch/appsearch-platform-storage/src/main/java/androidx/appsearch/platformstorage/FeaturesImpl.java
+++ b/appsearch/appsearch-platform-storage/src/main/java/androidx/appsearch/platformstorage/FeaturesImpl.java
@@ -41,6 +41,11 @@
     @Override
     @OptIn(markerClass = ExperimentalAppSearchApi.class)
     public boolean isFeatureSupported(@NonNull String feature) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+            // AppSearch landed in platform in S, however it was not updatable via mainline until T.
+            // So all features here are not available below T.
+            return false;
+        }
         switch (feature) {
             // Android T Features
             case Features.ADD_PERMISSIONS_AND_GET_VISIBILITY:
@@ -94,17 +99,21 @@
             case Features.ENTERPRISE_GLOBAL_SEARCH_SESSION:
                 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM;
 
-            // TODO(b/275592563): rearrange this part after fixing the merge conflict.
-            // Beyond Android V Features
+            // M-2024-11 Features
+            case Features.INDEXER_MOBILE_APPLICATIONS:
+                // For devices that receive mainline updates, this will be available in M-2024-11,
+                // and in B for devices that don't receive mainline updates.
+                return AppSearchVersionUtil.isAtLeastB()
+                        || AppSearchVersionUtil.getAppSearchVersionCode(mContext)
+                        >= AppSearchVersionUtil.APPSEARCH_M2024_11_VERSION_CODE;
+
+            // Pending Android B Features
             case Features.SCHEMA_EMBEDDING_PROPERTY_CONFIG:
                 // TODO(b/326656531) : Update when feature is ready in service-appsearch.
                 // fall through
             case Features.SCHEMA_EMBEDDING_QUANTIZATION:
                 // TODO(b/359959345) : Update when feature is ready in service-appsearch.
                 // fall through
-            case Features.SCHEMA_SET_DESCRIPTION:
-                // TODO(b/326987971) : Update when feature is ready in service-appsearch.
-                // fall through
             case Features.SEARCH_SPEC_SEARCH_STRING_PARAMETERS:
                 // TODO(b/332620561) : Update when feature is ready in service-appsearch.
                 // fall through
@@ -122,16 +131,15 @@
                 // fall through
             case Features.SEARCH_RESULT_PARENT_TYPES:
                 // TODO(b/371610934) : Update when feature is ready in service-appsearch.
-                // fall through
-            case Features.SCHEMA_STRING_PROPERTY_CONFIG_DELETE_PROPAGATION_TYPE_PROPAGATE_FROM:
-                // TODO(b/376913014) : Update when feature is ready in service-appsearch.
-                // fall through
                 return false;
 
-            // Android B Features
-            case Features.INDEXER_MOBILE_APPLICATIONS:
-                // TODO(b/275592563) : Update when B version code is available
-                return Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM;
+            // Beyond Android B Features
+            case Features.SCHEMA_SET_DESCRIPTION:
+                // TODO(b/326987971) : Update when feature is ready in service-appsearch.
+                // fall through
+            case Features.SCHEMA_STRING_PROPERTY_CONFIG_DELETE_PROPAGATION_TYPE_PROPAGATE_FROM:
+                // TODO(b/384947619) : Update when feature is ready in service-appsearch.
+                return false;
 
             default:
                 return false;
diff --git a/appsearch/appsearch-platform-storage/src/main/java/androidx/appsearch/platformstorage/PlatformStorage.java b/appsearch/appsearch-platform-storage/src/main/java/androidx/appsearch/platformstorage/PlatformStorage.java
index d595193..7838ec1 100644
--- a/appsearch/appsearch-platform-storage/src/main/java/androidx/appsearch/platformstorage/PlatformStorage.java
+++ b/appsearch/appsearch-platform-storage/src/main/java/androidx/appsearch/platformstorage/PlatformStorage.java
@@ -112,6 +112,7 @@
              * using {@link
              * androidx.appsearch.app.SetSchemaRequest.Builder#setSchemaTypeVisibilityForPackage}).
              *
+             * @param context The context used as the parent of the created SearchContext
              * @param databaseName The name of the database.
              * @throws IllegalArgumentException if the databaseName contains {@code '/'}.
              */
diff --git a/appsearch/appsearch-platform-storage/src/main/java/androidx/appsearch/platformstorage/util/AppSearchVersionUtil.java b/appsearch/appsearch-platform-storage/src/main/java/androidx/appsearch/platformstorage/util/AppSearchVersionUtil.java
index 753b681..10e589f 100644
--- a/appsearch/appsearch-platform-storage/src/main/java/androidx/appsearch/platformstorage/util/AppSearchVersionUtil.java
+++ b/appsearch/appsearch-platform-storage/src/main/java/androidx/appsearch/platformstorage/util/AppSearchVersionUtil.java
@@ -22,6 +22,7 @@
 import android.content.pm.PackageManager;
 import android.os.Build;
 
+import androidx.annotation.ChecksSdkIntAtLeast;
 import androidx.annotation.DoNotInline;
 import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
@@ -80,6 +81,13 @@
         return sAppSearchVersionCode;
     }
 
+    // TODO(b/326656531): Remove this function once BuildCompat#isAtLeastB is available.
+    @ChecksSdkIntAtLeast(api = 36, codename = "Baklava")
+    public static boolean isAtLeastB() {
+        return Build.VERSION.SDK_INT >= 36
+                || (Build.VERSION.SDK_INT >= 35 && Build.VERSION.CODENAME.equals("Baklava"));
+    }
+
     @RequiresApi(Build.VERSION_CODES.Q)
     private static class ApiHelperForQ {
         @DoNotInline
diff --git a/appsearch/appsearch-play-services-storage/src/main/java/androidx/appsearch/playservicesstorage/PlayServicesStorage.java b/appsearch/appsearch-play-services-storage/src/main/java/androidx/appsearch/playservicesstorage/PlayServicesStorage.java
index 325e7ea..40c1f66 100644
--- a/appsearch/appsearch-play-services-storage/src/main/java/androidx/appsearch/playservicesstorage/PlayServicesStorage.java
+++ b/appsearch/appsearch-play-services-storage/src/main/java/androidx/appsearch/playservicesstorage/PlayServicesStorage.java
@@ -107,6 +107,7 @@
              * using {@link
              * androidx.appsearch.app.SetSchemaRequest.Builder#setSchemaTypeVisibilityForPackage}).
              *
+             * @param context The context used as the parent of the created SearchContext
              * @param databaseName The name of the database.
              * @throws IllegalArgumentException if the databaseName contains {@code '/'}.
              */
diff --git a/appsearch/appsearch/src/main/java/androidx/appsearch/annotation/Document.java b/appsearch/appsearch/src/main/java/androidx/appsearch/annotation/Document.java
index 5e545a4..6f0f9f0 100644
--- a/appsearch/appsearch/src/main/java/androidx/appsearch/annotation/Document.java
+++ b/appsearch/appsearch/src/main/java/androidx/appsearch/annotation/Document.java
@@ -169,7 +169,9 @@
      * <p>The document will be automatically deleted {@link TtlMillis} milliseconds after
      * {@link CreationTimestampMillis}.
      *
-     * <p>This field is not required. If not present or not set, the document will never expire.
+     * <p>This field is not required. If not present, not set, or set to {@code 0}, the document
+     * will never expire or be auto-deleted until the app is uninstalled or
+     * {@link androidx.appsearch.app.AppSearchSession#removeAsync} is called.
      *
      * <p>If present, the field must be of type {@code long} or {@link Long}.
      *
diff --git a/browser/browser/src/main/java/androidx/browser/auth/AuthTabIntent.java b/browser/browser/src/main/java/androidx/browser/auth/AuthTabIntent.java
index 43c0e43..f1b964e 100644
--- a/browser/browser/src/main/java/androidx/browser/auth/AuthTabIntent.java
+++ b/browser/browser/src/main/java/androidx/browser/auth/AuthTabIntent.java
@@ -402,10 +402,8 @@
 
             // Put a null EXTRA_SESSION as a fallback so that this is interpreted as a Custom Tab
             // intent by browser implementations that don't support Auth Tab.
-            {
-                Bundle bundle = new Bundle();
-                bundle.putBinder(EXTRA_SESSION, null);
-                mIntent.putExtras(bundle);
+            if (!mIntent.hasExtra(EXTRA_SESSION)) {
+                setSessionParameters(null, null);
             }
 
             mIntent.putExtras(mDefaultColorSchemeBuilder.build().toBundle());
diff --git a/browser/browser/src/test/java/androidx/browser/customtabs/TestUtil.java b/browser/browser/src/test/java/androidx/browser/customtabs/TestUtil.java
index 2e6315f..60c23d3 100644
--- a/browser/browser/src/test/java/androidx/browser/customtabs/TestUtil.java
+++ b/browser/browser/src/test/java/androidx/browser/customtabs/TestUtil.java
@@ -18,6 +18,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -66,8 +67,9 @@
     /** Create s a mock {@link AuthTabSession} for testing. */
     @NonNull
     public static AuthTabSession makeMockAuthTabSession() {
-        return new AuthTabSession(mock(IAuthTabCallback.class),
-                new ComponentName("", ""), makeMockPendingIntent());
+        IAuthTabCallback callback = mock(IAuthTabCallback.class);
+        when(callback.asBinder()).thenReturn(mock(IAuthTabCallback.Stub.class));
+        return new AuthTabSession(callback, new ComponentName("", ""), makeMockPendingIntent());
     }
 
     /** Creates a mock {@link AuthTabSession.PendingSession} for testing. */
diff --git a/buildSrc/blank-proguard-rules/proguard-rules.pro b/buildSrc/blank-proguard-rules/proguard-rules.pro
new file mode 100644
index 0000000..3893b4c
--- /dev/null
+++ b/buildSrc/blank-proguard-rules/proguard-rules.pro
@@ -0,0 +1 @@
+# Intentionally empty proguard rules to indicate this library is safe to shrink
diff --git a/buildSrc/karmaconfig/karma.conf.js b/buildSrc/karmaconfig/karma.conf.js
index 2624c3c..3228090 100644
--- a/buildSrc/karmaconfig/karma.conf.js
+++ b/buildSrc/karmaconfig/karma.conf.js
@@ -8,7 +8,7 @@
   // https://karma-runner.github.io/6.4/config/configuration-file.html
     browserDisconnectTimeout: browserDisconnectTimeoutInMs,
     processKillTimeout: testTimeoutInMs,
-    concurrency: 10,
+    concurrency: 3,
     client: {
       mocha: {
         timeout: testTimeoutInMs
@@ -16,7 +16,7 @@
     }
 });
 
-// Add 5 second delay exit to ensure log flushing. This is needed for Kotlin to avoid flakiness when
+// Add 10 second delay exit to ensure log flushing. This is needed for Kotlin to avoid flakiness when
 // marking a test as complete. See (b/382336155)
 // Remove when https://youtrack.jetbrains.com/issue/KT-73911/ is resolved.
 (function() {
@@ -25,6 +25,6 @@
     console.log('Delaying exit for logs...');
     setTimeout(() => {
       originalExit(code);
-    }, 5000);
+    }, 10000);
   };
 })();
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
index 4dc9c6e..aea21e9 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
@@ -234,6 +234,7 @@
             if (androidXExtension.shouldPublish()) {
                 project.validatePublishedMultiplatformHasDefault()
                 project.addLicensesToPublishedArtifacts(androidXExtension.license)
+                project.registerValidateRelocatedDependenciesTask()
             }
             project.registerValidateMultiplatformSourceSetNamingTask()
             project.validateLintVersionTestExists(androidXExtension)
@@ -914,6 +915,13 @@
                 it.buildTypes.configureEach { buildType ->
                     if (buildType.name == buildTypeForTests && !project.hasBenchmarkPlugin())
                         (buildType as TestBuildType).isDebuggable = true
+                    val blankProguardRules =
+                        project
+                            .getSupportRootFolder()
+                            .resolve("buildSrc/blank-proguard-rules/proguard-rules.pro")
+                    if (buildType.consumerProguardFiles.isEmpty()) {
+                        buildType.consumerProguardFiles.add(blankProguardRules)
+                    }
                 }
             }
             beforeVariants(selector().withBuildType("debug")) { variant -> variant.enable = false }
@@ -1322,7 +1330,9 @@
     // If this project wants other project in the same group to have the same version,
     // this function configures those constraints.
     private fun Project.configureConstraintsWithinGroup(androidXExtension: AndroidXExtension) {
-        if (!project.shouldAddGroupConstraints().get()) {
+        if (
+            !project.shouldAddGroupConstraints().get() || buildFeatures.isIsolatedProjectsEnabled()
+        ) {
             return
         }
         project.afterEvaluate {
@@ -1372,7 +1382,8 @@
                     continue
                 }
                 // We only emit constraints referring to projects that will release
-                val otherFilepath = File(otherProject.filePath, "build.gradle")
+                val otherFilepath =
+                    getSupportRootFolder().resolve(File(otherProject.filePath, "build.gradle"))
                 val parsed = parseBuildFile(otherFilepath)
                 if (!parsed.shouldRelease()) {
                     continue
@@ -1491,6 +1502,10 @@
 /** Returns whether the configuration is used for testing. */
 private fun Configuration.isTest(): Boolean = name.lowercase().contains("test")
 
+/** Returns whether the configuration is part of publication. */
+internal fun Configuration.isPublished(): Boolean =
+    !isTest() && !name.lowercase().contains("metadata") && !name.endsWith("CInterop")
+
 /**
  * Hides a project's Javadoc tasks from the output of `./gradlew tasks` by setting their group to
  * `null`.
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/CheckKotlinApiTargetTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/CheckKotlinApiTargetTask.kt
index 62dbdd0..1dacc62 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/CheckKotlinApiTargetTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/CheckKotlinApiTargetTask.kt
@@ -36,12 +36,7 @@
     @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")
-            }
+            .filter { it.isPublished() && it.isCanBeResolved }
             .flatMap { config ->
                 config.resolvedConfiguration.firstLevelModuleDependencies.map {
                     "${it.moduleName}:${it.moduleVersion}" to config.name
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/VerifyRelocatedDependenciesTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/VerifyRelocatedDependenciesTask.kt
new file mode 100644
index 0000000..466811a
--- /dev/null
+++ b/buildSrc/private/src/main/kotlin/androidx/build/VerifyRelocatedDependenciesTask.kt
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2025 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 androidx.build.VerifyRelocatedDependenciesTask.Companion.ALLOWED_CONFIGURATIONS
+import androidx.build.uptodatedness.cacheEvenIfNoOutputs
+import org.gradle.api.DefaultTask
+import org.gradle.api.GradleException
+import org.gradle.api.Project
+import org.gradle.api.provider.ListProperty
+import org.gradle.api.tasks.CacheableTask
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Internal
+import org.gradle.api.tasks.TaskAction
+
+/** Ensures specified libraries are always relocated/jarjarred */
+@CacheableTask
+abstract class VerifyRelocatedDependenciesTask : DefaultTask() {
+
+    @get:Input abstract val allDependencies: ListProperty<Pair<String, List<String>>>
+
+    @Internal val projectPath: String = project.path
+
+    @Internal val librariesToCheck: List<String> = listOf("protobuf-javalite", "protobuf-java")
+
+    @TaskAction
+    fun check() {
+        if (projectPath == ":benchmark:benchmark-baseline-profile-gradle-plugin") {
+            return
+        }
+        val violations =
+            allDependencies.get().filter { (_, artifacts) ->
+                librariesToCheck.any { artifacts.contains(it) }
+            }
+
+        if (violations.isNotEmpty()) {
+            val message = buildString {
+                appendLine("The following configurations contain disallowed dependencies:")
+                violations.forEach { (configurationName, artifacts) ->
+                    appendLine("Configuration: $configurationName")
+                    artifacts.forEach { artifact ->
+                        if (librariesToCheck.contains(artifact)) {
+                            appendLine("  - $artifact")
+                        }
+                    }
+                }
+                appendLine(
+                    "Publishing $projectPath is not allowed until the above dependencies are " +
+                        "relocated. Consider using the AndroidXRepackagePlugin."
+                )
+            }
+            throw GradleException(message)
+        }
+    }
+
+    internal companion object {
+        const val TASK_NAME = "verifyRelocatedDependencies"
+        val ALLOWED_CONFIGURATIONS = listOf("compileOnly", "repackage")
+    }
+}
+
+internal fun Project.registerValidateRelocatedDependenciesTask() =
+    tasks
+        .register(
+            VerifyRelocatedDependenciesTask.TASK_NAME,
+            VerifyRelocatedDependenciesTask::class.java
+        ) {
+            val depsProvider =
+                project.providers.provider<List<Pair<String, List<String>>>> {
+                    project.configurations
+                        .filter { configuration ->
+                            configuration.isPublished() &&
+                                !configuration.isCanBeResolved &&
+                                configuration.name !in ALLOWED_CONFIGURATIONS
+                        }
+                        .map { configuration ->
+                            configuration.name to
+                                configuration.allDependencies.map { dependency -> dependency.name }
+                        }
+                }
+            it.allDependencies.set(depsProvider)
+            it.cacheEvenIfNoOutputs()
+        }
+        .also { addToBuildOnServer(it) }
diff --git a/buildSrc/public/src/main/kotlin/androidx/build/LibraryType.kt b/buildSrc/public/src/main/kotlin/androidx/build/LibraryType.kt
index 8347d6d..c6b6459 100644
--- a/buildSrc/public/src/main/kotlin/androidx/build/LibraryType.kt
+++ b/buildSrc/public/src/main/kotlin/androidx/build/LibraryType.kt
@@ -89,6 +89,7 @@
 
     companion object {
         // Host-only tooling libraries
+        @JvmStatic
         val ANNOTATION_PROCESSOR =
             ConfigurableLibrary(
                 name = "ANNOTATION_PROCESSOR",
@@ -97,6 +98,7 @@
                 compilationTarget = CompilationTarget.HOST
             )
 
+        @JvmStatic
         val ANNOTATION_PROCESSOR_UTILS =
             ConfigurableLibrary(
                 name = "ANNOTATION_PROCESSOR_UTILS",
@@ -105,6 +107,7 @@
                 compilationTarget = CompilationTarget.HOST
             )
 
+        @JvmStatic
         val GRADLE_PLUGIN =
             ConfigurableLibrary(
                 name = "GRADLE_PLUGIN",
@@ -113,6 +116,7 @@
                 compilationTarget = CompilationTarget.HOST
             )
 
+        @JvmStatic
         val OTHER_CODE_PROCESSOR =
             ConfigurableLibrary(
                 name = "OTHER_CODE_PROCESSOR",
@@ -122,6 +126,7 @@
             )
 
         // Lint libraries
+        @JvmStatic
         val LINT =
             ConfigurableLibrary(
                 name = "LINT",
@@ -129,6 +134,7 @@
                 compilationTarget = CompilationTarget.HOST
             )
 
+        @JvmStatic
         val STANDALONE_PUBLISHED_LINT =
             ConfigurableLibrary(
                 name = "STANDALONE_PUBLISHED_LINT",
@@ -138,6 +144,7 @@
             )
 
         // Published libraries
+        @JvmStatic
         val PUBLISHED_LIBRARY =
             ConfigurableLibrary(
                 name = "PUBLISHED_LIBRARY",
@@ -145,6 +152,7 @@
                 checkApi = RunApiTasks.Yes()
             )
 
+        @JvmStatic
         val PUBLISHED_PROTO_LIBRARY =
             ConfigurableLibrary(
                 name = "PUBLISHED_PROTO_LIBRARY",
@@ -153,6 +161,7 @@
                     RunApiTasks.No("Metalava doesn't properly parse the proto sources b/180579063")
             )
 
+        @JvmStatic
         val PUBLISHED_LIBRARY_ONLY_USED_BY_KOTLIN_CONSUMERS =
             ConfigurableLibrary(
                 name = "PUBLISHED_LIBRARY_ONLY_USED_BY_KOTLIN_CONSUMERS",
@@ -162,6 +171,7 @@
             )
 
         // Published test libraries
+        @JvmStatic
         val PUBLISHED_TEST_LIBRARY =
             ConfigurableLibrary(
                 name = "PUBLISHED_TEST_LIBRARY",
@@ -170,6 +180,7 @@
                 allowCallingVisibleForTestsApis = true
             )
 
+        @JvmStatic
         val PUBLISHED_KOTLIN_ONLY_TEST_LIBRARY =
             ConfigurableLibrary(
                 name = "PUBLISHED_KOTLIN_ONLY_TEST_LIBRARY",
@@ -180,6 +191,7 @@
             )
 
         // Snapshot-only libraries
+        @JvmStatic
         val SNAPSHOT_ONLY_LIBRARY_ONLY_USED_BY_KOTLIN_CONSUMERS =
             ConfigurableLibrary(
                 name = "SNAPSHOT_ONLY_LIBRARY_ONLY_USED_BY_KOTLIN_CONSUMERS",
@@ -188,6 +200,7 @@
                 targetsKotlinConsumersOnly = true
             )
 
+        @JvmStatic
         val SNAPSHOT_ONLY_TEST_LIBRARY_WITH_API_TASKS =
             ConfigurableLibrary(
                 name = "SNAPSHOT_ONLY_TEST_LIBRARY_WITH_API_TASKS",
@@ -196,6 +209,7 @@
                 allowCallingVisibleForTestsApis = true
             )
 
+        @JvmStatic
         val SNAPSHOT_ONLY_LIBRARY_WITH_API_TASKS =
             ConfigurableLibrary(
                 name = "SNAPSHOT_ONLY_LIBRARY_WITH_API_TASKS",
@@ -203,6 +217,7 @@
                 checkApi = RunApiTasks.Yes("Snapshot-only library that runs API tasks")
             )
 
+        @JvmStatic
         val SNAPSHOT_ONLY_LIBRARY =
             ConfigurableLibrary(
                 name = "SNAPSHOT_ONLY_LIBRARY",
@@ -211,6 +226,7 @@
             )
 
         // Samples library
+        @JvmStatic
         val SAMPLES =
             ConfigurableLibrary(
                 name = "SAMPLES",
@@ -219,6 +235,7 @@
             )
 
         // IDE libraries
+        @JvmStatic
         val IDE_PLUGIN =
             ConfigurableLibrary(
                 name = "IDE_PLUGIN",
@@ -227,6 +244,7 @@
             )
 
         // Internal libraries
+        @JvmStatic
         val INTERNAL_GRADLE_PLUGIN =
             ConfigurableLibrary(
                 name = "INTERNAL_GRADLE_PLUGIN",
@@ -234,6 +252,7 @@
                 compilationTarget = CompilationTarget.HOST
             )
 
+        @JvmStatic
         val INTERNAL_HOST_TEST_LIBRARY =
             ConfigurableLibrary(
                 name = "INTERNAL_HOST_TEST_LIBRARY",
@@ -241,12 +260,14 @@
                 compilationTarget = CompilationTarget.HOST
             )
 
+        @JvmStatic
         val INTERNAL_LIBRARY_WITH_API_TASKS =
             ConfigurableLibrary(
                 name = "INTERNAL_LIBRARY_WITH_API_TASKS",
                 checkApi = RunApiTasks.Yes("Always run API tasks even if not published")
             )
 
+        @JvmStatic
         val INTERNAL_OTHER_CODE_PROCESSOR =
             ConfigurableLibrary(
                 name = "INTERNAL_OTHER_CODE_PROCESSOR",
@@ -254,6 +275,7 @@
                 compilationTarget = CompilationTarget.HOST
             )
 
+        @JvmStatic
         val INTERNAL_TEST_LIBRARY =
             ConfigurableLibrary(
                 name = "INTERNAL_TEST_LIBRARY",
@@ -262,6 +284,7 @@
             )
 
         // Misc libraries
+        @JvmStatic
         val BENCHMARK =
             ConfigurableLibrary(
                 name = "BENCHMARK",
@@ -269,6 +292,7 @@
                 allowCallingVisibleForTestsApis = true
             )
 
+        @JvmStatic
         val TEST_APPLICATION =
             ConfigurableLibrary(name = "TEST_APPLICATION", checkApi = RunApiTasks.No("Test App"))
 
diff --git a/busytown/androidx.sh b/busytown/androidx.sh
index 8c59791..9c5f4e1 100755
--- a/busytown/androidx.sh
+++ b/busytown/androidx.sh
@@ -22,7 +22,6 @@
   if ! busytown/impl/build.sh buildOnServer createAllArchives checkExternalLicenses listTaskOutputs exportSboms \
       -Pandroidx.enableComposeCompilerMetrics=true \
       -Pandroidx.enableComposeCompilerReports=true \
-      -Pandroidx.constraints=true \
       --no-daemon "$@"; then
     EXIT_VALUE=1
   else
diff --git a/busytown/androidx_incremental.sh b/busytown/androidx_incremental.sh
index 810d4e4..ac2aaea03 100755
--- a/busytown/androidx_incremental.sh
+++ b/busytown/androidx_incremental.sh
@@ -102,7 +102,7 @@
   EXIT_VALUE=1
 else
     # Run Gradle
-    if impl/build.sh $DIAGNOSE_ARG buildOnServer checkExternalLicenses listTaskOutputs exportSboms \
+    if impl/build.sh $DIAGNOSE_ARG buildOnServer createAllArchives checkExternalLicenses listTaskOutputs exportSboms \
         "$@"; then
     echo build succeeded
     EXIT_VALUE=0
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/RequestProcessorAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/RequestProcessorAdapter.kt
index 91485d9..6490aa4 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/RequestProcessorAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/RequestProcessorAdapter.kt
@@ -31,18 +31,19 @@
 import androidx.camera.camera2.pipe.integration.config.UseCaseGraphConfig
 import androidx.camera.camera2.pipe.integration.impl.CAMERAX_TAG_BUNDLE
 import androidx.camera.camera2.pipe.integration.impl.Camera2ImplConfig
+import androidx.camera.camera2.pipe.integration.impl.CameraCallbackMap
+import androidx.camera.camera2.pipe.integration.impl.UseCaseThreads
 import androidx.camera.camera2.pipe.integration.impl.toParameters
 import androidx.camera.core.impl.DeferrableSurface
 import androidx.camera.core.impl.RequestProcessor
 import androidx.camera.core.impl.SessionConfig
 import androidx.camera.core.impl.SessionProcessorSurface
 import kotlinx.atomicfu.atomic
-import kotlinx.coroutines.CoroutineScope
 
 public class RequestProcessorAdapter(
     private val useCaseGraphConfig: UseCaseGraphConfig,
     private val processorSurfaces: List<SessionProcessorSurface>,
-    private val scope: CoroutineScope,
+    private val threads: UseCaseThreads
 ) : RequestProcessor {
     private val coroutineMutex = CoroutineMutex()
     private val sequenceIds = atomic(0)
@@ -173,7 +174,7 @@
                 )
             }
 
-        coroutineMutex.withLockLaunch(scope) {
+        coroutineMutex.withLockLaunch(threads.scope) {
             useCaseGraphConfig.graph.acquireSession().use { it.submit(requestsToSubmit) }
         }
         return sequenceId
@@ -207,10 +208,14 @@
                             shouldInvokeSequenceCallback = true,
                             request,
                             this
+                        ),
+                        CameraCallbackMap.createFor(
+                            sessionConfig!!.repeatingCameraCaptureCallbacks,
+                            threads.backgroundExecutor
                         )
                     )
             )
-        coroutineMutex.withLockLaunch(scope) {
+        coroutineMutex.withLockLaunch(threads.scope) {
             useCaseGraphConfig.graph.acquireSession().use { it.startRepeating(requestsToSubmit) }
         }
         return sequenceId
@@ -218,14 +223,14 @@
 
     override fun abortCaptures() {
         Log.debug { "$this#abortCaptures" }
-        coroutineMutex.withLockLaunch(scope) {
+        coroutineMutex.withLockLaunch(threads.scope) {
             useCaseGraphConfig.graph.acquireSession().use { it.abort() }
         }
     }
 
     override fun stopRepeating() {
         Log.debug { "$this#stopRepeating" }
-        coroutineMutex.withLockLaunch(scope) {
+        coroutineMutex.withLockLaunch(threads.scope) {
             useCaseGraphConfig.graph.acquireSession().use { it.stopRepeating() }
         }
     }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCamera.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCamera.kt
index cf3df44..cc39c70 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCamera.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCamera.kt
@@ -113,7 +113,7 @@
                             RequestProcessorAdapter(
                                 useCaseGraphConfig,
                                 sessionProcessorSurfaces,
-                                threads.scope,
+                                threads
                             )
                         sessionProcessorManager.onCaptureSessionStart(requestProcessorAdapter)
                     }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraState.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraState.kt
index ad6d9fd..1405fc0 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraState.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseCameraState.kt
@@ -361,6 +361,11 @@
                             addTag(tag, value)
                         }
                     }
+                    currentSessionConfig?.let {
+                        addAllCameraCaptureCallbacks(
+                            it.repeatingCaptureConfig.cameraCaptureCallbacks
+                        )
+                    }
                 }
                 .build()
                 .also { sessionConfig -> sessionProcessorManager.sessionConfig = sessionConfig }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
index 400a846..0a33480 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
@@ -18,7 +18,6 @@
 
 import android.content.Context
 import android.graphics.ImageFormat
-import android.hardware.camera2.CameraCharacteristics
 import android.hardware.camera2.CameraDevice.TEMPLATE_PREVIEW
 import android.hardware.camera2.CaptureRequest
 import android.hardware.camera2.params.OutputConfiguration
@@ -882,6 +881,25 @@
             return Camera2ImplConfig(implementationOptions)
         }
 
+        // return video stabilization mode. null indicate mode unspecified.
+        public fun getVideoStabilizationModeFromCaptureConfig(captureConfig: CaptureConfig): Int? {
+            val isPreviewStabilizationMode = captureConfig.previewStabilizationMode
+            val isVideoStabilizationMode = captureConfig.videoStabilizationMode
+
+            return if (
+                isPreviewStabilizationMode == StabilizationMode.OFF ||
+                    isVideoStabilizationMode == StabilizationMode.OFF
+            ) {
+                CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_OFF
+            } else if (isPreviewStabilizationMode == StabilizationMode.ON) {
+                CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION
+            } else if (isVideoStabilizationMode == StabilizationMode.ON) {
+                CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_ON
+            } else {
+                null
+            }
+        }
+
         public fun createCameraGraphConfig(
             sessionConfigAdapter: SessionConfigAdapter,
             streamConfigMap: MutableMap<CameraStream.Config, DeferrableSurface>,
@@ -991,24 +1009,11 @@
             val combinedFlags = createCameraGraphFlags(cameraQuirks, containsVideo, isExtensions)
 
             // Set video stabilization mode to capture request
-            var videoStabilizationMode = CameraCharacteristics.CONTROL_VIDEO_STABILIZATION_MODE_OFF
+            var videoStabilizationMode: Int? = null
             if (sessionConfigAdapter.getValidSessionConfigOrNull() != null) {
                 val config =
                     sessionConfigAdapter.getValidSessionConfigOrNull()!!.repeatingCaptureConfig
-                val isPreviewStabilizationMode = config.previewStabilizationMode
-                val isVideoStabilizationMode = config.videoStabilizationMode
-
-                if (
-                    isPreviewStabilizationMode == StabilizationMode.OFF ||
-                        isVideoStabilizationMode == StabilizationMode.OFF
-                ) {
-                    videoStabilizationMode = CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_OFF
-                } else if (isPreviewStabilizationMode == StabilizationMode.ON) {
-                    videoStabilizationMode =
-                        CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION
-                } else if (isVideoStabilizationMode == StabilizationMode.ON) {
-                    videoStabilizationMode = CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_ON
-                }
+                videoStabilizationMode = getVideoStabilizationModeFromCaptureConfig(config)
             }
 
             // Set fps range to capture request
@@ -1018,7 +1023,9 @@
                     if (isExtensions) {
                         set(CameraPipeKeys.ignore3ARequiredParameters, true)
                     }
-                    set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, videoStabilizationMode)
+                    videoStabilizationMode?.let {
+                        set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, it)
+                    }
                     set(
                         CameraPipeKeys.camera2CaptureRequestTag,
                         "android.hardware.camera2.CaptureRequest.setTag.CX"
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/RequestProcessorAdapterTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/RequestProcessorAdapterTest.kt
index ecbcc24..52f65af 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/RequestProcessorAdapterTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/RequestProcessorAdapterTest.kt
@@ -33,16 +33,20 @@
 import androidx.camera.camera2.pipe.compat.CameraPipeKeys
 import androidx.camera.camera2.pipe.integration.config.UseCaseGraphConfig
 import androidx.camera.camera2.pipe.integration.impl.Camera2ImplConfig
+import androidx.camera.camera2.pipe.integration.impl.UseCaseThreads
 import androidx.camera.camera2.pipe.testing.CameraGraphSimulator
 import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
+import androidx.camera.core.impl.CameraCaptureCallback
 import androidx.camera.core.impl.DeferrableSurface
 import androidx.camera.core.impl.RequestProcessor
 import androidx.camera.core.impl.SessionConfig
 import androidx.camera.core.impl.SessionProcessorSurface
 import androidx.test.core.app.ApplicationProvider
 import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
 import kotlin.test.Test
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.asCoroutineDispatcher
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.advanceUntilIdle
 import kotlinx.coroutines.test.runTest
@@ -87,11 +91,13 @@
     private val imageCaptureProcessorSurface =
         SessionProcessorSurface(imageCaptureSurface, imageCaptureOutputConfigId)
 
+    private val cameraCaptureCallback: CameraCaptureCallback = mock()
     private val fakeSessionConfig =
         SessionConfig.Builder()
             .apply {
                 addSurface(previewProcessorSurface)
                 addSurface(imageCaptureProcessorSurface)
+                addCameraCaptureCallback(cameraCaptureCallback)
             }
             .build()
 
@@ -140,12 +146,11 @@
         val useCaseGraphConfig =
             UseCaseGraphConfig(simulator, surfaceToStreamMap, CameraStateAdapter())
 
+        val executor = MoreExecutors.directExecutor()
+        val dispatcher = executor.asCoroutineDispatcher()
+        val useCaseThreads = UseCaseThreads(scope, executor, dispatcher)
         requestProcessorAdapter =
-            RequestProcessorAdapter(
-                    useCaseGraphConfig,
-                    sessionProcessorSurfaces,
-                    scope,
-                )
+            RequestProcessorAdapter(useCaseGraphConfig, sessionProcessorSurfaces, useCaseThreads)
                 .apply { sessionConfig = fakeSessionConfig }
         scope.advanceUntilIdle()
     }
@@ -180,9 +185,11 @@
             .isEqualTo(checkNotNull(cameraGraphSimulator!!.streams[previewStreamConfig]).id)
 
         verify(callback, times(1)).onCaptureStarted(eq(requestToSet), any(), any())
+        verify(cameraCaptureCallback, times(1)).onCaptureStarted(any())
 
         frame.simulateComplete(emptyMap())
         verify(callback, times(1)).onCaptureCompleted(eq(requestToSet), any())
+        verify(cameraCaptureCallback, times(1)).onCaptureCompleted(any(), any())
         advanceUntilIdle()
     }
 
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2DeviceManager.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2DeviceManager.kt
index eb765c9..f154261 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2DeviceManager.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2DeviceManager.kt
@@ -16,11 +16,14 @@
 
 package androidx.camera.camera2.pipe.compat
 
+import androidx.annotation.VisibleForTesting
 import androidx.camera.camera2.pipe.CameraError
 import androidx.camera.camera2.pipe.CameraId
 import androidx.camera.camera2.pipe.GraphState
 import androidx.camera.camera2.pipe.core.Log
 import androidx.camera.camera2.pipe.core.Permissions
+import androidx.camera.camera2.pipe.core.PruningProcessingQueue
+import androidx.camera.camera2.pipe.core.PruningProcessingQueue.Companion.processIn
 import androidx.camera.camera2.pipe.core.Threads
 import androidx.camera.camera2.pipe.core.WakeLock
 import androidx.camera.camera2.pipe.graph.GraphListener
@@ -30,7 +33,6 @@
 import kotlinx.coroutines.CoroutineName
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.channels.SendChannel
 import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.launch
@@ -98,7 +100,7 @@
     private val androidCameraState: AndroidCameraState,
     internal val allCameraIds: Set<CameraId>,
     scope: CoroutineScope,
-    channel: SendChannel<CameraRequest>
+    closeCallback: (ActiveCamera) -> Unit
 ) {
     val cameraId: CameraId
         get() = androidCameraState.cameraId
@@ -109,7 +111,7 @@
         WakeLock(
             scope,
             timeout = 1000,
-            callback = { channel.trySend(RequestClose(this)).isSuccess },
+            callback = { closeCallback(this) },
             // Every ActiveCamera is associated with an opened camera. We should ensure that we
             // issue a RequestClose eventually for every ActiveCamera created.
             //
@@ -145,6 +147,369 @@
     }
 }
 
+/**
+ * PruningCamera2DeviceManager is an implementation of [Camera2DeviceManager] that actively prunes
+ * incoming camera requests before processing them. It does this through a proven sequence of logic
+ * that reduces the pending requests to an equivalent but shorter sequence of requests, allowing the
+ * internal request processing channel to stay at a size within a proven upper bound, and the actual
+ * request processing to be done optimally and efficiently.
+ */
+@Singleton
+internal class PruningCamera2DeviceManager
+@Inject
+constructor(
+    private val permissions: Permissions,
+    private val retryingCameraStateOpener: RetryingCameraStateOpener,
+    private val camera2DeviceCloser: Camera2DeviceCloser,
+    private val camera2ErrorProcessor: Camera2ErrorProcessor,
+    val threads: Threads
+) : Camera2DeviceManager {
+    private val scope = threads.globalScope
+
+    private val queue =
+        PruningProcessingQueue<CameraRequest>(prune = ::prune) { process(it) }.processIn(scope)
+    private val activeCameras: MutableSet<ActiveCamera> = mutableSetOf()
+    private val pendingRequestOpens = mutableListOf<RequestOpen>()
+    private val pendingRequestOpenActiveCameraMap = mutableMapOf<RequestOpen, ActiveCamera>()
+
+    override fun open(
+        cameraId: CameraId,
+        sharedCameraIds: List<CameraId>,
+        graphListener: GraphListener,
+        isPrewarm: Boolean,
+        isForegroundObserver: (Unit) -> Boolean
+    ): VirtualCamera? {
+        val result = VirtualCameraState(cameraId, graphListener, scope)
+        if (
+            !queue.tryEmit(
+                RequestOpen(result, sharedCameraIds, graphListener, isPrewarm, isForegroundObserver)
+            )
+        ) {
+            // This should generally not happen unless someone attempts to open a camera after
+            // CameraPipe shutdown, or we somehow run out of memory, since this class lives for the
+            // duration of the application process.
+            Log.error { "Camera open request failed for $cameraId!" }
+            graphListener.onGraphError(
+                GraphState.GraphStateError(
+                    CameraError.ERROR_CAMERA_OPENER,
+                    willAttemptRetry = false
+                )
+            )
+            return null
+        }
+        return result
+    }
+
+    override fun prewarm(cameraId: CameraId) {
+        open(
+            cameraId = cameraId,
+            sharedCameraIds = emptyList(),
+            graphListener = NoOpGraphListener,
+            isPrewarm = true,
+        ) { _ ->
+            false
+        }
+    }
+
+    override fun close(cameraId: CameraId) {
+        if (!queue.tryEmit(RequestCloseById(cameraId))) {
+            Log.error { "Camera close by ID request failed for $cameraId!" }
+        }
+    }
+
+    override fun closeAll() {
+        if (!queue.tryEmit(RequestCloseAll)) {
+            Log.error { "Camera close all request failed!" }
+        }
+    }
+
+    @VisibleForTesting
+    internal fun prune(requests: MutableList<CameraRequest>) {
+        // Step 1: Prioritize RequestClose - place them at the front of the queue.
+        val requestCloses = requests.filter { it is RequestClose }
+        requests.removeAll(requestCloses)
+        // Move the RequestCloses to the front of the queue (in order) to be processed first.
+        for (request in requestCloses.reversed()) {
+            requests.add(0, request)
+        }
+
+        // Step 2: Handle RequestCloseAll. The last one would nullify all preceding requests.
+        val numRequestsBeforeCloseAll = requests.indexOfLast { it is RequestCloseAll }
+        if (numRequestsBeforeCloseAll > 0) {
+            repeat(numRequestsBeforeCloseAll) { requests.removeAt(0).onRemoved() }
+        }
+
+        // Step 3: Handle RequestOpen and RequestCloseById pruning.
+        val prunedIndices = mutableSetOf<Int>()
+        for ((idx, request) in requests.withIndex()) {
+            val prunedByIdx =
+                when (request) {
+                    is RequestOpen -> {
+                        // There are 2 cases where a RequestOpen can be pruned by a latter request:
+                        //
+                        // 1. RequestCloseById: If any of its cameras (including itself and the
+                        //    shared cameras) would be closed by it, then this RequestOpen could be
+                        //    pruned.
+                        // 2. RequestOpen: If the latter RequestOpen requests the same camera, or
+                        //    it requests a different camera and it doesn't need the camera to be
+                        //    opened by the current RequestOpen.
+                        val cameraId = request.virtualCamera.cameraId
+                        val allCameraIds = (request.sharedCameraIds + cameraId).toSet()
+
+                        requests.firstFromIndexOrNull(idx + 1) {
+                            when (it) {
+                                is RequestCloseById -> allCameraIds.contains(it.activeCameraId)
+                                is RequestOpen -> {
+                                    val cameraId2 = it.virtualCamera.cameraId
+                                    val allCameraIds2 = (it.sharedCameraIds + cameraId2).toSet()
+                                    cameraId == cameraId2 || allCameraIds != allCameraIds2
+                                }
+                                else -> false
+                            }
+                        }
+                    }
+                    is RequestCloseById ->
+                        // If there are several RequestCloseByIds with identical camera IDs, we can
+                        // just leave the latter one.
+                        requests.firstFromIndexOrNull(idx + 1) {
+                            it is RequestCloseById && it.activeCameraId == request.activeCameraId
+                        }
+                    else -> null
+                }
+            if (prunedByIdx != null) {
+                Log.debug { "$request is pruned by ${requests[prunedByIdx]}" }
+                prunedIndices.add(idx)
+            }
+        }
+        requests.removeIndices(prunedIndices).forEach { it.onRemoved() }
+    }
+
+    private fun CameraRequest.onRemoved() {
+        if (this is RequestOpen) {
+            virtualCamera.disconnect()
+        }
+    }
+
+    private suspend fun process(request: CameraRequest) {
+        when (request) {
+            is RequestOpen -> processRequestOpen(request)
+            is RequestClose -> processRequestClose(request)
+            is RequestCloseById -> processRequestCloseById(request)
+            is RequestCloseAll -> processRequestCloseAll()
+        }
+    }
+
+    private suspend fun processRequestOpen(request: RequestOpen) {
+        val cameraIdToOpen = request.virtualCamera.cameraId
+        Log.info { "PruningCamera2DeviceManager#processRequestOpen($cameraIdToOpen)" }
+
+        val camerasToClose =
+            if (request.sharedCameraIds.isEmpty()) {
+                activeCameras.filter { it.cameraId != cameraIdToOpen }
+            } else {
+                val allCameraIds =
+                    (request.sharedCameraIds + request.virtualCamera.cameraId).toSet()
+                activeCameras.filter { it.allCameraIds != allCameraIds }
+            }
+
+        // Step 1: Close the cameras needed to be closed.
+        if (camerasToClose.isNotEmpty()) {
+            // Shutdown of cameras should always happen first (and suspend until complete)
+            activeCameras.removeAll(camerasToClose)
+            for (requestOpen in pendingRequestOpens) {
+                if (camerasToClose.contains(pendingRequestOpenActiveCameraMap[requestOpen])) {
+                    pendingRequestOpens.remove(requestOpen)
+                    pendingRequestOpenActiveCameraMap.remove(requestOpen)
+                }
+            }
+            for (camera in camerasToClose) {
+                camera.close()
+            }
+            for (realCamera in camerasToClose) {
+                realCamera.awaitClosed()
+            }
+        }
+
+        // Step 2: Open the camera if not opened already.
+        camera2ErrorProcessor.setActiveVirtualCamera(cameraIdToOpen, request.virtualCamera)
+        var realCamera = activeCameras.firstOrNull { it.cameraId == cameraIdToOpen }
+        if (realCamera == null) {
+            val openResult =
+                openCameraWithRetry(
+                    cameraIdToOpen,
+                    request.sharedCameraIds,
+                    request.isForegroundObserver,
+                    scope,
+                )
+            when (openResult) {
+                is OpenVirtualCameraResult.Success -> {
+                    realCamera = openResult.activeCamera
+                    activeCameras.add(realCamera)
+                }
+                is OpenVirtualCameraResult.Error -> {
+                    request.virtualCamera.disconnect(openResult.lastCameraError)
+                    return
+                }
+            }
+        }
+
+        // Step 3: Connect the opened camera(s).
+        if (request.sharedCameraIds.isNotEmpty()) {
+            // Both sharedCameraIds and activeCameras are small collections. Looping over them
+            // in what equates to nested for-loops are actually going to be more efficient than
+            // say, replacing activeCameras with a hashmap.
+            if (
+                request.sharedCameraIds.all { cameraId ->
+                    activeCameras.any { it.cameraId == cameraId }
+                }
+            ) {
+                // If the camera of the request and the cameras it is shared with have been
+                // opened, we can connect the ActiveCameras.
+                check(!request.isPrewarm)
+                realCamera.connectTo(request.virtualCamera)
+                connectPendingRequestOpens(request.sharedCameraIds)
+            } else {
+                // Else, save the request in the pending request queue, and connect the request
+                // once other cameras are opened.
+                pendingRequestOpens.add(request)
+                pendingRequestOpenActiveCameraMap[request] = realCamera
+            }
+        } else {
+            if (!request.isPrewarm) {
+                realCamera.connectTo(request.virtualCamera)
+            }
+        }
+    }
+
+    private suspend fun processRequestClose(request: RequestClose) {
+        val cameraId = request.activeCamera.cameraId
+        Log.info { "PruningCamera2DeviceManager#processRequestClose($cameraId)" }
+
+        if (activeCameras.contains(request.activeCamera)) {
+            activeCameras.remove(request.activeCamera)
+        }
+        for (requestOpen in pendingRequestOpens) {
+            // Edge case: There is a possibility that we receive RequestClose after a RequestOpen
+            // for concurrent cameras has been processed. As such, we don't want to close the
+            // ActiveCamera newly created by the RequestOpen, but only the one RequestClose is
+            // aiming to close.
+            if (pendingRequestOpenActiveCameraMap[requestOpen] == request.activeCamera) {
+                pendingRequestOpens.remove(requestOpen)
+                pendingRequestOpenActiveCameraMap.remove(requestOpen)
+            }
+        }
+        request.activeCamera.close()
+        request.activeCamera.awaitClosed()
+    }
+
+    private suspend fun processRequestCloseById(request: RequestCloseById) {
+        val cameraId = request.activeCameraId
+        Log.info { "PruningCamera2DeviceManager#processRequestCloseById(${request.activeCameraId}" }
+
+        for (requestOpen in pendingRequestOpens) {
+            if (requestOpen.virtualCamera.cameraId == cameraId) {
+                pendingRequestOpens.remove(requestOpen)
+                pendingRequestOpenActiveCameraMap.remove(requestOpen)
+            }
+        }
+        val activeCamera = activeCameras.firstOrNull { it.cameraId == cameraId }
+        if (activeCamera == null) return
+        activeCameras.remove(activeCamera)
+        activeCamera.close()
+        activeCamera.awaitClosed()
+    }
+
+    private suspend fun processRequestCloseAll() {
+        Log.info { "PruningCamera2DeviceManager#processRequestCloseAll()" }
+
+        pendingRequestOpens.clear()
+        pendingRequestOpenActiveCameraMap.clear()
+        for (activeCamera in activeCameras) {
+            activeCamera.close()
+        }
+        for (activeCamera in activeCameras) {
+            activeCamera.awaitClosed()
+        }
+        activeCameras.clear()
+    }
+
+    private suspend fun openCameraWithRetry(
+        cameraId: CameraId,
+        sharedCameraIds: List<CameraId>,
+        isForegroundObserver: (Unit) -> Boolean,
+        scope: CoroutineScope
+    ): OpenVirtualCameraResult {
+        // TODO: Figure out how 1-time permissions work, and see if they can be reset without
+        //   causing the application process to restart.
+        check(permissions.hasCameraPermission) { "Missing camera permissions!" }
+
+        Log.debug { "Opening $cameraId with retries..." }
+        val result =
+            retryingCameraStateOpener.openCameraWithRetry(
+                cameraId,
+                camera2DeviceCloser,
+                isForegroundObserver
+            )
+        if (result.cameraState == null) {
+            return OpenVirtualCameraResult.Error(result.errorCode)
+        }
+        return OpenVirtualCameraResult.Success(
+            activeCamera =
+                ActiveCamera(
+                    androidCameraState = result.cameraState,
+                    allCameraIds = (sharedCameraIds + cameraId).toSet(),
+                    scope = scope,
+                    closeCallback = { activeCamera -> queue.tryEmit(RequestClose(activeCamera)) },
+                )
+        )
+    }
+
+    private suspend fun connectPendingRequestOpens(cameraIds: List<CameraId>) {
+        val requestOpensToRemove = mutableListOf<RequestOpen>()
+        val requestOpens =
+            pendingRequestOpens.filter { cameraIds.contains(it.virtualCamera.cameraId) }
+        for (request in requestOpens) {
+            // If the request is shared with this pending request, then we should be
+            // able to connect this pending request too, since we don't allow
+            // overlapping.
+            val allCameraIds = listOf(request.virtualCamera.cameraId) + request.sharedCameraIds
+            check(allCameraIds.all { cameraId -> activeCameras.any { it.cameraId == cameraId } })
+
+            val realCamera = activeCameras.find { it.cameraId == request.virtualCamera.cameraId }
+            checkNotNull(realCamera)
+            realCamera.connectTo(request.virtualCamera)
+            requestOpensToRemove.add(request)
+        }
+        pendingRequestOpens.removeAll(requestOpensToRemove)
+    }
+
+    private inline fun <T> List<T>.firstFromIndexOrNull(
+        index: Int,
+        predicate: (T) -> Boolean
+    ): Int? {
+        for (i in index..size - 1) {
+            if (predicate(get(i))) {
+                return i
+            }
+        }
+        return null
+    }
+
+    private fun <T> MutableList<T>.removeIndices(indices: Set<Int>): List<T> {
+        val removedElements = mutableListOf<T>()
+        for (idx in indices.sorted()) {
+            removedElements.add(removeAt(idx - removedElements.size))
+        }
+        return removedElements
+    }
+
+    private sealed interface OpenVirtualCameraResult {
+        data class Success(val activeCamera: ActiveCamera) : OpenVirtualCameraResult
+
+        data class Error(val lastCameraError: CameraError?) : OpenVirtualCameraResult
+    }
+}
+
 // TODO: b/307396261 - A queue depth of 64 was deemed necessary in b/276051078 and b/307396261 where
 //  a flood of requests can cause the queue depth to grow larger than anticipated. Rewrite the
 //  camera manager such that it handles these abnormal scenarios more robustly.
@@ -415,7 +780,9 @@
                     androidCameraState = result.cameraState,
                     allCameraIds = (sharedCameraIds + cameraId).toSet(),
                     scope = scope,
-                    channel = requestQueue
+                    closeCallback = { activeCamera ->
+                        requestQueue.trySend(RequestClose(activeCamera)).isSuccess
+                    }
                 )
         )
     }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/RetryingCameraStateOpener.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/RetryingCameraStateOpener.kt
index 14b60a78..66abe1d 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/RetryingCameraStateOpener.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/RetryingCameraStateOpener.kt
@@ -65,6 +65,19 @@
     suspend fun awaitAvailableCamera(cameraId: CameraId, timeoutMillis: Long): Boolean
 }
 
+internal interface RetryingCameraStateOpener {
+    suspend fun openCameraWithRetry(
+        cameraId: CameraId,
+        camera2DeviceCloser: Camera2DeviceCloser,
+        isForegroundObserver: (Unit) -> Boolean = { _ -> true },
+    ): OpenCameraResult
+
+    fun openAndAwaitCameraWithRetry(
+        cameraId: CameraId,
+        camera2DeviceCloser: Camera2DeviceCloser,
+    ): AwaitOpenCameraResult
+}
+
 internal interface DevicePolicyManagerWrapper {
     val camerasDisabled: Boolean
 }
@@ -100,7 +113,7 @@
     CameraAvailabilityMonitor {
 
     override suspend fun awaitAvailableCamera(cameraId: CameraId, timeoutMillis: Long): Boolean =
-        withTimeoutOrNull(timeoutMillis) { awaitAvailableCamera(cameraId) } ?: false
+        withTimeoutOrNull(timeoutMillis) { awaitAvailableCamera(cameraId) } == true
 
     private suspend fun awaitAvailableCamera(cameraId: CameraId) =
         suspendCancellableCoroutine { continuation ->
@@ -227,7 +240,7 @@
     }
 }
 
-internal class RetryingCameraStateOpener
+internal class RetryingCameraStateOpenerImpl
 @Inject
 constructor(
     private val cameraStateOpener: CameraStateOpener,
@@ -237,11 +250,11 @@
     private val devicePolicyManager: DevicePolicyManagerWrapper,
     private val audioRestrictionController: AudioRestrictionController,
     private val cameraInteropConfig: CameraPipe.CameraInteropConfig?
-) {
-    internal suspend fun openCameraWithRetry(
+) : RetryingCameraStateOpener {
+    override suspend fun openCameraWithRetry(
         cameraId: CameraId,
         camera2DeviceCloser: Camera2DeviceCloser,
-        isForegroundObserver: (Unit) -> Boolean = { _ -> true },
+        isForegroundObserver: (Unit) -> Boolean,
     ): OpenCameraResult {
         val requestTimestamp = Timestamps.now(timeSource)
         var attempts = 0
@@ -318,7 +331,7 @@
         }
     }
 
-    internal fun openAndAwaitCameraWithRetry(
+    override fun openAndAwaitCameraWithRetry(
         cameraId: CameraId,
         camera2DeviceCloser: Camera2DeviceCloser,
     ): AwaitOpenCameraResult {
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt
index a92c954..47af0bf 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/Camera2Component.kt
@@ -17,6 +17,7 @@
 package androidx.camera.camera2.pipe.config
 
 import android.hardware.camera2.CameraManager
+import android.util.Log
 import androidx.camera.camera2.pipe.CameraBackend
 import androidx.camera.camera2.pipe.CameraController
 import androidx.camera.camera2.pipe.CameraGraph
@@ -41,6 +42,9 @@
 import androidx.camera.camera2.pipe.compat.Camera2MetadataProvider
 import androidx.camera.camera2.pipe.compat.CameraAvailabilityMonitor
 import androidx.camera.camera2.pipe.compat.CameraOpener
+import androidx.camera.camera2.pipe.compat.PruningCamera2DeviceManager
+import androidx.camera.camera2.pipe.compat.RetryingCameraStateOpener
+import androidx.camera.camera2.pipe.compat.RetryingCameraStateOpenerImpl
 import androidx.camera.camera2.pipe.compat.StandardCamera2CaptureSequenceProcessorFactory
 import androidx.camera.camera2.pipe.core.Threads
 import androidx.camera.camera2.pipe.graph.GraphListener
@@ -62,14 +66,14 @@
     @DefaultCameraBackend
     abstract fun bindCameraPipeCameraBackend(camera2Backend: Camera2Backend): CameraBackend
 
-    @Binds
-    abstract fun bindCamera2DeviceManager(
-        camera2DeviceManager: Camera2DeviceManagerImpl
-    ): Camera2DeviceManager
-
     @Binds abstract fun bindCameraOpener(camera2CameraOpener: Camera2CameraOpener): CameraOpener
 
     @Binds
+    abstract fun bindRetryingCameraStateOpener(
+        retryingCameraStateOpenerImpl: RetryingCameraStateOpenerImpl
+    ): RetryingCameraStateOpener
+
+    @Binds
     abstract fun bindCameraMetadataProvider(
         camera2MetadataCache: Camera2MetadataCache
     ): Camera2MetadataProvider
@@ -93,6 +97,24 @@
     abstract fun bindAudioRestrictionController(
         audioRestrictionController: AudioRestrictionControllerImpl
     ): AudioRestrictionController
+
+    companion object {
+        // TODO: b/369684573 - Enable PruningCamera2DeviceManager for all users.
+        const val CAMERA_PIPE_MH_FLAG = "CameraPipeMH"
+        val ENABLE_PRUNING_DEVICE_MANAGER = Log.isLoggable(CAMERA_PIPE_MH_FLAG, Log.DEBUG)
+
+        @Provides
+        fun provideCamera2DeviceManager(
+            camera2DeviceManager: Provider<Camera2DeviceManagerImpl>,
+            pruningCamera2DeviceManager: Provider<PruningCamera2DeviceManager>,
+        ): Camera2DeviceManager {
+            return if (ENABLE_PRUNING_DEVICE_MANAGER) {
+                pruningCamera2DeviceManager.get()
+            } else {
+                camera2DeviceManager.get()
+            }
+        }
+    }
 }
 
 @Scope internal annotation class Camera2ControllerScope
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/core/PruningProcessingQueue.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/core/PruningProcessingQueue.kt
new file mode 100644
index 0000000..7721c94
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/core/PruningProcessingQueue.kt
@@ -0,0 +1,208 @@
+/*
+ * 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.core
+
+import kotlinx.atomicfu.atomic
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.async
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.selects.select
+import kotlinx.coroutines.supervisorScope
+
+/**
+ * PruningProcessingQueue is a data structure designed and optimized for parallel, high throughput,
+ * continuous element processing operations. It handles the sequential aggregation, pruning and
+ * processing of a running list of elements.
+ *
+ * PruningProcessingQueue is constructed and instructed with these notable parameters:
+ * - [prune] gets a mutable list of elements and is expected to trim, remove elements that can be
+ *   dropped, or reorder elements for those that have a higher priority. It is invoked whenever
+ *   there's a new batch of element ready to be processed.
+ * - [onUnprocessedElements] gets the list of elements that haven't been processed. It is invoked
+ *   when the coroutine scope is cancelled, or whenever there was an exception taken place during
+ *   processing.
+ * - [process] is continuously and sequentially invoked with the next element to process. It is
+ *   invoked only after the previous processing job is done.
+ *
+ * Example Usage:
+ * ```
+ * class MyClass(scope: CoroutineScope) {
+ *     private val processingQueue = ProcessingQueue<Int>(
+ *         onUnprocessedElements = ::onUnprocessedElements
+ *             prune = ::pruneInts
+ *             process = ::processInt
+ *         ).processIn(scope)
+ *
+ *     fun processAnInt(value: Int) {
+ *         processingQueue.emitChecked(value)
+ *     }
+ *
+ *     private fun pruneInts(items: MutableList<Int>) {
+ *         println("Pruning: $items")
+ *         items.removeAt(0)
+ *     }
+ *
+ *     private suspend fun processInt(item: Int) {
+ *         println("Processing: $item")
+ *     }
+ *
+ *     private fun onUnprocessedElements(items: List<Int>) {
+ *         println("Releasing unprocessed items: items")
+ *     }
+ * }
+ * ```
+ *
+ * This class is thread safe.
+ */
+internal class PruningProcessingQueue<T>(
+    val capacity: Int = Channel.UNLIMITED,
+    private val prune: (MutableList<T>) -> Unit = {},
+    private val onUnprocessedElements: (List<T>) -> Unit = {},
+    private val process: suspend (T) -> Unit,
+) {
+    private val started = atomic(false)
+    private val channel = Channel<T>(capacity = capacity, onUndeliveredElement = { queue.add(it) })
+    private val queue = ArrayDeque<T>()
+
+    /** Emit an element into the queue, suspending if the queue is at capacity. */
+    suspend fun emit(element: T) {
+        channel.send(element)
+    }
+
+    /** Emit an element into the queue, throwing an exception if it is closed or at capacity. */
+    fun emitChecked(element: T) {
+        val result = channel.trySend(element)
+        check(result.isSuccess) { "Failed to emit item to ProcessingQueue!: $result" }
+    }
+
+    /**
+     * Synchronously emit an element into the queue. Returns false if closed or if the queue is at
+     * capacity.
+     */
+    fun tryEmit(element: T): Boolean {
+        return channel.trySend(element).isSuccess
+    }
+
+    private suspend fun processingLoop() = supervisorScope {
+        var processDeferred: Deferred<Unit>? = null
+        var exitCause: Throwable? = null
+        while (isActive) {
+            try {
+                // In our processing loop, one of two events can occur:
+                //
+                // 1. We received a new element
+                // 2. `process` finished processing an element
+                //
+                // This means our workflow is driven by these two events. Whichever occurs, we'll
+                // handle the event, and see if we're ready to process a new element.
+                //
+                // Using select here effectively helps us sequence these two events, as it "selects"
+                // whichever comes first. This eliminates the need for locks, which reduces
+                // potential resource contention in high throughput scenarios.
+                select<Unit> {
+                    channel.onReceive {
+                        queue.add(it)
+
+                        // Optimization: When we receive elements to process, there may be multiple
+                        // elements ready to be received. To reduce the amount of `prune` calls,
+                        // here we continue receiving elements until we're unable to.
+                        var nextResult = channel.tryReceive()
+                        while (nextResult.isSuccess) {
+                            queue.add(nextResult.getOrThrow())
+                            nextResult = channel.tryReceive()
+                        }
+                        Log.debug { "PruningProcessingQueue: Pruning $queue" }
+                        prune(queue)
+                    }
+
+                    processDeferred?.onAwait { processDeferred = null }
+                }
+            } catch (throwable: Throwable) {
+                Log.error(throwable) { "Encountered exception during processing" }
+                exitCause = throwable
+                break
+            }
+
+            if (queue.isEmpty() || processDeferred != null) continue
+
+            val elementToProcess = queue.first()
+            val deferred = async {
+                Log.debug { "PruningProcessingQueue: Processing $elementToProcess" }
+                process(elementToProcess)
+            }
+            if (deferred.isCancelled) {
+                // If the Job is already cancelled, the CoroutineScope may have been cancelled.
+                Log.info { "Unable to process $elementToProcess due to Job cancellation" }
+                break
+            }
+            queue.removeFirst()
+            processDeferred = deferred
+        }
+
+        closeAndReleaseUnprocessedElements(exitCause)
+        exitCause?.let { throw it }
+    }
+
+    private fun closeAndReleaseUnprocessedElements(cause: Throwable?) {
+        // If we reach here, it means the scope that was driving the processing loop has been
+        // cancelled. It means that the last call to `process` has exited. The first time
+        // that channel.close() is called, the `onUndeliveredElement` handler will be invoked
+        // with the item that was pending for delivery. This, however, does not include *all*
+        // of the items, and we may need to iterate and handle the remaining items that may
+        // still be in the channel.
+        if (channel.close(cause)) {
+            // After closing the channel, there may be remaining items in the channel that were sent
+            // after the receiving scope was closed. Read these items out and send them to the
+            // onUnprocessedElements handler.
+            var nextResult = channel.tryReceive()
+            while (nextResult.isSuccess) {
+                queue.add(nextResult.getOrThrow())
+                nextResult = channel.tryReceive()
+            }
+
+            // Synchronously invoke the onUnprocessedElements handler with the remaining items.
+            if (queue.isNotEmpty()) {
+                onUnprocessedElements(queue.toMutableList())
+                queue.clear()
+            }
+        }
+    }
+
+    internal companion object {
+        /** Launch the processing loop in the provided processing scope. */
+        fun <T> PruningProcessingQueue<T>.processIn(
+            scope: CoroutineScope,
+        ): PruningProcessingQueue<T> {
+            check(started.compareAndSet(expect = false, update = true)) {
+                "PruningProcessingQueue cannot be re-started!"
+            }
+
+            // Launch the processing loop in the provided scope.
+            val job = scope.launch { processingLoop() }
+
+            // If the scope is already cancelled, then `process` will never be invoked. To ensure
+            // items are released, attempt to close the channel and release any remaining items.
+            if (job.isCancelled) {
+                closeAndReleaseUnprocessedElements(null)
+            }
+            return this
+        }
+    }
+}
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/Camera2DeviceManagerTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/Camera2DeviceManagerTest.kt
new file mode 100644
index 0000000..2ccb5c5
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/Camera2DeviceManagerTest.kt
@@ -0,0 +1,584 @@
+/*
+ * Copyright 2025 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.compat
+
+import android.content.Context
+import android.content.pm.PackageManager.PERMISSION_GRANTED
+import android.hardware.camera2.CameraDevice
+import android.os.Build
+import androidx.camera.camera2.pipe.CameraId
+import androidx.camera.camera2.pipe.core.Permissions
+import androidx.camera.camera2.pipe.core.TimeSource
+import androidx.camera.camera2.pipe.core.TimestampNs
+import androidx.camera.camera2.pipe.graph.GraphListener
+import androidx.camera.camera2.pipe.internal.CameraErrorListener
+import androidx.camera.camera2.pipe.testing.FakeCamera2MetadataProvider
+import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
+import androidx.camera.camera2.pipe.testing.FakeThreads
+import androidx.camera.camera2.pipe.testing.RobolectricCameraPipeTestRunner
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertIs
+import kotlin.test.assertIsNot
+import kotlin.test.assertNotNull
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+import org.robolectric.annotation.Config
+
+@RunWith(RobolectricCameraPipeTestRunner::class)
+@Config(minSdk = Build.VERSION_CODES.M)
+@OptIn(ExperimentalCoroutinesApi::class)
+internal class PruningCamera2DeviceManagerImplTest {
+    private val testScope = TestScope()
+
+    private val fakeContext: Context = mock()
+    private val fakePermissions = Permissions(fakeContext)
+    private val fakeCamera2DeviceCloser: Camera2DeviceCloser = mock()
+    private val fakeThreads =
+        FakeThreads.fromDispatcher(StandardTestDispatcher(testScope.testScheduler))
+    private val cameraId0 = CameraId("0")
+    private val cameraId1 = CameraId("1")
+    private val fakeCameraDevice0: CameraDevice = mock()
+    private val fakeCameraDevice1: CameraDevice = mock()
+    private val fakeTimeSource: TimeSource = mock()
+    private val fakeCameraErrorListener: CameraErrorListener = mock()
+    val fakeAudioRestrictionController: AudioRestrictionController = mock()
+
+    private val fakeRetryingCameraStateOpener =
+        object : RetryingCameraStateOpener {
+            var androidCameraStates = mutableListOf<AndroidCameraState>()
+
+            override suspend fun openCameraWithRetry(
+                cameraId: CameraId,
+                camera2DeviceCloser: Camera2DeviceCloser,
+                isForegroundObserver: (Unit) -> Boolean
+            ): OpenCameraResult {
+                val fakeCameraMetadata = FakeCameraMetadata(cameraId = cameraId)
+                val fakeCamera2MetadataProvider =
+                    FakeCamera2MetadataProvider(mapOf(cameraId to fakeCameraMetadata))
+                val fakeCamera2Quirks = Camera2Quirks(fakeCamera2MetadataProvider)
+                val fakeAndroidCameraState =
+                    AndroidCameraState(
+                        cameraId,
+                        fakeCameraMetadata,
+                        1,
+                        TimestampNs(0L),
+                        fakeTimeSource,
+                        fakeCameraErrorListener,
+                        fakeCamera2DeviceCloser,
+                        fakeCamera2Quirks,
+                        fakeThreads,
+                        fakeAudioRestrictionController,
+                    )
+                androidCameraStates.add(fakeAndroidCameraState)
+                return OpenCameraResult(fakeAndroidCameraState, null)
+            }
+
+            override fun openAndAwaitCameraWithRetry(
+                cameraId: CameraId,
+                camera2DeviceCloser: Camera2DeviceCloser
+            ): AwaitOpenCameraResult {
+                TODO("Not yet implemented")
+            }
+        }
+    private val fakeCamera2ErrorProcessor = Camera2ErrorProcessor()
+
+    private val deviceManager =
+        PruningCamera2DeviceManager(
+            fakePermissions,
+            fakeRetryingCameraStateOpener,
+            fakeCamera2DeviceCloser,
+            fakeCamera2ErrorProcessor,
+            fakeThreads,
+        )
+
+    private val fakeGraphListener1: GraphListener = mock()
+    private val fakeGraphListener2: GraphListener = mock()
+    private val fakeGraphListener3: GraphListener = mock()
+    private val fakeGraphListener4: GraphListener = mock()
+
+    init {
+        whenever(fakeContext.checkSelfPermission(any())).thenReturn(PERMISSION_GRANTED)
+        whenever(fakeCameraDevice0.id).thenReturn(cameraId0.value)
+        whenever(fakeCameraDevice1.id).thenReturn(cameraId1.value)
+    }
+
+    @Test
+    fun canOpenAndCloseCamera() =
+        testScope.runTest {
+            deviceManager.open(cameraId0, emptyList(), fakeGraphListener1, false) { true }
+            advanceUntilIdle()
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 1)
+            val androidCameraState = fakeRetryingCameraStateOpener.androidCameraStates.first()
+
+            deviceManager.close(cameraId0)
+            advanceUntilIdle()
+
+            assertIs<CameraStateClosed>(androidCameraState.state.value)
+        }
+
+    @Test
+    fun cameraIsClosedAfterDisconnect() =
+        testScope.runTest {
+            val virtualCamera =
+                deviceManager.open(cameraId0, emptyList(), fakeGraphListener1, false) { true }
+            assertNotNull(virtualCamera)
+            advanceUntilIdle()
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 1)
+            val androidCameraState = fakeRetryingCameraStateOpener.androidCameraStates.first()
+
+            virtualCamera.disconnect()
+            advanceUntilIdle()
+
+            assertIs<CameraStateClosed>(androidCameraState.state.value)
+        }
+
+    @Test
+    fun cameraIsReusedWhenTheSameCameraIsOpened() =
+        testScope.runTest {
+            val virtualCamera1 =
+                deviceManager.open(cameraId0, emptyList(), fakeGraphListener1, false) { true }
+            assertNotNull(virtualCamera1)
+            advanceUntilIdle()
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 1)
+
+            // Simulate camera graph close by disconnecting the virtual camera.
+            virtualCamera1.disconnect()
+
+            // Simulate a small delay for capture session switching, but short enough to keep the
+            // camera opened.
+            advanceTimeBy(100)
+
+            // Now open the same camera again.
+            val virtualCamera2 =
+                deviceManager.open(cameraId0, emptyList(), fakeGraphListener2, false) { true }
+            assertNotNull(virtualCamera2)
+            advanceUntilIdle()
+
+            // The first virtual camera should be disconnected.
+            val virtualCameraState1 = virtualCamera1.value
+            assertIs<CameraStateClosed>(virtualCameraState1)
+
+            // There shouldn't be any new camera open calls, and thus we should be reusing the same
+            // Android camera state.
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 1)
+        }
+
+    @Test
+    fun cameraIsNotReusedWhenTheSameCameraIsOpenedAfterLongDelay() =
+        testScope.runTest {
+            val virtualCamera1 =
+                deviceManager.open(cameraId0, emptyList(), fakeGraphListener1, false) { true }
+            assertNotNull(virtualCamera1)
+            advanceUntilIdle()
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 1)
+
+            // Simulate camera graph close by disconnecting the virtual camera.
+            virtualCamera1.disconnect()
+
+            // Simulate a long delay such that the camera should be closed.
+            advanceTimeBy(3000)
+
+            // Now open the same camera again.
+            val virtualCamera2 =
+                deviceManager.open(cameraId0, emptyList(), fakeGraphListener2, false) { true }
+            assertNotNull(virtualCamera2)
+            advanceUntilIdle()
+
+            // The first virtual camera should be disconnected.
+            val virtualCameraState = virtualCamera1.value
+            assertIs<CameraStateClosed>(virtualCameraState)
+
+            // Given the long delay, we should be reopening the camera, and thus we would have 2
+            // camera open calls with 2 Android camera states.
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 2)
+        }
+
+    @Test
+    fun cameraIsClosedOnlyOnceWhenMultipleRequestClose() =
+        testScope.runTest {
+            val virtualCamera =
+                deviceManager.open(cameraId0, emptyList(), fakeGraphListener1, false) { true }
+            assertNotNull(virtualCamera)
+            advanceUntilIdle()
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 1)
+            val androidCameraState = fakeRetryingCameraStateOpener.androidCameraStates.first()
+            androidCameraState.onOpened(fakeCameraDevice0)
+            advanceUntilIdle()
+
+            deviceManager.close(cameraId0)
+            advanceUntilIdle()
+
+            deviceManager.closeAll()
+            advanceUntilIdle()
+
+            deviceManager.close(cameraId0)
+            advanceUntilIdle()
+
+            verify(fakeCamera2DeviceCloser, times(1))
+                .closeCamera(
+                    any(),
+                    eq(fakeCameraDevice0),
+                    eq(androidCameraState),
+                    any(),
+                    any(),
+                    any()
+                )
+        }
+
+    @Test
+    fun closingUnopenedCameraIsIgnored() =
+        testScope.runTest {
+            val virtualCamera =
+                deviceManager.open(cameraId0, emptyList(), fakeGraphListener1, false) { true }
+            assertNotNull(virtualCamera)
+            advanceUntilIdle()
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 1)
+            val androidCameraState = fakeRetryingCameraStateOpener.androidCameraStates.first()
+            androidCameraState.onOpened(fakeCameraDevice0)
+            advanceUntilIdle()
+
+            assertIs<CameraStateOpen>(androidCameraState.state.value)
+            assertIs<CameraStateOpen>(virtualCamera.value)
+
+            // Close camera 1, which was never opened.
+            deviceManager.close(cameraId1)
+            advanceUntilIdle()
+
+            // Camera 0 should remain open.
+            assertIs<CameraStateOpen>(androidCameraState.state.value)
+            assertIs<CameraStateOpen>(virtualCamera.value)
+        }
+
+    @Test
+    fun openingDifferentCameraClosesThePreviousOne() =
+        testScope.runTest {
+            val virtualCamera1 =
+                deviceManager.open(cameraId0, emptyList(), fakeGraphListener1, false) { true }
+            assertNotNull(virtualCamera1)
+            advanceUntilIdle()
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 1)
+            val androidCameraState1 = fakeRetryingCameraStateOpener.androidCameraStates.first()
+            assertEquals(androidCameraState1.cameraId, cameraId0)
+
+            // Now open a different camera. To do so, the previous camera would have to be closed.
+            val virtualCamera2 =
+                deviceManager.open(cameraId1, emptyList(), fakeGraphListener2, false) { true }
+            assertNotNull(virtualCamera2)
+            advanceUntilIdle()
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 2)
+            val androidCameraState2 = fakeRetryingCameraStateOpener.androidCameraStates.last()
+            assertEquals(androidCameraState2.cameraId, cameraId1)
+
+            // The previous camera should be closed.
+            assertIs<CameraStateClosed>(androidCameraState1.state.value)
+        }
+
+    @Test
+    fun allCamerasShouldBeOpenedBeforeConnectingWhenOpeningConcurrentCameras() =
+        testScope.runTest {
+            val virtualCamera1 =
+                deviceManager.open(cameraId0, listOf(cameraId1), fakeGraphListener1, false) { true }
+            assertNotNull(virtualCamera1)
+            // Advance time by just a bit to allow coroutines to finish but not closing the camera.
+            advanceTimeBy(100)
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 1)
+            val androidCameraState1 = fakeRetryingCameraStateOpener.androidCameraStates.first()
+            androidCameraState1.onOpened(fakeCameraDevice0)
+            advanceTimeBy(100)
+
+            // Since camera 1 is not yet opened, the virtual camera should not be connected yet.
+            var virtualCameraState1 = virtualCamera1.value
+            assertIsNot<CameraStateOpen>(virtualCameraState1)
+
+            val virtualCamera2 =
+                deviceManager.open(cameraId1, listOf(cameraId0), fakeGraphListener2, false) { true }
+            assertNotNull(virtualCamera2)
+            advanceTimeBy(100)
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 2)
+            val androidCameraState2 = fakeRetryingCameraStateOpener.androidCameraStates.last()
+            androidCameraState2.onOpened(fakeCameraDevice1)
+            advanceUntilIdle()
+
+            virtualCameraState1 = virtualCamera1.value
+            assertIs<CameraStateOpen>(virtualCameraState1)
+            val virtualCameraState2 = virtualCamera2.value
+            assertIs<CameraStateOpen>(virtualCameraState2)
+        }
+
+    @Test
+    fun singleCameraShouldBeClosedWhenConcurrentCamerasAreRequested() =
+        testScope.runTest {
+            // First open camera 0 in regular (single) camera mode.
+            val virtualCamera1 =
+                deviceManager.open(cameraId0, emptyList(), fakeGraphListener1, false) { true }
+            assertNotNull(virtualCamera1)
+            advanceUntilIdle()
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 1)
+            val androidCameraState1 = fakeRetryingCameraStateOpener.androidCameraStates.first()
+            assertEquals(androidCameraState1.cameraId, cameraId0)
+
+            // Now open camera 0, with camera 1 as a shared camera.
+            val virtualCamera2 =
+                deviceManager.open(cameraId0, listOf(cameraId1), fakeGraphListener2, false) { true }
+            assertNotNull(virtualCamera2)
+            advanceTimeBy(100)
+
+            // Even though we request the same camera, the single camera 0 cannot be reused, and
+            // should thus be closed.
+            assertIs<CameraStateClosed>(androidCameraState1.state.value)
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 2)
+            val androidCameraState2 = fakeRetryingCameraStateOpener.androidCameraStates.last()
+            androidCameraState2.onOpened(fakeCameraDevice0)
+            advanceTimeBy(100)
+
+            val virtualCamera3 =
+                deviceManager.open(cameraId1, listOf(cameraId0), fakeGraphListener3, false) { true }
+            assertNotNull(virtualCamera3)
+            advanceTimeBy(100)
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 3)
+            val androidCameraState3 = fakeRetryingCameraStateOpener.androidCameraStates.last()
+            androidCameraState3.onOpened(fakeCameraDevice1)
+            advanceUntilIdle()
+
+            // We should still succeed in opening the concurrent cameras.
+            val virtualCameraState2 = virtualCamera2.value
+            assertIs<CameraStateOpen>(virtualCameraState2)
+            val virtualCameraState3 = virtualCamera3.value
+            assertIs<CameraStateOpen>(virtualCameraState3)
+        }
+
+    @Test
+    fun onlyOneCameraIsClosedWhenGoingFromConcurrentCameraToSingleCamera() =
+        testScope.runTest {
+            // First, open concurrent cameras with camera 0 and camera1.
+            val virtualCamera1 =
+                deviceManager.open(cameraId0, listOf(cameraId1), fakeGraphListener1, false) { true }
+            assertNotNull(virtualCamera1)
+            // Advance time by just a bit to allow coroutines to finish but not closing the camera.
+            advanceTimeBy(100)
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 1)
+            val androidCameraState1 = fakeRetryingCameraStateOpener.androidCameraStates.first()
+            androidCameraState1.onOpened(fakeCameraDevice0)
+            advanceTimeBy(100)
+
+            val virtualCamera2 =
+                deviceManager.open(cameraId1, listOf(cameraId0), fakeGraphListener2, false) { true }
+            assertNotNull(virtualCamera2)
+            advanceTimeBy(100)
+
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 2)
+            val androidCameraState2 = fakeRetryingCameraStateOpener.androidCameraStates.last()
+            androidCameraState2.onOpened(fakeCameraDevice1)
+            advanceUntilIdle()
+
+            // Then, open camera 1 in regular (single) camera mode.
+            val virtualCamera3 =
+                deviceManager.open(cameraId1, emptyList(), fakeGraphListener3, false) { true }
+            assertNotNull(virtualCamera3)
+            advanceUntilIdle()
+            assertIs<CameraStateOpen>(virtualCamera3.value)
+
+            // No new cameras should be opened
+            assertEquals(fakeRetryingCameraStateOpener.androidCameraStates.size, 2)
+
+            // Camera 0 should be closed, while camera 1 should remain open.
+            assertIs<CameraStateClosed>(androidCameraState1.state.value)
+            assertIs<CameraStateOpen>(androidCameraState2.state.value)
+        }
+
+    @Test
+    fun prunePrioritizesRequestCloseAndOrdersAreRetained() =
+        testScope.runTest {
+            val requestOpen1 = createFakeRequestOpen(cameraId0, emptyList(), fakeGraphListener1)
+            val requestClose1 = createFakeRequestClose(cameraId0)
+            var requestList =
+                mutableListOf<CameraRequest>(
+                    RequestCloseById(cameraId0),
+                    requestClose1,
+                )
+            deviceManager.prune(requestList)
+            assertEquals(requestList.first(), requestClose1)
+
+            val requestOpen2 = createFakeRequestOpen(cameraId1, emptyList(), fakeGraphListener2)
+            val requestClose2 = createFakeRequestClose(cameraId1)
+            requestList =
+                mutableListOf<CameraRequest>(
+                    requestOpen1,
+                    RequestCloseById(cameraId0),
+                    RequestCloseById(cameraId1),
+                    requestOpen2,
+                    requestClose1,
+                    requestClose2,
+                )
+            deviceManager.prune(requestList)
+            assertEquals(requestList[0], requestClose1)
+            assertEquals(requestList[1], requestClose2)
+        }
+
+    @Test
+    fun pruneRequestCloseAllSupersedesAllRequests() =
+        testScope.runTest {
+            val requestList =
+                mutableListOf<CameraRequest>(
+                    createFakeRequestOpen(cameraId0, emptyList(), fakeGraphListener1),
+                    RequestCloseById(cameraId0),
+                    createFakeRequestOpen(cameraId1, emptyList(), fakeGraphListener2),
+                    createFakeRequestClose(cameraId1),
+                    RequestCloseAll,
+                    RequestCloseAll,
+                    createFakeRequestOpen(cameraId0, emptyList(), fakeGraphListener1),
+                )
+            deviceManager.prune(requestList)
+            assertIs<RequestCloseAll>(requestList[0])
+            // The former RequestCloseAll should be superseded, and thus we should only have one.
+            assertIsNot<RequestCloseAll>(requestList[1])
+        }
+
+    @Test
+    fun pruneMultipleRequestOpensWithSameCameraId() =
+        testScope.runTest {
+            val requestOpen1 = createFakeRequestOpen(cameraId0, emptyList(), fakeGraphListener1)
+            val requestOpen2 =
+                createFakeRequestOpen(cameraId0, listOf(cameraId1), fakeGraphListener2)
+            val requestOpen3 = createFakeRequestOpen(cameraId0, emptyList(), fakeGraphListener3)
+            var requestList =
+                mutableListOf<CameraRequest>(
+                    RequestCloseById(cameraId1),
+                    requestOpen1,
+                    createFakeRequestClose(cameraId1),
+                    requestOpen2,
+                    requestOpen3,
+                )
+            deviceManager.prune(requestList)
+            val remainingRequestOpens = requestList.filterIsInstance<RequestOpen>()
+            assertEquals(remainingRequestOpens.size, 1)
+            assertEquals(remainingRequestOpens.first(), requestOpen3)
+        }
+
+    @Test
+    fun pruneMultipleRequestOpensWithDifferentCameraId() =
+        testScope.runTest {
+            val requestOpen1 = createFakeRequestOpen(cameraId0, emptyList(), fakeGraphListener1)
+            val requestOpen2 = createFakeRequestOpen(cameraId1, emptyList(), fakeGraphListener2)
+            val requestOpen3 =
+                createFakeRequestOpen(cameraId1, listOf(cameraId0), fakeGraphListener3)
+            val requestOpen4 =
+                createFakeRequestOpen(cameraId0, listOf(cameraId1), fakeGraphListener4)
+            val requestList =
+                mutableListOf<CameraRequest>(
+                    RequestCloseById(cameraId1),
+                    requestOpen1,
+                    createFakeRequestClose(cameraId1),
+                    requestOpen2,
+                    requestOpen3,
+                    requestOpen4,
+                )
+            deviceManager.prune(requestList)
+            val remainingRequestOpens = requestList.filterIsInstance<RequestOpen>()
+            // 1. requestOpen1 should be pruned by requestOpen2 since their camera IDs are
+            //    different, and they don't share the set of concurrent cameras.
+            // 2. requestOpen2 should be pruned by requestOpen3 since their camera IDs are the same.
+            // 3. requestOpen3 and requestOpen4 should both be kept since they same the set of
+            //    concurrent cameras.
+            assertEquals(remainingRequestOpens.size, 2)
+            assertEquals(remainingRequestOpens[0], requestOpen3)
+            assertEquals(remainingRequestOpens[1], requestOpen4)
+        }
+
+    @Test
+    fun pruneRequestCloseById() =
+        testScope.runTest {
+            val requestList =
+                mutableListOf<CameraRequest>(
+                    createFakeRequestOpen(cameraId0, emptyList(), fakeGraphListener1),
+                    RequestCloseById(cameraId0),
+                    createFakeRequestOpen(cameraId1, listOf(cameraId0), fakeGraphListener2),
+                    createFakeRequestOpen(cameraId0, listOf(cameraId1), fakeGraphListener3),
+                    RequestCloseById(cameraId1),
+                )
+            deviceManager.prune(requestList)
+            // 1. The first RequestOpen should be pruned by RequestCloseById(cameraId0)
+            // 2. The latter RequestOpen for concurrent cameras should be pruned altogether by
+            //    RequestCloseById(cameraId1), because by closing cameraId1, neither would succeed.
+            assertEquals(requestList.size, 2)
+            assertIs<RequestCloseById>(requestList[0])
+            assertEquals((requestList[0] as RequestCloseById).activeCameraId, cameraId0)
+            assertIs<RequestCloseById>(requestList[1])
+            assertEquals((requestList[1] as RequestCloseById).activeCameraId, cameraId1)
+        }
+
+    private fun createFakeRequestOpen(
+        cameraId: CameraId,
+        sharedCameraIds: List<CameraId>,
+        graphListener: GraphListener,
+    ): RequestOpen {
+        val virtualCamera = VirtualCameraState(cameraId, graphListener, fakeThreads.globalScope)
+        return RequestOpen(virtualCamera, sharedCameraIds, graphListener, false, { true })
+    }
+
+    private fun createFakeRequestClose(
+        cameraId: CameraId,
+        allCameraIds: Set<CameraId> = setOf(cameraId),
+    ): RequestClose {
+        val fakeCameraMetadata = FakeCameraMetadata(cameraId = cameraId)
+        val fakeCamera2MetadataProvider =
+            FakeCamera2MetadataProvider(mapOf(cameraId to fakeCameraMetadata))
+        val fakeCamera2Quirks = Camera2Quirks(fakeCamera2MetadataProvider)
+        val fakeAndroidCameraState =
+            AndroidCameraState(
+                cameraId,
+                fakeCameraMetadata,
+                1,
+                TimestampNs(0),
+                fakeTimeSource,
+                fakeCameraErrorListener,
+                fakeCamera2DeviceCloser,
+                fakeCamera2Quirks,
+                fakeThreads,
+                fakeAudioRestrictionController,
+            )
+        val fakeActiveCamera =
+            ActiveCamera(fakeAndroidCameraState, allCameraIds, fakeThreads.globalScope) {}
+        return RequestClose(fakeActiveCamera)
+    }
+}
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/RetryingCameraStateOpenerTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/RetryingCameraStateOpenerTest.kt
index 7100e1d..3fc64bc 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/RetryingCameraStateOpenerTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/RetryingCameraStateOpenerTest.kt
@@ -145,7 +145,7 @@
     private val audioRestrictionController = FakeAudioRestrictionController()
 
     private val retryingCameraStateOpener =
-        RetryingCameraStateOpener(
+        RetryingCameraStateOpenerImpl(
             cameraStateOpener,
             fakeCameraErrorListener,
             cameraAvailabilityMonitor,
@@ -158,7 +158,7 @@
     @Test
     fun testShouldRetryReturnsTrueWithinTimeout() {
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_IN_USE,
                     1,
                     DurationNs(1_000_000_000L), // 1 second
@@ -172,7 +172,7 @@
     @Test
     fun testShouldRetryReturnsFalseWhenTimeoutExpires() {
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_IN_USE,
                     1,
                     DurationNs(3600_000_000_000L), // 3600 seconds (60 minutes)
@@ -186,7 +186,7 @@
     @Test
     fun testShouldRetryUndetermined() {
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_UNDETERMINED,
                     1,
                     DurationNs(1_000_000_000L), // 1 second
@@ -198,7 +198,7 @@
 
         // The second retry attempt should fail.
         val secondRetry =
-            RetryingCameraStateOpener.shouldRetry(
+            RetryingCameraStateOpenerImpl.shouldRetry(
                 ERROR_UNDETERMINED,
                 2,
                 DurationNs(1_000_000_001L),
@@ -211,7 +211,7 @@
     @Test
     fun testShouldRetryCameraInUse() {
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_IN_USE,
                     1,
                     DurationNs(1_000_000_000L), // 1 second
@@ -223,7 +223,7 @@
 
         // The second retry attempt should fail if SDK version < S, and succeed otherwise.
         val secondRetry =
-            RetryingCameraStateOpener.shouldRetry(
+            RetryingCameraStateOpenerImpl.shouldRetry(
                 ERROR_CAMERA_IN_USE,
                 2,
                 DurationNs(1_000_000_001L),
@@ -240,7 +240,7 @@
     @Test
     fun testShouldRetryCameraLimitExceeded() {
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_LIMIT_EXCEEDED,
                     1,
                     DurationNs(1_000_000_000L), // 1 second
@@ -252,7 +252,7 @@
 
         // Second attempt should succeed as well.
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_LIMIT_EXCEEDED,
                     2,
                     DurationNs(1_000_000_001L),
@@ -266,7 +266,7 @@
     @Test
     fun testShouldRetryOnceCameraDisabledWhenDpcCameraDisabled() {
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_DISABLED,
                     1,
                     DurationNs(1_000_000_000L), // 1 second
@@ -278,7 +278,7 @@
 
         // Second attempt should fail if camera is disabled.
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_DISABLED,
                     2,
                     DurationNs(1_000_000_001L),
@@ -292,7 +292,7 @@
     @Test
     fun testShouldRetryRepeatedlyCameraDisabledWhenDpcCameraEnabled() {
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_DISABLED,
                     1,
                     DurationNs(1_000_000_000L), // 1 second
@@ -304,7 +304,7 @@
 
         // Second attempt should success if camera is not disabled.
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_DISABLED,
                     2,
                     DurationNs(1_000_000_001L),
@@ -318,7 +318,7 @@
     @Test
     fun testShouldRetryCameraDevice() {
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     CameraError.ERROR_CAMERA_DEVICE,
                     1,
                     DurationNs(1_000_000_000L), // 1 second
@@ -330,7 +330,7 @@
 
         // Second attempt should succeed as well.
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     CameraError.ERROR_CAMERA_DEVICE,
                     2,
                     DurationNs(1_000_000_001L),
@@ -344,7 +344,7 @@
     @Test
     fun testShouldRetryCameraService() {
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_SERVICE,
                     1,
                     DurationNs(1_000_000_000L), // 1 second
@@ -356,7 +356,7 @@
 
         // Second attempt should succeed as well.
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_SERVICE,
                     2,
                     DurationNs(1_000_000_001L),
@@ -370,7 +370,7 @@
     @Test
     fun testShouldRetryCameraDisconnected() {
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_DISCONNECTED,
                     1,
                     DurationNs(1_000_000_000L), // 1 second
@@ -382,7 +382,7 @@
 
         // Second attempt should succeed as well.
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_DISCONNECTED,
                     2,
                     DurationNs(1_000_000_001L),
@@ -396,7 +396,7 @@
     @Test
     fun testShouldRetryIllegalArgumentException() {
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_ILLEGAL_ARGUMENT_EXCEPTION,
                     1,
                     DurationNs(1_000_000_000L), // 1 second
@@ -408,7 +408,7 @@
 
         // Second attempt should succeed as well.
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_ILLEGAL_ARGUMENT_EXCEPTION,
                     2,
                     DurationNs(1_000_000_001L),
@@ -422,7 +422,7 @@
     @Test
     fun testShouldRetrySecurityException() {
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_SECURITY_EXCEPTION,
                     1,
                     DurationNs(1_000_000_000L), // 1 second
@@ -434,7 +434,7 @@
 
         // Second attempt should fail.
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_SECURITY_EXCEPTION,
                     2,
                     DurationNs(1_000_000_001L),
@@ -448,7 +448,7 @@
     @Test
     fun testShouldNotRetryDoNotDisturbModeEnabled() {
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_DO_NOT_DISTURB_ENABLED,
                     1,
                     DurationNs(1_000_000_000L), // 1 second
@@ -466,7 +466,7 @@
             return
         }
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_IN_USE,
                     1,
                     DurationNs(1_000_000_000L),
@@ -477,7 +477,7 @@
             .isTrue()
 
         val secondRetry =
-            RetryingCameraStateOpener.shouldRetry(
+            RetryingCameraStateOpenerImpl.shouldRetry(
                 ERROR_CAMERA_IN_USE,
                 2,
                 DurationNs(30_000_000_000L), // 30s
@@ -498,7 +498,7 @@
             return
         }
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_LIMIT_EXCEEDED,
                     1,
                     DurationNs(1_000_000_000L),
@@ -509,7 +509,7 @@
             .isTrue()
 
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_LIMIT_EXCEEDED,
                     2,
                     DurationNs(30_000_000_000L), // 30s
@@ -527,7 +527,7 @@
             return
         }
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_DISCONNECTED,
                     1,
                     DurationNs(1_000_000_000L),
@@ -538,7 +538,7 @@
             .isTrue()
 
         assertThat(
-                RetryingCameraStateOpener.shouldRetry(
+                RetryingCameraStateOpenerImpl.shouldRetry(
                     ERROR_CAMERA_DISCONNECTED,
                     2,
                     DurationNs(30_000_000_000L), // 30s
@@ -552,7 +552,7 @@
     @Test
     fun testShouldActivateActiveResume() {
         assertThat(
-                RetryingCameraStateOpener.shouldActivateActiveResume(
+                RetryingCameraStateOpenerImpl.shouldActivateActiveResume(
                     isForeground = false,
                     errorCode = ERROR_CAMERA_IN_USE,
                 )
@@ -563,28 +563,28 @@
             // API level is [Q, S_V2], where multi-resume is supported and camera access priority
             // changes aren't properly notified.
             assertThat(
-                    RetryingCameraStateOpener.shouldActivateActiveResume(
+                    RetryingCameraStateOpenerImpl.shouldActivateActiveResume(
                         isForeground = true,
                         errorCode = ERROR_CAMERA_SERVICE,
                     )
                 )
                 .isFalse()
             assertThat(
-                    RetryingCameraStateOpener.shouldActivateActiveResume(
+                    RetryingCameraStateOpenerImpl.shouldActivateActiveResume(
                         isForeground = true,
                         errorCode = ERROR_CAMERA_IN_USE,
                     )
                 )
                 .isTrue()
             assertThat(
-                    RetryingCameraStateOpener.shouldActivateActiveResume(
+                    RetryingCameraStateOpenerImpl.shouldActivateActiveResume(
                         isForeground = true,
                         errorCode = ERROR_CAMERA_LIMIT_EXCEEDED,
                     )
                 )
                 .isTrue()
             assertThat(
-                    RetryingCameraStateOpener.shouldActivateActiveResume(
+                    RetryingCameraStateOpenerImpl.shouldActivateActiveResume(
                         isForeground = true,
                         errorCode = ERROR_CAMERA_DISCONNECTED,
                     )
@@ -592,14 +592,14 @@
                 .isTrue()
         } else {
             assertThat(
-                    RetryingCameraStateOpener.shouldActivateActiveResume(
+                    RetryingCameraStateOpenerImpl.shouldActivateActiveResume(
                         isForeground = true,
                         errorCode = ERROR_CAMERA_SERVICE,
                     )
                 )
                 .isFalse()
             assertThat(
-                    RetryingCameraStateOpener.shouldActivateActiveResume(
+                    RetryingCameraStateOpenerImpl.shouldActivateActiveResume(
                         isForeground = true,
                         errorCode = ERROR_CAMERA_IN_USE,
                     )
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/core/PruningProcessingQueueTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/core/PruningProcessingQueueTest.kt
new file mode 100644
index 0000000..680ed23
--- /dev/null
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/core/PruningProcessingQueueTest.kt
@@ -0,0 +1,334 @@
+/*
+ * 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.core
+
+import android.os.Build
+import androidx.camera.camera2.pipe.core.PruningProcessingQueue.Companion.processIn
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineExceptionHandler
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.robolectric.annotation.Config
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(JUnit4::class)
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+class PruningProcessingQueueTest {
+    private val testScope = TestScope()
+    private val processingScope =
+        CoroutineScope(
+            Job() +
+                StandardTestDispatcher(testScope.testScheduler) +
+                CoroutineExceptionHandler { _, throwable -> lastUncaughtException = throwable }
+        )
+
+    private var lastUncaughtException: Throwable? = null
+    private val pruningCalls = mutableListOf<List<Int>>()
+    private val processingCalls = mutableListOf<Int>()
+    private val unprocessedElements = mutableListOf<List<Int>>()
+    private val unprocessElementHandler: (List<Int>) -> Unit = {
+        unprocessedElements.add(it.toMutableList())
+    }
+
+    @Test
+    fun processingQueueBuffersItems() =
+        testScope.runTest {
+            val processingQueue =
+                PruningProcessingQueue<Int>(
+                    capacity = 2,
+                    onUnprocessedElements = unprocessElementHandler
+                ) {}
+
+            assertThat(processingQueue.tryEmit(1)).isTrue()
+            assertThat(processingQueue.tryEmit(2)).isTrue()
+            assertThat(processingQueue.tryEmit(3)).isFalse() // Queue is full (2 items)
+        }
+
+    @Test
+    fun processingQueueProcessesElements() =
+        testScope.runTest {
+            val processingQueue =
+                PruningProcessingQueue<Int>(
+                        capacity = 2,
+                        prune = { pruningCalls.add(it.toList()) },
+                        onUnprocessedElements = unprocessElementHandler
+                    ) {
+                        processingCalls.add(it)
+                    }
+                    .processIn(processingScope)
+
+            assertThat(processingQueue.tryEmit(1)).isTrue()
+            assertThat(processingQueue.tryEmit(2)).isTrue()
+            assertThat(processingQueue.tryEmit(3)).isFalse() // Queue is full
+
+            advanceUntilIdle() // Processing loop runs
+
+            // The pruning step should continue to receive elements whenever possible to reduce
+            // prune calls. It should therefore be called only once with [1, 2].
+            assertThat(pruningCalls).containsExactly(listOf(1, 2))
+            // Processing loop receives 1 and 2.
+            assertThat(processingCalls).containsExactly(1, 2)
+
+            processingScope.cancel()
+        }
+
+    @Test
+    fun processingQueuePrunesElements() =
+        testScope.runTest {
+            val processingQueue =
+                PruningProcessingQueue<Int>(
+                        prune = { elements ->
+                            pruningCalls.add(elements.toList())
+
+                            // Prune algorithm: A number supersedes all preceding numbers that are
+                            // smaller than it. Repeat |size - 1| times for all neighboring pairs -
+                            // the biggest number can supersede smaller numbers at most |size - 1|
+                            // times.
+                            repeat(elements.size - 1) {
+                                for (i in 0..elements.size - 2) {
+                                    if (elements[i] < elements[i + 1]) {
+                                        elements.removeAt(i)
+                                        break
+                                    }
+                                }
+                            }
+                        },
+                        onUnprocessedElements = unprocessElementHandler
+                    ) {
+                        processingCalls.add(it)
+                    }
+                    .processIn(processingScope)
+
+            processingQueue.tryEmit(2)
+            processingQueue.tryEmit(5)
+            processingQueue.tryEmit(4)
+            advanceUntilIdle()
+
+            processingQueue.tryEmit(1)
+            processingQueue.tryEmit(3)
+            processingQueue.tryEmit(6)
+            advanceUntilIdle()
+
+            // Processing loop should run the following:
+            // 1. prune([2, 5, 4]) --> reduces the list to [5, 4]
+            // 2. process(5)
+            // 3. process(4)
+            // 4. prune([1, 3, 6]) --> reduces the list to [6]
+            // 5. process(6)
+            assertThat(pruningCalls).containsExactly(listOf(2, 5, 4), listOf(1, 3, 6))
+            assertThat(processingCalls).containsExactly(5, 4, 6)
+        }
+
+    @Test
+    fun processingQueueIterativelyAggregatesAndProcessesElements() =
+        testScope.runTest {
+            val processingQueue =
+                PruningProcessingQueue<Int>(
+                        capacity = 2,
+                        prune = { pruningCalls.add(it.toList()) },
+                        onUnprocessedElements = unprocessElementHandler
+                    ) {
+                        processingCalls.add(it)
+                    }
+                    .processIn(processingScope)
+
+            processingQueue.tryEmit(1)
+            processingQueue.tryEmit(2)
+            advanceUntilIdle()
+
+            processingQueue.tryEmit(3)
+            advanceUntilIdle()
+
+            processingQueue.tryEmit(4)
+            processingQueue.tryEmit(5)
+            advanceUntilIdle()
+
+            // Processing loop should run the following:
+            // 1. prune([1, 2])
+            // 2. process(1)
+            // 3. process(2)
+            // 4. prune([3])
+            // 5. process(3)
+            // 6. prune([4, 5])
+            // 7. process(4)
+            // 8. process(5)
+            assertThat(pruningCalls).containsExactly(listOf(1, 2), listOf(3), listOf(4, 5))
+            assertThat(processingCalls).containsExactly(1, 2, 3, 4, 5)
+
+            processingScope.cancel()
+        }
+
+    @Test
+    fun processInOnCanceledScopeInvokesOnUnprocessedElements() =
+        testScope.runTest {
+            val processingQueue =
+                PruningProcessingQueue<Int>(
+                    prune = { pruningCalls.add(it.toList()) },
+                    onUnprocessedElements = unprocessElementHandler
+                ) {}
+
+            processingQueue.tryEmit(1)
+            processingQueue.tryEmit(2)
+
+            processingScope.cancel()
+            processingQueue.processIn(processingScope)
+
+            // Processing loop does not receive anything
+            assertThat(pruningCalls).isEmpty()
+            assertThat(unprocessedElements).containsExactly(listOf(1, 2))
+        }
+
+    @Test
+    fun cancellingProcessingScopeStopsProcessing() =
+        testScope.runTest {
+            val processingQueue =
+                PruningProcessingQueue<Int>(
+                        prune = { pruningCalls.add(it.toList()) },
+                        onUnprocessedElements = unprocessElementHandler
+                    ) {
+                        processingCalls.add(it)
+                    }
+                    .processIn(processingScope)
+
+            processingQueue.tryEmit(1)
+            processingQueue.tryEmit(2)
+            advanceUntilIdle()
+
+            assertThat(processingQueue.tryEmit(3)).isTrue() // Normal
+            assertThat(processingQueue.tryEmit(4)).isTrue() // Normal
+            processingScope.cancel()
+            assertThat(processingQueue.tryEmit(5)).isTrue() // Channel hasn't been closed
+            assertThat(processingQueue.tryEmit(6)).isTrue() // Channel hasn't been closed
+            advanceUntilIdle()
+
+            assertThat(processingQueue.tryEmit(7)).isFalse() // fails
+            assertThat(processingQueue.tryEmit(8)).isFalse() // fails
+
+            assertThat(pruningCalls)
+                .containsExactly(
+                    listOf(1, 2),
+                )
+            assertThat(processingCalls).containsExactly(1, 2)
+            assertThat(unprocessedElements).containsExactly(listOf(3, 4, 5, 6))
+        }
+
+    @Test
+    fun longProcessingDoesNotBlockPruning() =
+        testScope.runTest {
+            val processingQueue =
+                PruningProcessingQueue<Int>(
+                        prune = { pruningCalls.add(it.toList()) },
+                        onUnprocessedElements = unprocessElementHandler
+                    ) {
+                        processingCalls.add(it)
+                        delay(100)
+                    }
+                    .processIn(processingScope)
+
+            processingQueue.emitChecked(1)
+            processingQueue.emitChecked(2)
+            processingQueue.emitChecked(3)
+            advanceTimeBy(50) // Triggers initial processing call
+            assertThat(processingCalls).containsExactly(1)
+
+            processingQueue.emitChecked(4)
+            processingQueue.emitChecked(5)
+            advanceTimeBy(25) // Still processing 1, but elements are still aggregated and pruned.
+            assertThat(processingCalls).containsExactly(1)
+
+            processingQueue.emitChecked(6)
+            advanceTimeBy(50) // Processed 1, and processing 2.
+            assertThat(processingCalls).containsExactly(1, 2)
+
+            processingQueue.emitChecked(7)
+            processingQueue.emitChecked(8)
+            advanceUntilIdle() // Last update includes all previous updates.
+
+            assertThat(pruningCalls)
+                .containsExactly(
+                    listOf(1, 2, 3),
+                    listOf(2, 3, 4, 5),
+                    listOf(2, 3, 4, 5, 6),
+                    listOf(3, 4, 5, 6, 7, 8),
+                )
+            assertThat(processingCalls).containsExactly(1, 2, 3, 4, 5, 6, 7, 8)
+            processingScope.cancel()
+        }
+
+    @Test
+    fun exceptionsDuringProcessingArePropagated() =
+        testScope.runTest {
+            val processingQueue =
+                PruningProcessingQueue<Int>(
+                        prune = { pruningCalls.add(it.toList()) },
+                        onUnprocessedElements = unprocessElementHandler
+                    ) {
+                        processingCalls.add(it)
+                        delay(100)
+                        throw RuntimeException("Test")
+                    }
+                    .processIn(processingScope)
+
+            processingQueue.emitChecked(1)
+            processingQueue.emitChecked(2)
+            processingQueue.emitChecked(3)
+            advanceTimeBy(50) // Triggers initial processing call, but not exception
+
+            processingQueue.emitChecked(4)
+            processingQueue.emitChecked(5)
+            advanceUntilIdle() // Trigger exception.
+
+            assertThat(pruningCalls).containsExactly(listOf(1, 2, 3), listOf(2, 3, 4, 5))
+            assertThat(unprocessedElements).containsExactly(listOf(2, 3, 4, 5))
+            assertThat(lastUncaughtException).isInstanceOf(RuntimeException::class.java)
+        }
+
+    @Test
+    fun duplicateItemsAreNotOmitted() =
+        testScope.runTest {
+            val processingQueue =
+                PruningProcessingQueue<Int>(
+                        prune = { pruningCalls.add(it.toList()) },
+                        onUnprocessedElements = unprocessElementHandler
+                    ) {
+                        processingCalls.add(it)
+                    }
+                    .processIn(processingScope)
+
+            processingQueue.emitChecked(1)
+            processingQueue.emitChecked(1)
+            advanceUntilIdle()
+            processingQueue.emitChecked(1)
+            processingQueue.emitChecked(1)
+            processingQueue.emitChecked(1)
+            advanceUntilIdle()
+
+            assertThat(pruningCalls).containsExactly(listOf(1, 1), listOf(1, 1, 1))
+            assertThat(processingCalls).containsExactly(1, 1, 1, 1, 1)
+        }
+}
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java
index 5e35a7a..ff3a803 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java
@@ -59,6 +59,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.util.Range;
 import android.util.Size;
 import android.view.Surface;
 
@@ -70,7 +71,9 @@
 import androidx.camera.core.CameraControl;
 import androidx.camera.core.CameraSelector;
 import androidx.camera.core.CompositionSettings;
+import androidx.camera.core.DynamicRange;
 import androidx.camera.core.ImageCapture;
+import androidx.camera.core.MirrorMode;
 import androidx.camera.core.Preview;
 import androidx.camera.core.UseCase;
 import androidx.camera.core.impl.CameraCaptureCallback;
@@ -916,11 +919,23 @@
 
     private @NonNull TestUseCase createUseCase(int template, @NonNull SurfaceOption surfaceOption,
             int imageFormat) {
+        return createUseCase(template, surfaceOption, imageFormat, null, null);
+    }
+
+    private @NonNull TestUseCase createUseCase(int template, @NonNull SurfaceOption surfaceOption,
+            int imageFormat, @Nullable Range<Integer> targetFpsRange,
+            @Nullable DynamicRange dynamicRange) {
         boolean isZslDisabled = getDefaultZslDisabled(template);
         FakeUseCaseConfig.Builder configBuilder =
                 new FakeUseCaseConfig.Builder().setSessionOptionUnpacker(
                                 new Camera2SessionOptionUnpacker()).setTargetName("UseCase")
                         .setZslDisabled(isZslDisabled);
+        if (targetFpsRange != null) {
+            configBuilder.setTargetFrameRate(targetFpsRange);
+        }
+        if (dynamicRange != null) {
+            configBuilder.setDynamicRange(dynamicRange);
+        }
         new Camera2Interop.Extender<>(configBuilder).setSessionStateCallback(mSessionStateCallback);
         return createUseCase(configBuilder.getUseCaseConfig(), template, surfaceOption,
                 imageFormat);
@@ -936,10 +951,16 @@
                 surfaceOption,
                 imageFormat
         );
-
-        testUseCase.updateSuggestedStreamSpec(StreamSpec.builder(
+        StreamSpec.Builder builder = StreamSpec.builder(
                 new Size(640, 480)).setImplementationOptions(
-                StreamUseCaseUtil.getStreamSpecImplementationOptions(config)).build(),
+                StreamUseCaseUtil.getStreamSpecImplementationOptions(config));
+        if (config.getTargetFrameRate(null) != null) {
+            builder.setExpectedFrameRateRange(config.getTargetFrameRate());
+        }
+        if (config.hasDynamicRange()) {
+            builder.setDynamicRange(config.getDynamicRange());
+        }
+        testUseCase.updateSuggestedStreamSpec(builder.build(),
                 null);
         mFakeUseCases.add(testUseCase);
         return testUseCase;
@@ -1366,6 +1387,67 @@
         }
     }
 
+    @SdkSuppress(minSdkVersion = 35)
+    @Test
+    public void lowLightBoostDisabled_whenFrameRateRangeExceed30() throws InterruptedException {
+        assumeTrue(mCamera2CameraImpl.getCameraInfo().isLowLightBoostSupported());
+        Set<Range<Integer>> supportedFrameRateRanges =
+                mCamera2CameraImpl.mCameraInfoInternal.getSupportedFrameRateRanges();
+        Range<Integer> fpsRangeExceed30 = null;
+        for (Range<Integer> fpsRange: supportedFrameRateRanges) {
+            if (fpsRange.getUpper() > 30) {
+                fpsRangeExceed30 = fpsRange;
+                break;
+            }
+        }
+        assumeTrue("The test only runs on devices that support frame rate range exceeding 30.",
+                fpsRangeExceed30 != null);
+
+        UseCase useCase = createUseCase(CameraDevice.TEMPLATE_PREVIEW, DEFAULT_SURFACE_OPTION,
+                DEFAULT_IMAGE_FORMAT, fpsRangeExceed30, null);
+
+        Camera2CameraControlImpl camera2CameraControlImpl =
+                (Camera2CameraControlImpl) mCamera2CameraImpl.getCameraControlInternal();
+        LowLightBoostControl lowLightBoostControl =
+                camera2CameraControlImpl.getLowLightBoostControl();
+
+        mCamera2CameraImpl.onUseCaseActive(useCase);
+        mCamera2CameraImpl.attachUseCases(singletonList(useCase));
+        HandlerUtil.waitForLooperToIdle(sCameraHandler);
+        assertThat(lowLightBoostControl.isLowLightBoostDisabledByUseCaseSessionConfig()).isTrue();
+    }
+
+    @SdkSuppress(minSdkVersion = 35)
+    @Test
+    public void lowLightBoostDisabled_whenHdr10BitEnabled() throws InterruptedException {
+        assumeTrue(mCamera2CameraImpl.getCameraInfo().isLowLightBoostSupported());
+
+        Set<DynamicRange> supportedDynamicRanges =
+                mCamera2CameraImpl.mCameraInfoInternal.getSupportedDynamicRanges();
+        DynamicRange hdr10BitDynamicRange = null;
+        for (DynamicRange dynamicRange: supportedDynamicRanges) {
+            if (dynamicRange != DynamicRange.SDR) {
+                hdr10BitDynamicRange = dynamicRange;
+                break;
+            }
+        }
+        assumeTrue("The test only runs on devices that support HDR 10-bit dynamic range.",
+                hdr10BitDynamicRange != null);
+
+        UseCase useCase = createUseCase(CameraDevice.TEMPLATE_PREVIEW, DEFAULT_SURFACE_OPTION,
+                DEFAULT_IMAGE_FORMAT, null, hdr10BitDynamicRange);
+
+        Camera2CameraControlImpl camera2CameraControlImpl =
+                (Camera2CameraControlImpl) mCamera2CameraImpl.getCameraControlInternal();
+        LowLightBoostControl lowLightBoostControl =
+                camera2CameraControlImpl.getLowLightBoostControl();
+
+        mCamera2CameraImpl.onUseCaseActive(useCase);
+        mCamera2CameraImpl.attachUseCases(singletonList(useCase));
+        HandlerUtil.waitForLooperToIdle(sCameraHandler);
+        assertThat(lowLightBoostControl.isLowLightBoostDisabledByUseCaseSessionConfig()).isTrue();
+    }
+
     private void changeUseCaseSurface(UseCase useCase) {
         useCase.updateSuggestedStreamSpec(StreamSpec.builder(
                 new Size(640, 480)).setImplementationOptions(
@@ -1451,6 +1533,8 @@
                     primaryStreamSpec.getResolution());
             mSessionConfigBuilder.setTemplateType(mTemplate);
             mSessionConfigBuilder.addRepeatingCameraCaptureCallback(mRepeatingCaptureCallback);
+            mSessionConfigBuilder.setExpectedFrameRateRange(
+                    primaryStreamSpec.getExpectedFrameRateRange());
             updateSessionBuilderBySurfaceOption();
             updateSessionConfig(List.of(mSessionConfigBuilder.build()));
             return primaryStreamSpec;
@@ -1471,10 +1555,14 @@
                 case NO_SURFACE:
                     break;
                 case REPEATING:
-                    mSessionConfigBuilder.addSurface(mDeferrableSurface);
+                    mSessionConfigBuilder.addSurface(mDeferrableSurface,
+                            mConfig.hasDynamicRange() ? mConfig.getDynamicRange()
+                                    : DynamicRange.SDR, null, MirrorMode.MIRROR_MODE_UNSPECIFIED);
                     break;
                 case NON_REPEATING:
-                    mSessionConfigBuilder.addNonRepeatingSurface(mDeferrableSurface);
+                    mSessionConfigBuilder.addNonRepeatingSurface(mDeferrableSurface,
+                            mConfig.hasDynamicRange() ? mConfig.getDynamicRange()
+                                    : DynamicRange.SDR);
                     break;
             }
         }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraControlImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraControlImpl.java
index ef38ab5..f6db921 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraControlImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraControlImpl.java
@@ -434,6 +434,12 @@
         return Futures.nonCancellationPropagating(mTorchControl.enableTorch(torch));
     }
 
+    @Override
+    @ExecutedBy("mExecutor")
+    public void setLowLightBoostDisabledByUseCaseSessionConfig(boolean disabled) {
+        mLowLightBoostControl.setLowLightBoostDisabledByUseCaseSessionConfig(disabled);
+    }
+
     /** {@inheritDoc} */
     @Override
     public @NonNull ListenableFuture<Void> enableLowLightBoostAsync(final boolean lowLightBoost) {
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
index 7589dc8..7d12e76 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
@@ -16,6 +16,8 @@
 
 package androidx.camera.camera2.internal;
 
+import static android.hardware.camera2.params.DynamicRangeProfiles.STANDARD;
+
 import static androidx.camera.core.concurrent.CameraCoordinator.CAMERA_OPERATING_MODE_CONCURRENT;
 
 import android.annotation.SuppressLint;
@@ -24,7 +26,9 @@
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.params.DynamicRangeProfiles;
 import android.media.CamcorderProfile;
+import android.os.Build;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.text.TextUtils;
@@ -40,6 +44,7 @@
 import androidx.camera.camera2.internal.compat.CameraAccessExceptionCompat;
 import androidx.camera.camera2.internal.compat.CameraCharacteristicsCompat;
 import androidx.camera.camera2.internal.compat.CameraManagerCompat;
+import androidx.camera.camera2.internal.compat.params.DynamicRangeConversions;
 import androidx.camera.camera2.internal.compat.params.DynamicRangesCompat;
 import androidx.camera.camera2.internal.compat.quirk.DeviceQuirks;
 import androidx.camera.camera2.internal.compat.quirk.LegacyCameraOutputConfigNullPointerQuirk;
@@ -48,6 +53,7 @@
 import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
 import androidx.camera.core.CameraState;
 import androidx.camera.core.CameraUnavailableException;
+import androidx.camera.core.DynamicRange;
 import androidx.camera.core.Logger;
 import androidx.camera.core.Preview;
 import androidx.camera.core.UseCase;
@@ -982,6 +988,9 @@
 
         // Update Zsl disabled status by iterating all attached use cases.
         updateZslDisabledByUseCaseConfigStatus();
+        // Update low-light boost disabled status by the session config generated from all
+        // attached use cases.
+        updateLowLightBoostDisabledByUseCaseSessionConfigStatus();
 
         updateCaptureSessionConfig();
         resetCaptureSession(/*abortInFlightCaptures=*/false);
@@ -1103,8 +1112,10 @@
         // attached use cases.
         if (mUseCaseAttachState.getAttachedUseCaseConfigs().isEmpty()) {
             mCameraControlInternal.setZslDisabledByUserCaseConfig(false);
+            mCameraControlInternal.setLowLightBoostDisabledByUseCaseSessionConfig(false);
         } else {
             updateZslDisabledByUseCaseConfigStatus();
+            updateLowLightBoostDisabledByUseCaseSessionConfigStatus();
         }
 
         boolean allUseCasesDetached = mUseCaseAttachState.getAttachedSessionConfigs().isEmpty();
@@ -1137,6 +1148,51 @@
         mCameraControlInternal.setZslDisabledByUserCaseConfig(isZslDisabledByUseCaseConfig);
     }
 
+    private void updateLowLightBoostDisabledByUseCaseSessionConfigStatus() {
+        if (!mCameraInfoInternal.isLowLightBoostSupported()) {
+            return;
+        }
+
+        ValidatingBuilder validatingBuilder = mUseCaseAttachState.getActiveAndAttachedBuilder();
+
+        SessionConfig useCaseSessionConfig;
+
+        if (validatingBuilder.isValid()) {
+            useCaseSessionConfig = validatingBuilder.build();
+        } else {
+            return;
+        }
+
+        // Low-light boost should be disabled when expected frame rate range exceeds 30.
+        if (useCaseSessionConfig.getExpectedFrameRateRange().getUpper() > 30) {
+            mCameraControlInternal.setLowLightBoostDisabledByUseCaseSessionConfig(true);
+            return;
+        }
+
+        // HDR 10-bit can be supported since API level 33
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
+            return;
+        }
+
+        for (SessionConfig.OutputConfig outputConfig : useCaseSessionConfig.getOutputConfigs()) {
+            DynamicRangeProfiles dynamicRangeProfiles =
+                    mDynamicRangesCompat.toDynamicRangeProfiles();
+            if (dynamicRangeProfiles != null) {
+                DynamicRange requestedDynamicRange = outputConfig.getDynamicRange();
+                Long dynamicRangeProfileOrNull =
+                        DynamicRangeConversions.dynamicRangeToFirstSupportedProfile(
+                                requestedDynamicRange, dynamicRangeProfiles);
+                // Low-light boost should be disabled when HDR 10-bit is enabled.
+                if (dynamicRangeProfileOrNull != null && dynamicRangeProfileOrNull != STANDARD) {
+                    mCameraControlInternal.setLowLightBoostDisabledByUseCaseSessionConfig(true);
+                    return;
+                }
+            }
+        }
+
+        mCameraControlInternal.setLowLightBoostDisabledByUseCaseSessionConfig(false);
+    }
+
     // Check if it need the repeating surface for ImageCapture only use case.
     private void addOrRemoveMeteringRepeatingUseCase() {
         ValidatingBuilder validatingBuilder = mUseCaseAttachState.getAttachedBuilder();
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CaptureRequestBuilder.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CaptureRequestBuilder.java
index a56d479..b6689f0 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CaptureRequestBuilder.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CaptureRequestBuilder.java
@@ -122,16 +122,24 @@
     @VisibleForTesting
     static void applyVideoStabilization(@NonNull CaptureConfig captureConfig,
             CaptureRequest.@NonNull Builder builder) {
+        Integer mode = getVideoStabilizationModeFromCaptureConfig(captureConfig);
+        if (mode != null) {
+            builder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, mode);
+        }
+    }
+
+    // null indicates the stabilization mode unspecified.
+    static Integer getVideoStabilizationModeFromCaptureConfig(
+            @NonNull CaptureConfig captureConfig) {
         if (captureConfig.getPreviewStabilizationMode() == StabilizationMode.OFF
                 || captureConfig.getVideoStabilizationMode() == StabilizationMode.OFF) {
-            builder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,
-                    CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_OFF);
+            return CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_OFF;
         } else if (captureConfig.getPreviewStabilizationMode() == StabilizationMode.ON) {
-            builder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,
-                    CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION);
+            return CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION;
         } else if (captureConfig.getVideoStabilizationMode() == StabilizationMode.ON) {
-            builder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE,
-                    CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_ON);
+            return CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_ON;
+        } else {
+            return null;
         }
     }
 
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/LowLightBoostControl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/LowLightBoostControl.java
index 78bcb35..f4576e5 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/LowLightBoostControl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/LowLightBoostControl.java
@@ -23,6 +23,7 @@
 import android.hardware.camera2.CaptureRequest;
 import android.os.Build;
 
+import androidx.annotation.GuardedBy;
 import androidx.annotation.VisibleForTesting;
 import androidx.camera.camera2.internal.annotation.CameraExecutor;
 import androidx.camera.camera2.internal.compat.CameraCharacteristicsCompat;
@@ -60,6 +61,9 @@
     private final Camera2CameraControlImpl mCamera2CameraControlImpl;
     private final MutableLiveData<Integer> mLowLightBoostState;
     private final boolean mIsLowLightBoostSupported;
+    private final Object mLock = new Object();
+    @GuardedBy("mLock")
+    private boolean mLowLightBoostDisabledByUseCaseSessionConfig = false;
     @CameraExecutor
     private final Executor mExecutor;
 
@@ -158,6 +162,36 @@
         }
     }
 
+    @ExecutedBy("mExecutor")
+    void setLowLightBoostDisabledByUseCaseSessionConfig(boolean disabled) {
+        synchronized (mLock) {
+            mLowLightBoostDisabledByUseCaseSessionConfig = disabled;
+
+            if (!mLowLightBoostDisabledByUseCaseSessionConfig) {
+                return;
+            }
+        }
+
+        if (mTargetLlbEnabled) {
+            mTargetLlbEnabled = false;
+            mCamera2CameraControlImpl.enableLowLightBoostInternal(false);
+            setLiveDataValue(mLowLightBoostState, LowLightBoostState.OFF);
+
+            if (mEnableLlbCompleter != null) {
+                mEnableLlbCompleter.setException(new IllegalStateException(
+                        "Low-light boost is disabled when expected frame rate range exceeds 30 or"
+                                + " HDR 10-bit is on."));
+                mEnableLlbCompleter = null;
+            }
+        }
+    }
+
+    boolean isLowLightBoostDisabledByUseCaseSessionConfig() {
+        synchronized (mLock) {
+            return mLowLightBoostDisabledByUseCaseSessionConfig;
+        }
+    }
+
     /**
      * Enable or disable the low-light boost.
      *
@@ -212,6 +246,18 @@
     @SuppressWarnings("WeakerAccess") /* synthetic accessor */
     @ExecutedBy("mExecutor")
     void enableLowLightBoostInternal(@Nullable Completer<Void> completer, boolean enabled) {
+        synchronized (mLock) {
+            if (mLowLightBoostDisabledByUseCaseSessionConfig) {
+                setLiveDataValue(mLowLightBoostState, LowLightBoostState.OFF);
+                if (completer != null) {
+                    completer.setException(new IllegalStateException(
+                            "Low-light boost is disabled when expected frame rate range exceeds "
+                                    + "30 or HDR 10-bit is on."));
+                }
+                return;
+            }
+        }
+
         if (!mIsActive) {
             setLiveDataValue(mLowLightBoostState, LowLightBoostState.OFF);
             if (completer != null) {
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ProcessingCaptureSession.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ProcessingCaptureSession.java
index 6f7d586..edf54ac 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ProcessingCaptureSession.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ProcessingCaptureSession.java
@@ -616,9 +616,18 @@
         }
 
         if (mProcessorState == ProcessorState.ON_CAPTURE_SESSION_STARTED) {
-            mSessionOptions =
-                    CaptureRequestOptions.Builder.from(sessionConfig.getImplementationOptions())
-                            .build();
+            CaptureRequestOptions.Builder requestOptionsbuilder =
+                    CaptureRequestOptions.Builder.from(sessionConfig.getImplementationOptions());
+
+            // Applying stabilization mode
+            Integer stabilizationMode =
+                    Camera2CaptureRequestBuilder.getVideoStabilizationModeFromCaptureConfig(
+                            sessionConfig.getRepeatingCaptureConfig());
+            if (stabilizationMode != null) {
+                requestOptionsbuilder.setCaptureRequestOption(
+                        CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, stabilizationMode);
+            }
+            mSessionOptions = requestOptionsbuilder.build();
             updateParameters(mSessionOptions, mStillCaptureOptions);
 
             // We can't disable only preview stream but enable ImageAnalysis in Extensions.
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/LowLightBoostControlTest.kt b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/LowLightBoostControlTest.kt
index bed297c..3b77eff 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/LowLightBoostControlTest.kt
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/LowLightBoostControlTest.kt
@@ -204,6 +204,38 @@
         }
     }
 
+    @Test
+    fun enableLowLightBoostThrowException_stateActive_whenDisabledByUseCaseConfig() {
+        initCamera(supportedLlb = true)
+        createLowLightBoostControl().apply {
+            setActive(true)
+            setLowLightBoostDisabledByUseCaseSessionConfig(true)
+            val future = enableLowLightBoost(true)
+            shadowOf(getMainLooper()).idle()
+            assertFutureCompleteWithException(future, IllegalStateException::class.java)
+        }
+    }
+
+    @Test
+    fun lowLightBoostCanBeDisabledByUseCaseConfig() {
+        initCamera(supportedLlb = true)
+        createLowLightBoostControl().apply {
+            setActive(true)
+            enableLowLightBoost(true)
+            shadowOf(getMainLooper()).idle()
+            assertThat(lowLightBoostState.value).isEqualTo(LowLightBoostState.INACTIVE)
+
+            // Sets low-light boost disabled flag
+            setLowLightBoostDisabledByUseCaseSessionConfig(true)
+            runBlocking { delay(100) }
+            shadowOf(getMainLooper()).idle()
+
+            // Verifies that low-light boost is turned off
+            assertThat(mTargetLlbEnabled).isFalse()
+            assertThat(lowLightBoostState.value).isEqualTo(LowLightBoostState.OFF)
+        }
+    }
+
     private fun assertFutureCompleteWithException(future: ListenableFuture<Void>, clazz: Class<*>) {
         assertThat(future.isDone).isTrue()
         try {
diff --git a/camera/camera-core/api/current.txt b/camera/camera-core/api/current.txt
index c33aa83..7837ece 100644
--- a/camera/camera-core/api/current.txt
+++ b/camera/camera-core/api/current.txt
@@ -14,6 +14,7 @@
 
   public interface CameraControl {
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelFocusAndMetering();
+    method public default com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enableLowLightBoostAsync(boolean);
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enableTorch(boolean);
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer!> setExposureCompensationIndex(int);
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setLinearZoom(@FloatRange(from=0.0f, to=1.0f) float);
@@ -46,6 +47,7 @@
     method public androidx.camera.core.ExposureState getExposureState();
     method @FloatRange(from=0, fromInclusive=false) public default float getIntrinsicZoomRatio();
     method public default int getLensFacing();
+    method public default androidx.lifecycle.LiveData<java.lang.Integer!> getLowLightBoostState();
     method public default java.util.Set<androidx.camera.core.CameraInfo!> getPhysicalCameraInfos();
     method public int getSensorRotationDegrees();
     method public int getSensorRotationDegrees(int);
@@ -55,6 +57,7 @@
     method public boolean hasFlashUnit();
     method public default boolean isFocusMeteringSupported(androidx.camera.core.FocusMeteringAction);
     method public default boolean isLogicalMultiCameraSupported();
+    method public default boolean isLowLightBoostSupported();
     method @SuppressCompatibility @androidx.camera.core.ExperimentalZeroShutterLag public default boolean isZslSupported();
     method public static boolean mustPlayShutterSound();
     method public default java.util.Set<androidx.camera.core.DynamicRange!> querySupportedDynamicRanges(java.util.Set<androidx.camera.core.DynamicRange!>);
@@ -511,6 +514,12 @@
     ctor public InitializationException(Throwable?);
   }
 
+  public class LowLightBoostState {
+    field public static final int ACTIVE = 1; // 0x1
+    field public static final int INACTIVE = 0; // 0x0
+    field public static final int OFF = -1; // 0xffffffff
+  }
+
   public class MeteringPoint {
     method public float getSize();
   }
diff --git a/camera/camera-core/api/restricted_current.txt b/camera/camera-core/api/restricted_current.txt
index c33aa83..7837ece 100644
--- a/camera/camera-core/api/restricted_current.txt
+++ b/camera/camera-core/api/restricted_current.txt
@@ -14,6 +14,7 @@
 
   public interface CameraControl {
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelFocusAndMetering();
+    method public default com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enableLowLightBoostAsync(boolean);
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enableTorch(boolean);
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer!> setExposureCompensationIndex(int);
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setLinearZoom(@FloatRange(from=0.0f, to=1.0f) float);
@@ -46,6 +47,7 @@
     method public androidx.camera.core.ExposureState getExposureState();
     method @FloatRange(from=0, fromInclusive=false) public default float getIntrinsicZoomRatio();
     method public default int getLensFacing();
+    method public default androidx.lifecycle.LiveData<java.lang.Integer!> getLowLightBoostState();
     method public default java.util.Set<androidx.camera.core.CameraInfo!> getPhysicalCameraInfos();
     method public int getSensorRotationDegrees();
     method public int getSensorRotationDegrees(int);
@@ -55,6 +57,7 @@
     method public boolean hasFlashUnit();
     method public default boolean isFocusMeteringSupported(androidx.camera.core.FocusMeteringAction);
     method public default boolean isLogicalMultiCameraSupported();
+    method public default boolean isLowLightBoostSupported();
     method @SuppressCompatibility @androidx.camera.core.ExperimentalZeroShutterLag public default boolean isZslSupported();
     method public static boolean mustPlayShutterSound();
     method public default java.util.Set<androidx.camera.core.DynamicRange!> querySupportedDynamicRanges(java.util.Set<androidx.camera.core.DynamicRange!>);
@@ -511,6 +514,12 @@
     ctor public InitializationException(Throwable?);
   }
 
+  public class LowLightBoostState {
+    field public static final int ACTIVE = 1; // 0x1
+    field public static final int INACTIVE = 0; // 0x0
+    field public static final int OFF = -1; // 0xffffffff
+  }
+
   public class MeteringPoint {
     method public float getSize();
   }
diff --git a/camera/camera-core/build.gradle b/camera/camera-core/build.gradle
index cc4ad3f..8b08373 100644
--- a/camera/camera-core/build.gradle
+++ b/camera/camera-core/build.gradle
@@ -59,6 +59,7 @@
     testImplementation(libs.robolectric)
     testImplementation(libs.mockitoCore4)
     testImplementation("androidx.concurrent:concurrent-futures-ktx:1.1.0")
+    testImplementation(project(":internal-testutils-ktx"))
     testImplementation(project(":internal-testutils-truth"))
     testImplementation(project(":camera:camera-camera2"))
     testImplementation(project(":camera:camera-testing"), {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraControl.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraControl.java
index 9dbfa50..6b25593 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraControl.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraControl.java
@@ -93,19 +93,27 @@
      * <li>When low-light boost is on, the flash or torch functionality may be unavailable.
      * <li>When frame rate configuration results in an FPS exceeding 30, low-light boost will be
      * disabled and the state will always be ({@link LowLightBoostState#OFF}).
+     * <li>Low-light boost is not currently supported for HDR 10-bit capture sessions. If the
+     * dynamic range configuration results in a 10-bit capture session, low-light boost will be
+     * disabled and the state will always be ({@link LowLightBoostState#OFF}).
      * </ul>
      *
      * <p>Therefore, to use flash or torch functionality, low-light boost mode must be disabled.
-     * To ensure low-light boost mode functions correctly, avoid frame rate settings that result
-     * in an FPS exceeding 30.
+     * To ensure low-light boost mode functions correctly, the following conditions must be met:
+     * <ul>
+     * <li> The frame rate must not exceed 30 FPS.
+     * <li> The dynamic range setting must not be 10-bit.
+     * </ul>
      *
      * @param lowLightBoost true to turn on the low-light boost mode, false to turn it off.
      * @return A {@link ListenableFuture} which is successful when the low-light boost mode was
-     * changed to the value specified. It fails when it is unable to change the log-light boost
-     * state. Cancellation of this future is a no-op.
+     * changed to the value specified. It fails with {@link IllegalStateException} when low-light
+     * boost is not available due to the device does not support it or there is a settings
+     * conflict. It fails with {@link OperationCanceledException} if a newer value is set or
+     * camera is closed. The failure reason will be provided in the exception' message.
+     * Cancellation of this future is a no-op.
      * @see CameraInfo#isLowLightBoostSupported()
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     default @NonNull ListenableFuture<Void> enableLowLightBoostAsync(boolean lowLightBoost) {
         return Futures.immediateFailedFuture(new OperationCanceledException("Not supported!"));
     }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/CameraInfo.java b/camera/camera-core/src/main/java/androidx/camera/core/CameraInfo.java
index e2f6556..efbb3c3 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/CameraInfo.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/CameraInfo.java
@@ -443,7 +443,6 @@
      * @see CameraControl#enableLowLightBoostAsync(boolean)
      * @see CaptureRequest#CONTROL_AE_MODE_ON_LOW_LIGHT_BOOST_BRIGHTNESS_PRIORITY
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
     default boolean isLowLightBoostSupported() {
         return false;
     }
@@ -462,7 +461,6 @@
      *
      * @return a {@link LiveData} containing current low-light boost state.
      */
-    @RestrictTo(Scope.LIBRARY_GROUP)
     default @NonNull LiveData<Integer> getLowLightBoostState() {
         return new MutableLiveData<>(LowLightBoostState.OFF);
     }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/LowLightBoostState.java b/camera/camera-core/src/main/java/androidx/camera/core/LowLightBoostState.java
index 94d37b3..222b386 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/LowLightBoostState.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/LowLightBoostState.java
@@ -16,6 +16,9 @@
 
 package androidx.camera.core;
 
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureResult;
+
 import androidx.annotation.IntDef;
 import androidx.annotation.RestrictTo;
 
@@ -28,14 +31,34 @@
  *
  * <p>These states indicate whether the camera device supports low light boost and if it is
  * currently active.
+ *
+ * @see CaptureResult#CONTROL_LOW_LIGHT_BOOST_STATE
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 public class LowLightBoostState {
-    /** Low-light boost is off. */
+    /**
+     * Low-light boost is off.
+     *
+     * <p>This is the default state if low-light boost is unavailable. This may be because your
+     * camera doesn't support it or there's a settings conflict.
+     */
     public static final int OFF = -1;
-    /** Low-light boost is on but inactive. */
+    /**
+     * Low-light boost is on but inactive.
+     *
+     * <p>This state indicates that the camera device supports low-light boost but it is not
+     * currently active. This can happen if the camera device is not in low-light conditions.
+     *
+     * @see CameraMetadata#CONTROL_LOW_LIGHT_BOOST_STATE_INACTIVE
+     */
     public static final int INACTIVE = 0;
-    /** Low-light boost is on and active. */
+    /**
+     * Low-light boost is on and active.
+     *
+     * <p>This state indicates that the camera device is currently applying low-light boost to
+     * the image stream.
+     *
+     * @see CameraMetadata#CONTROL_LOW_LIGHT_BOOST_STATE_ACTIVE
+     */
     public static final int ACTIVE = 1;
 
     private LowLightBoostState() {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraControlInternal.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraControlInternal.java
index 94398db..cd75af2 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraControlInternal.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/CameraControlInternal.java
@@ -101,6 +101,19 @@
     boolean isZslDisabledByByUserCaseConfig();
 
     /**
+     * Sets the flag if low-light boost needs to be disabled by use case session config.
+     *
+     * <p> Low-light boost will be disabled when any of the following conditions:
+     * <ul>
+     *     <li> Expected frame rate range exceeds 30
+     *     <li> HDR 10-bit is ON
+     * </ul>
+     *
+     * @param disabled True if low-light boost should be disabled. Otherwise returns false.
+     */
+    default void setLowLightBoostDisabledByUseCaseSessionConfig(boolean disabled) {}
+
+    /**
      * Performs still capture requests with the desired capture mode.
      *
      * @param captureConfigs capture configuration used for creating CaptureRequest
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/LiveDataUtil.kt b/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/LiveDataUtil.kt
index 13620f2..695edc4 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/LiveDataUtil.kt
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/LiveDataUtil.kt
@@ -33,38 +33,64 @@
      */
     @MainThread
     @JvmStatic
-    public fun <X> map(source: LiveData<X>, mapFunction: Function<X, X>): LiveData<X> {
-        val result = RedirectableLiveData<X>(mapFunction.apply(source.value!!))
-        result.redirectToWithMapping(source, mapFunction)
+    public fun <I, O> map(source: LiveData<I>, mapFunction: Function<I, O>): LiveData<O> {
+        val result = MappingRedirectableLiveData<I, O>(mapFunction.apply(source.value), mapFunction)
+        result.redirectTo(source)
         return result
     }
 }
 
 /**
- * A [LiveData] which can be redirected to another [LiveData]. If no redirection is set, initial
- * value will be used. Optionally, a map function can be supplied to transform every value delivered
- * in observers or via [getValue].
+ * A [LiveData] which can be redirected to a source [LiveData] in order to use the source data as
+ * its own.
+ *
+ * This `LiveData` is considered as the destination `LiveData` while the source `LiveData` is the
+ * one this redirects to. Whenever source `LiveData` gets updated with a value, this `LiveData` is
+ * also updated with that value.
+ *
+ * @param T The type of both the source `LiveData` and this `LiveData`.
+ * @property initialValue The initial value that is returned if no redirection is set yet.
+ * @see MappingRedirectableLiveData
  */
-public class RedirectableLiveData<T> internal constructor(private val mInitialValue: T) :
-    MediatorLiveData<T>() {
-    private var mLiveDataSource: LiveData<T>? = null
-    private var mapFunction: Function<T, T>? = null
+public class RedirectableLiveData<T>(private val initialValue: T) :
+    MappingRedirectableLiveData<T, T>(initialValue, { it })
 
-    public fun redirectTo(liveDataSource: LiveData<T>) {
-        redirectToWithMapping(liveDataSource, mapFunction = null)
-    }
+/**
+ * A [LiveData] which can be redirected to a source [LiveData] in order to map the source data as
+ * its own data.
+ *
+ * This `LiveData` is considered as the destination `LiveData` while the source `LiveData` is the
+ * one this redirects to. Whenever source `LiveData` gets updated with a value, this `LiveData` is
+ * also updated with a mapped equivalent of that value.
+ *
+ * @param I The type of the source `LiveData`.
+ * @param O The type of the destination `LiveData`.
+ * @property initialValue The initial value that is returned if no redirection is set yet.
+ * @property mapFunction The function that maps source data.
+ * @see redirectTo
+ */
+public open class MappingRedirectableLiveData<I, O>(
+    private val initialValue: O,
+    private val mapFunction: Function<I, O>
+) : MediatorLiveData<O>() {
+    private var liveDataSource: LiveData<I>? = null
 
-    public fun redirectToWithMapping(liveDataSource: LiveData<T>, mapFunction: Function<T, T>?) {
-        if (mLiveDataSource != null) {
-            super.removeSource(mLiveDataSource!!)
+    /**
+     * Redirects to a source [LiveData] whose value is mapped to this `LiveData`.
+     *
+     * After this function is invoked, the data of this `LiveData` will depend on the source live
+     * data with [mapFunction] invoked.
+     *
+     * @param liveDataSource The source `LiveData`.
+     */
+    public fun redirectTo(liveDataSource: LiveData<I>) {
+        if (this.liveDataSource != null) {
+            super.removeSource(this.liveDataSource!!)
         }
-        mLiveDataSource = liveDataSource
-        this.mapFunction = mapFunction
+        this.liveDataSource = liveDataSource
         runOnMain {
             // addSource should be invoked in main thread.
-            super.addSource(liveDataSource) { value: T ->
-                this.setValue(mapFunction?.apply(value) ?: value)
-            }
+            super.addSource(liveDataSource) { value: I -> this.value = mapFunction.apply(value) }
         }
     }
 
@@ -74,9 +100,20 @@
 
     // Overrides getValue() to reflect the correct value from source. This is required to ensure
     // getValue() is correct when observe() or observeForever() is not called.
-    override fun getValue(): T? {
+    /**
+     * Gets the value of this [LiveData] based on the provided redirection and mapping.
+     *
+     * If no redirection has been set yet, the [initialValue] property is returned.
+     *
+     * @see redirectTo
+     * @see MediatorLiveData.getValue
+     */
+    override fun getValue(): O? {
         // Returns initial value if source is not set.
-        val livedataValue = mLiveDataSource?.value ?: mInitialValue
-        return mapFunction?.apply(livedataValue) ?: livedataValue
+        val liveDataSource = this.liveDataSource // snapshot for non-null smart casting
+        if (liveDataSource == null) {
+            return initialValue
+        }
+        return mapFunction.apply(liveDataSource.value)
     }
 }
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/utils/LiveDataUtilTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/impl/utils/LiveDataUtilTest.kt
similarity index 63%
rename from camera/camera-core/src/androidTest/java/androidx/camera/core/impl/utils/LiveDataUtilTest.kt
rename to camera/camera-core/src/test/java/androidx/camera/core/impl/utils/LiveDataUtilTest.kt
index 4490ebc3..4d13862 100644
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/impl/utils/LiveDataUtilTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/impl/utils/LiveDataUtilTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2024 The Android Open Source Project
+ * Copyright 2025 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.
@@ -16,22 +16,34 @@
 
 package androidx.camera.core.impl.utils
 
+import android.os.Build
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.Observer
+import androidx.testutils.MainDispatcherRule
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
 import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.asCoroutineDispatcher
 import kotlinx.coroutines.runBlocking
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertThrows
+import org.junit.Assert
 import org.junit.Before
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+import org.robolectric.annotation.internal.DoNotInstrument
 
-@RunWith(JUnit4::class)
+@RunWith(RobolectricTestRunner::class)
+@DoNotInstrument
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
 class LiveDataUtilTest {
+    @get:Rule
+    val dispatcherRule = MainDispatcherRule(MoreExecutors.directExecutor().asCoroutineDispatcher())
+
     private lateinit var sourceLiveData: MutableLiveData<Int>
     private lateinit var redirectableLiveData: RedirectableLiveData<Int>
 
@@ -47,7 +59,7 @@
             sourceLiveData.value = 5
             val mappedLiveData = LiveDataUtil.map(sourceLiveData) { it * 2 }
 
-            assertEquals(10, mappedLiveData.value)
+            assertThat(mappedLiveData.value).isEqualTo(10)
         }
 
     @Test
@@ -67,7 +79,7 @@
 
     @Test
     fun redirectableLiveData_initialValue_isReturnedBeforeRedirection() =
-        runBlocking(Dispatchers.Main) { assertEquals(0, redirectableLiveData.value) }
+        runBlocking(Dispatchers.Main) { assertThat(redirectableLiveData.value).isEqualTo(0) }
 
     @Test
     fun redirectableLiveData_reflectsSourceValueAfterRedirection() =
@@ -75,7 +87,7 @@
             sourceLiveData.value = 5
             redirectableLiveData.redirectTo(sourceLiveData)
 
-            assertEquals(5, redirectableLiveData.value)
+            assertThat(redirectableLiveData.value).isEqualTo(5)
         }
 
     @Test
@@ -94,19 +106,23 @@
         }
 
     @Test
-    fun redirectableLiveData_withMapping_returnsMappedValueWithoutObservers() =
+    fun mappingRedirectableLiveData_returnsMappedValueWithoutObservers() =
         runBlocking(Dispatchers.Main) {
             sourceLiveData.value = 5
-            redirectableLiveData.redirectToWithMapping(sourceLiveData) { it * 2 }
+            val redirectableLiveData =
+                MappingRedirectableLiveData<Int, Int>(0) { it * 2 }
+                    .apply { redirectTo(sourceLiveData) }
 
-            assertEquals(10, redirectableLiveData.value)
+            assertThat(redirectableLiveData.value).isEqualTo(10)
         }
 
     @Test
-    fun redirectableLiveData_withMapping_propagatesMappedChangesToObservers() =
+    fun mappingRedirectableLiveData_propagatesMappedChangesToObservers() =
         runBlocking(Dispatchers.Main) {
             sourceLiveData.value = 5
-            redirectableLiveData.redirectToWithMapping(sourceLiveData) { it * 2 }
+            val redirectableLiveData =
+                MappingRedirectableLiveData<Int, Int>(0) { it * 2 }
+                    .apply { redirectTo(sourceLiveData) }
 
             @Suppress("UNCHECKED_CAST") val observer = mock(Observer::class.java) as Observer<Int>
             redirectableLiveData.observeForever(observer)
@@ -123,38 +139,41 @@
             sourceLiveData.value = 5
             redirectableLiveData.redirectTo(sourceLiveData)
 
-            assertEquals(5, redirectableLiveData.value)
+            assertThat(redirectableLiveData.value).isEqualTo(5)
 
             sourceLiveData.value = 10
 
-            assertEquals(10, redirectableLiveData.value)
+            assertThat(redirectableLiveData.value).isEqualTo(10)
         }
 
     @Test
-    fun redirectableLiveData_getValueReflectsLatestSourceValueWithMappingEvenWithoutObservers() =
+    fun mappingRedirectableLiveData_getValueReflectsLatestSourceValueEvenWithoutObservers() =
         runBlocking(Dispatchers.Main) {
             sourceLiveData.value = 5
-            redirectableLiveData.redirectToWithMapping(sourceLiveData) { it * 2 }
+            val redirectableLiveData =
+                MappingRedirectableLiveData<Int, Int>(0) { it * 2 }
+                    .apply { redirectTo(sourceLiveData) }
 
-            assertEquals(10, redirectableLiveData.value)
+            assertThat(redirectableLiveData.value).isEqualTo(10)
 
             sourceLiveData.value = 10
 
-            assertEquals(20, redirectableLiveData.value)
+            assertThat(redirectableLiveData.value).isEqualTo(20)
         }
 
     @Test
     fun redirectableLiveData_addSource_throwsUnsupportedOperationException() =
         runBlocking(Dispatchers.Main) {
             val otherLiveData = MutableLiveData<String>()
+
             @Suppress("UNCHECKED_CAST")
             val observer = mock(Observer::class.java) as Observer<String>
 
-            assertThrows(UnsupportedOperationException::class.java) {
+            Assert.assertThrows(UnsupportedOperationException::class.java) {
                 redirectableLiveData.addSource(otherLiveData, observer)
             }
 
-            verifyZeroInteractions(observer)
+            verifyNoMoreInteractions(observer)
         }
 
     @Test
@@ -178,22 +197,28 @@
             verify(observer).onChanged(100)
             verify(observer).onChanged(200)
 
-            assertEquals(200, redirectableLiveData.value)
+            assertThat(redirectableLiveData.value).isEqualTo(200)
         }
 
     @Test
-    fun redirectableLiveData_redirectToWithMapping_switchToNewSourceWithMapping_correctly() =
+    fun mappingRedirectableLiveData_redirectTo_switchToNewSourceWithMapping_correctly() =
         runBlocking(Dispatchers.Main) {
             val sourceLiveData2 = MutableLiveData<Int>()
             sourceLiveData.value = 1
             sourceLiveData2.value = 100
-            redirectableLiveData.redirectTo(sourceLiveData)
+            var redirectableLiveData =
+                MappingRedirectableLiveData<Int, Int>(0) { it }.apply { redirectTo(sourceLiveData) }
 
             @Suppress("UNCHECKED_CAST") val observer = mock(Observer::class.java) as Observer<Int>
             redirectableLiveData.observeForever(observer)
 
             sourceLiveData.value = 2
-            redirectableLiveData.redirectToWithMapping(sourceLiveData2) { it + 1000 }
+            redirectableLiveData =
+                MappingRedirectableLiveData<Int, Int>(0) { it + 1000 }
+                    .apply {
+                        redirectTo(sourceLiveData2)
+                        observeForever(observer)
+                    }
             sourceLiveData.value = 3 // Should not be observed
             sourceLiveData2.value = 200
 
@@ -202,6 +227,20 @@
             verify(observer).onChanged(1100)
             verify(observer).onChanged(1200)
 
-            assertEquals(1200, redirectableLiveData.value)
+            assertThat(redirectableLiveData.value).isEqualTo(1200)
+        }
+
+    @Test
+    fun mappingRedirectableLiveData_returnsNullWhenSetAfterNonNullInitialValue() =
+        runBlocking(Dispatchers.Main) {
+            val sourceLiveData = MutableLiveData<Int?>()
+            sourceLiveData.value = 0
+            var redirectableLiveData =
+                MappingRedirectableLiveData<Int?, Int?>(0) { it }
+                    .apply { redirectTo(sourceLiveData) }
+
+            sourceLiveData.value = null
+
+            assertThat(redirectableLiveData.value).isNull()
         }
 }
diff --git a/camera/camera-feature-combination-query/src/main/java/androidx/camera/featurecombinationquery/CameraDeviceSetupCompat.java b/camera/camera-feature-combination-query/src/main/java/androidx/camera/featurecombinationquery/CameraDeviceSetupCompat.java
index 4cfe854..e65464f 100644
--- a/camera/camera-feature-combination-query/src/main/java/androidx/camera/featurecombinationquery/CameraDeviceSetupCompat.java
+++ b/camera/camera-feature-combination-query/src/main/java/androidx/camera/featurecombinationquery/CameraDeviceSetupCompat.java
@@ -53,7 +53,8 @@
      *                               encountered a fatal error.
      * @see CameraDevice.CameraDeviceSetup#isSessionConfigurationSupported
      */
-    @NonNull SupportQueryResult isSessionConfigurationSupported(
+    @NonNull
+    SupportQueryResult isSessionConfigurationSupported(
             @NonNull SessionConfiguration sessionConfig) throws CameraAccessException;
 
     /**
@@ -128,7 +129,8 @@
          * @param source          The source of the result.
          * @param timestampMillis The epoch timestamp of when the result was updated.
          */
-        public SupportQueryResult(int supported, int source, long timestampMillis) {
+        public SupportQueryResult(@Supported int supported, @Sources int source,
+                long timestampMillis) {
             mSupported = supported;
             mSource = source;
             mTimestampMillis = timestampMillis;
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java
index 6d99713..a769d33 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeCameraControl.java
@@ -28,6 +28,7 @@
 
 import androidx.annotation.GuardedBy;
 import androidx.annotation.RestrictTo;
+import androidx.camera.core.CameraControl;
 import androidx.camera.core.FocusMeteringAction;
 import androidx.camera.core.FocusMeteringResult;
 import androidx.camera.core.ImageCapture;
@@ -58,8 +59,9 @@
 
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
-import java.util.Objects;
+import java.util.Map;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicReference;
@@ -108,6 +110,16 @@
     @GuardedBy("mLock")
     private final ArrayDeque<CaptureResult> mCaptureResults = new ArrayDeque<>();
 
+    private boolean mIsFocusMeteringAutoCompleted = true;
+    @GuardedBy("mLock")
+    private final ArrayDeque<FocusMeteringAction> mRequestedFocusMeteringActions =
+            new ArrayDeque<>();
+    @GuardedBy("mLock")
+    private final Map<FocusMeteringAction, CallbackToFutureAdapter.Completer<FocusMeteringResult>>
+            mFocusMeteringActionToResultMap = new HashMap<>();
+    @GuardedBy("mLock")
+    private final ArrayDeque<FocusMeteringResult> mFocusMeteringResults = new ArrayDeque<>();
+
     private final List<CaptureSuccessListener> mCaptureSuccessListeners =
             new CopyOnWriteArrayList<>();
 
@@ -255,7 +267,7 @@
                 switch (captureStatus) {
                     case CAPTURE_STATUS_SUCCESSFUL:
                         cameraCaptureCallback.onCaptureCompleted(captureConfig.getId(),
-                                Objects.requireNonNull(captureResult));
+                                requireNonNull(captureResult));
                         break;
                     case CAPTURE_STATUS_FAILED:
                         cameraCaptureCallback.onCaptureFailed(captureConfig.getId(),
@@ -392,7 +404,7 @@
                     completerRef.set(completer);
                     return "fakeFuture";
                 }));
-                mSubmittedCompleterList.add(Objects.requireNonNull(completerRef.get()));
+                mSubmittedCompleterList.add(requireNonNull(completerRef.get()));
             }
         }
 
@@ -434,7 +446,8 @@
     }
 
     /**
-     * Stores the last submitted {@link FocusMeteringAction}.
+     * Stores the last submitted {@link FocusMeteringAction} and returns a result that may still be
+     * incomplete based on {@link #disableFocusMeteringAutoComplete(boolean)}.
      *
      * @param action The {@link FocusMeteringAction} to be used.
      * @return Returns a {@link Futures#immediateFuture} which immediately contains a empty
@@ -444,6 +457,28 @@
     public @NonNull ListenableFuture<FocusMeteringResult> startFocusAndMetering(
             @NonNull FocusMeteringAction action) {
         mLastSubmittedFocusMeteringAction = action;
+
+        if (!mIsFocusMeteringAutoCompleted) {
+            synchronized (mLock) {
+                mRequestedFocusMeteringActions.add(action);
+
+                AtomicReference<CallbackToFutureAdapter.Completer<FocusMeteringResult>>
+                        resultCompleter = new AtomicReference<>();
+
+                ListenableFuture<FocusMeteringResult> future = CallbackToFutureAdapter.getFuture(
+                        completer -> {
+                            resultCompleter.set(completer);
+                            return "focusMeteringResultFuture";
+                        });
+
+                // CallbackToFutureAdapter.getFuture provides completer synchronously, so it should
+                // already be available
+                mFocusMeteringActionToResultMap.put(action, resultCompleter.get());
+
+                return future;
+            }
+        }
+
         return Futures.immediateFuture(FocusMeteringResult.emptyInstance());
     }
 
@@ -590,6 +625,104 @@
     }
 
     /**
+     * Disables the auto-completion behavior of {@link #startFocusAndMetering(FocusMeteringAction)}.
+     *
+     * <p> Currently, {@link #startFocusAndMetering(FocusMeteringAction)} immediately provides a
+     * completed result by default and no request result is ever pending. This will allow to disable
+     * that behavior so that focus metering status of started but not completed can be tested.
+     *
+     * @param disable Whether to disable or enable.
+     *
+     * @see #submitFocusMeteringResult(FocusMeteringResult)
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public void disableFocusMeteringAutoComplete(boolean disable) {
+        mIsFocusMeteringAutoCompleted = !disable;
+    }
+
+    /**
+     * Submits a {@link FocusMeteringResult} to be used for the first pending focus-metering
+     * request.
+     *
+     * <p> This method will complete a corresponding focus-metering request according to the
+     * provided result. If there are no pending requests, the `FocusMeteringResult` is kept in a
+     * queue to be used in future requests.
+     *
+     * <p> For applying a focus metering result to all already submitted requests, use the
+     * {@link #completeAllFocusMeteringRequests} method instead.
+     *
+     * @see CameraControl#startFocusAndMetering(FocusMeteringAction)
+     * @see #disableFocusMeteringAutoComplete(boolean)
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public void submitFocusMeteringResult(@NonNull FocusMeteringResult focusMeteringResult) {
+        synchronized (mLock) {
+            mFocusMeteringResults.add(focusMeteringResult);
+        }
+        applyFocusMeteringResults();
+    }
+
+    /**
+     * Completes all the incomplete focus-metering requests with the provided
+     * {@link FocusMeteringResult}.
+     *
+     * @see CameraControl#startFocusAndMetering(FocusMeteringAction)
+     * @see #disableFocusMeteringAutoComplete(boolean)
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    public void completeAllFocusMeteringRequests(@NonNull FocusMeteringResult focusMeteringResult) {
+        synchronized (mLock) {
+            // Add FocusMeteringResult instances for all pending requests first.
+            for (int i = 0; i < mRequestedFocusMeteringActions.size(); i++) {
+                mFocusMeteringResults.add(focusMeteringResult);
+            }
+        }
+
+        applyFocusMeteringResults();
+    }
+
+    private void applyFocusMeteringResults() {
+        synchronized (mLock) {
+            while (!mFocusMeteringResults.isEmpty()) {
+                FocusMeteringResult focusMeteringResult = mFocusMeteringResults.getFirst();
+
+                if (completeFirstPendingFocusMeteringRequest(focusMeteringResult)) {
+                    mFocusMeteringResults.removeFirst();
+                } else {
+                    Logger.d(TAG, "applyFocusMeteringResults: failed to notify");
+                    break;
+                }
+            }
+        }
+    }
+
+    private boolean completeFirstPendingFocusMeteringRequest(
+            @NonNull FocusMeteringResult focusMeteringResult) {
+        FocusMeteringAction focusMeteringAction;
+        CallbackToFutureAdapter.Completer<FocusMeteringResult> completer;
+
+        synchronized (mLock) {
+            if (mRequestedFocusMeteringActions.isEmpty()) {
+                Logger.d(TAG,
+                        "completeFirstPendingFocusMeteringRequest: returning early since "
+                                + "mRequestedFocusMeteringActions is empty!");
+                return false;
+            }
+
+            focusMeteringAction = mRequestedFocusMeteringActions.removeFirst();
+            completer = mFocusMeteringActionToResultMap.get(focusMeteringAction);
+        }
+
+        if (completer == null) {
+            Logger.e(TAG, "completeFirstPendingFocusMeteringRequest: completer is null!");
+            return false;
+        }
+
+        completer.set(focusMeteringResult);
+        return true;
+    }
+
+    /**
      * Adds a listener to be notified when there are completed capture requests.
      *
      * @param listener {@link CaptureSuccessListener} that is notified with the submitted
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/ExtensionsUtil.kt b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/ExtensionsUtil.kt
index 7ddd527..5b3cd9a 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/ExtensionsUtil.kt
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/ExtensionsUtil.kt
@@ -26,6 +26,7 @@
 import androidx.camera.core.CameraSelector
 import androidx.camera.core.ImageCapture
 import androidx.camera.core.impl.CameraConfig
+import androidx.camera.core.impl.CameraConfig.REQUIRED_RULE_COEXISTING_PREVIEW_AND_IMAGE_CAPTURE
 import androidx.camera.core.impl.CameraInfoInternal
 import androidx.camera.core.impl.Config
 import androidx.camera.core.impl.ExtendedCameraConfigProviderStore
@@ -78,6 +79,10 @@
                     return sessionProcessor
                 }
 
+                override fun getUseCaseCombinationRequiredRule(): Int {
+                    return REQUIRED_RULE_COEXISTING_PREVIEW_AND_IMAGE_CAPTURE
+                }
+
                 override fun getUseCaseConfigFactory(): UseCaseConfigFactory =
                     object : UseCaseConfigFactory {
                         override fun getConfig(
diff --git a/camera/camera-view/api/current.txt b/camera/camera-view/api/current.txt
index d2fd422..94f26d4f 100644
--- a/camera/camera-view/api/current.txt
+++ b/camera/camera-view/api/current.txt
@@ -22,7 +22,8 @@
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> getInitializationFuture();
     method @MainThread public androidx.camera.core.resolutionselector.ResolutionSelector? getPreviewResolutionSelector();
     method @Deprecated @MainThread public androidx.camera.view.CameraController.OutputSize? getPreviewTargetSize();
-    method @MainThread public androidx.lifecycle.LiveData<java.lang.Integer!> getTapToFocusState();
+    method @MainThread public androidx.lifecycle.LiveData<androidx.camera.view.TapToFocusInfo!> getTapToFocusInfoState();
+    method @Deprecated @MainThread public androidx.lifecycle.LiveData<java.lang.Integer!> getTapToFocusState();
     method @MainThread public androidx.lifecycle.LiveData<java.lang.Integer!> getTorchState();
     method @MainThread public androidx.camera.core.DynamicRange getVideoCaptureDynamicRange();
     method @MainThread public int getVideoCaptureMirrorMode();
@@ -154,6 +155,14 @@
     method @UiThread public void setScreenFlashWindow(android.view.Window?);
   }
 
+  public final class TapToFocusInfo {
+    ctor public TapToFocusInfo(int focusState, android.graphics.PointF? tapPoint);
+    method public int getFocusState();
+    method public android.graphics.PointF? getTapPoint();
+    property public final int focusState;
+    property public final android.graphics.PointF? tapPoint;
+  }
+
 }
 
 package androidx.camera.view.transform {
diff --git a/camera/camera-view/api/restricted_current.txt b/camera/camera-view/api/restricted_current.txt
index d2fd422..94f26d4f 100644
--- a/camera/camera-view/api/restricted_current.txt
+++ b/camera/camera-view/api/restricted_current.txt
@@ -22,7 +22,8 @@
     method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> getInitializationFuture();
     method @MainThread public androidx.camera.core.resolutionselector.ResolutionSelector? getPreviewResolutionSelector();
     method @Deprecated @MainThread public androidx.camera.view.CameraController.OutputSize? getPreviewTargetSize();
-    method @MainThread public androidx.lifecycle.LiveData<java.lang.Integer!> getTapToFocusState();
+    method @MainThread public androidx.lifecycle.LiveData<androidx.camera.view.TapToFocusInfo!> getTapToFocusInfoState();
+    method @Deprecated @MainThread public androidx.lifecycle.LiveData<java.lang.Integer!> getTapToFocusState();
     method @MainThread public androidx.lifecycle.LiveData<java.lang.Integer!> getTorchState();
     method @MainThread public androidx.camera.core.DynamicRange getVideoCaptureDynamicRange();
     method @MainThread public int getVideoCaptureMirrorMode();
@@ -154,6 +155,14 @@
     method @UiThread public void setScreenFlashWindow(android.view.Window?);
   }
 
+  public final class TapToFocusInfo {
+    ctor public TapToFocusInfo(int focusState, android.graphics.PointF? tapPoint);
+    method public int getFocusState();
+    method public android.graphics.PointF? getTapPoint();
+    property public final int focusState;
+    property public final android.graphics.PointF? tapPoint;
+  }
+
 }
 
 package androidx.camera.view.transform {
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java b/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java
index f720b8e..7ee8e01 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/CameraController.java
@@ -28,8 +28,12 @@
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.graphics.Matrix;
+import android.graphics.PointF;
 import android.hardware.camera2.CaptureResult;
 import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
 import android.util.Range;
 import android.util.Rational;
 import android.util.Size;
@@ -73,6 +77,7 @@
 import androidx.camera.core.impl.StreamSpec;
 import androidx.camera.core.impl.utils.CameraOrientationUtil;
 import androidx.camera.core.impl.utils.ContextUtil;
+import androidx.camera.core.impl.utils.LiveDataUtil;
 import androidx.camera.core.impl.utils.Threads;
 import androidx.camera.core.impl.utils.futures.FutureCallback;
 import androidx.camera.core.impl.utils.futures.Futures;
@@ -318,13 +323,14 @@
 
     private boolean mPinchToZoomEnabled = true;
     private boolean mTapToFocusEnabled = true;
+    private long mLatestFocusCancelTimeMillis;
 
     private final ForwardingLiveData<ZoomState> mZoomState = new ForwardingLiveData<>();
     private final ForwardingLiveData<Integer> mTorchState = new ForwardingLiveData<>();
-    // Synthetic access
-    @SuppressWarnings("WeakerAccess")
-    final MutableLiveData<Integer> mTapToFocusState = new MutableLiveData<>(
-            TAP_TO_FOCUS_NOT_STARTED);
+    final MutableLiveData<TapToFocusInfo> mTapToFocusInfoState = new MutableLiveData<>(
+            new TapToFocusInfo(TAP_TO_FOCUS_NOT_STARTED, /* tapPoint = */ null));
+    final LiveData<Integer> mTapToFocusState = LiveDataUtil.map(mTapToFocusInfoState,
+            TapToFocusInfo::getFocusState);
 
     private final @NonNull PendingValue<Boolean> mPendingEnableTorch = new PendingValue<>();
 
@@ -2163,7 +2169,7 @@
             return;
         }
         Logger.d(TAG, "Tap to focus started: " + x + ", " + y);
-        mTapToFocusState.postValue(TAP_TO_FOCUS_STARTED);
+        mTapToFocusInfoState.postValue(new TapToFocusInfo(TAP_TO_FOCUS_STARTED, new PointF(x, y)));
         MeteringPoint afPoint = meteringPointFactory.createPoint(x, y, AF_SIZE);
         MeteringPoint aePoint = meteringPointFactory.createPoint(x, y, AE_SIZE);
         FocusMeteringAction focusMeteringAction = new FocusMeteringAction
@@ -2179,8 +2185,9 @@
                             return;
                         }
                         Logger.d(TAG, "Tap to focus onSuccess: " + result.isFocusSuccessful());
-                        mTapToFocusState.postValue(result.isFocusSuccessful()
-                                ? TAP_TO_FOCUS_FOCUSED : TAP_TO_FOCUS_NOT_FOCUSED);
+                        mTapToFocusInfoState.postValue(new TapToFocusInfo(
+                                result.isFocusSuccessful() ? TAP_TO_FOCUS_FOCUSED
+                                        : TAP_TO_FOCUS_NOT_FOCUSED, new PointF(x, y)));
                     }
 
                     @Override
@@ -2190,9 +2197,30 @@
                             return;
                         }
                         Logger.d(TAG, "Tap to focus failed.", t);
-                        mTapToFocusState.postValue(TAP_TO_FOCUS_FAILED);
+                        mTapToFocusInfoState.postValue(
+                                new TapToFocusInfo(TAP_TO_FOCUS_FAILED, new PointF(x, y)));
                     }
                 }, directExecutor());
+
+        mLatestFocusCancelTimeMillis = 0; // reset to default first
+        long cancelDuration = focusMeteringAction.getAutoCancelDurationInMillis();
+        if (cancelDuration > 0L) {
+            mLatestFocusCancelTimeMillis = SystemClock.elapsedRealtime() + cancelDuration;
+            new Handler(Looper.getMainLooper()).postDelayed(() -> {
+                long currentTime = SystemClock.elapsedRealtime();
+                if (mLatestFocusCancelTimeMillis != 0
+                        && currentTime < mLatestFocusCancelTimeMillis) {
+                    Logger.d(TAG, "Ignoring current focus cancel event due to this not"
+                            + " being the latest cancel time, probably a new focus event arrived: "
+                            + "mLatestFocusCancelTimeMillis = " + mLatestFocusCancelTimeMillis
+                            + ", current time = " + currentTime);
+                    // There's a new focus event that came after this cancel event was scheduled.
+                    return;
+                }
+                mTapToFocusInfoState.postValue(new TapToFocusInfo(TAP_TO_FOCUS_NOT_STARTED, null));
+                mLatestFocusCancelTimeMillis = 0;
+            }, cancelDuration);
+        }
     }
 
     /**
@@ -2242,12 +2270,12 @@
      *     <td>TAP_TO_FOCUS_STARTED</td>
      * </tr>
      * <tr>
-     *     <td>TAP_TO_FOCUS_SUCCESSFUL</td>
+     *     <td>TAP_TO_FOCUS_FOCUSED</td>
      *     <td>User taps on {@link PreviewView}</td>
      *     <td>TAP_TO_FOCUS_STARTED</td>
      * </tr>
      * <tr>
-     *     <td>TAP_TO_FOCUS_UNSUCCESSFUL</td>
+     *     <td>TAP_TO_FOCUS_NOT_FOCUSED</td>
      *     <td>User taps on {@link PreviewView}</td>
      *     <td>TAP_TO_FOCUS_STARTED</td>
      * </tr>
@@ -2259,25 +2287,118 @@
      * <tr>
      *     <td rowspan="3">TAP_TO_FOCUS_STARTED</td>
      *     <td>Focusing succeeded</td>
-     *     <td>TAP_TO_FOCUS_SUCCESSFUL</td>
+     *     <td>TAP_TO_FOCUS_FOCUSED</td>
      * </tr>
      * <tr>
      *     <td>Focusing failed due to lighting and/or camera distance</td>
-     *     <td>TAP_TO_FOCUS_UNSUCCESSFUL</td>
+     *     <td>TAP_TO_FOCUS_NOT_FOCUSED</td>
      * </tr>
      * <tr>
      *     <td>Focusing failed due to device constraints</td>
      *     <td>TAP_TO_FOCUS_FAILED</td>
      * </tr>
+     * <tr>
+     *     <td>TAP_TO_FOCUS_FOCUSED</td>
+     *     <td>Auto-cancel duration elapses</td>
+     *     <td>TAP_TO_FOCUS_NOT_STARTED</td>
+     * </tr>
+     * <tr>
+     *     <td>TAP_TO_FOCUS_NOT_FOCUSED</td>
+     *     <td>Auto-cancel duration elapses</td>
+     *     <td>TAP_TO_FOCUS_NOT_STARTED</td>
+     * </tr>
+     * <tr>
+     *     <td>TAP_TO_FOCUS_FAILED</td>
+     *     <td>Auto-cancel duration elapses</td>
+     *     <td>TAP_TO_FOCUS_NOT_STARTED</td>
+     * </tr>
+     * </table>
+     *
+     * @see #setTapToFocusEnabled(boolean)
+     * @see CameraControl#startFocusAndMetering(FocusMeteringAction)
+     *
+     * @deprecated Use {@link #getTapToFocusInfoState()} instead.
+     */
+    @Deprecated
+    @MainThread
+    public @NonNull LiveData<Integer> getTapToFocusState() {
+        checkMainThread();
+        return mTapToFocusState;
+    }
+
+    /**
+     * Returns a {@link LiveData} with a {@link TapToFocusInfo} containing the latest focus state
+     * and corresponding tap position.
+     *
+     * <p>When tap-to-focus feature is enabled, the {@link LiveData} will receive updates of
+     * focusing states. This usually happens when the end user taps on {@link PreviewView}, and then
+     * again when focusing is finished either successfully or unsuccessfully. The following table
+     * displays the states the {@link LiveData} can be in, and the possible transitions between
+     * them.
+     *
+     * <table>
+     * <tr>
+     *     <th>State</th>
+     *     <th>Transition cause</th>
+     *     <th>New State</th>
+     * </tr>
+     * <tr>
+     *     <td>TAP_TO_FOCUS_NOT_STARTED</td>
+     *     <td>User taps on {@link PreviewView}</td>
+     *     <td>TAP_TO_FOCUS_STARTED</td>
+     * </tr>
+     * <tr>
+     *     <td>TAP_TO_FOCUS_FOCUSED</td>
+     *     <td>User taps on {@link PreviewView}</td>
+     *     <td>TAP_TO_FOCUS_STARTED</td>
+     * </tr>
+     * <tr>
+     *     <td>TAP_TO_FOCUS_NOT_FOCUSED</td>
+     *     <td>User taps on {@link PreviewView}</td>
+     *     <td>TAP_TO_FOCUS_STARTED</td>
+     * </tr>
+     * <tr>
+     *     <td>TAP_TO_FOCUS_FAILED</td>
+     *     <td>User taps on {@link PreviewView}</td>
+     *     <td>TAP_TO_FOCUS_STARTED</td>
+     * </tr>
+     * <tr>
+     *     <td rowspan="3">TAP_TO_FOCUS_STARTED</td>
+     *     <td>Focusing succeeded</td>
+     *     <td>TAP_TO_FOCUS_FOCUSED</td>
+     * </tr>
+     * <tr>
+     *     <td>Focusing failed due to lighting and/or camera distance</td>
+     *     <td>TAP_TO_FOCUS_NOT_FOCUSED</td>
+     * </tr>
+     * <tr>
+     *     <td>Focusing failed due to device constraints</td>
+     *     <td>TAP_TO_FOCUS_FAILED</td>
+     * </tr>
+     * <tr>
+     *     <td>TAP_TO_FOCUS_FOCUSED</td>
+     *     <td>Auto-cancel duration elapses</td>
+     *     <td>TAP_TO_FOCUS_NOT_STARTED</td>
+     * </tr>
+     * <tr>
+     *     <td>TAP_TO_FOCUS_NOT_FOCUSED</td>
+     *     <td>Auto-cancel duration elapses</td>
+     *     <td>TAP_TO_FOCUS_NOT_STARTED</td>
+     * </tr>
+     * <tr>
+     *     <td>TAP_TO_FOCUS_FAILED</td>
+     *     <td>Auto-cancel duration elapses</td>
+     *     <td>TAP_TO_FOCUS_NOT_STARTED</td>
+     * </tr>
      * </table>
      *
      * @see #setTapToFocusEnabled(boolean)
      * @see CameraControl#startFocusAndMetering(FocusMeteringAction)
      */
     @MainThread
-    public @NonNull LiveData<Integer> getTapToFocusState() {
+    public @NonNull LiveData<TapToFocusInfo> getTapToFocusInfoState() {
         checkMainThread();
-        return mTapToFocusState;
+        return mTapToFocusInfoState;
     }
 
     /**
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/TapToFocusInfo.kt b/camera/camera-view/src/main/java/androidx/camera/view/TapToFocusInfo.kt
new file mode 100644
index 0000000..010b5ee
--- /dev/null
+++ b/camera/camera-view/src/main/java/androidx/camera/view/TapToFocusInfo.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.view
+
+import android.graphics.PointF
+import androidx.camera.core.CameraControl
+
+/**
+ * Describes the focus state and tap location that [CameraController] uses for tap-to-focus feature
+ * corresponding to the [PreviewView] touch events.
+ *
+ * @property focusState The focus state of the camera.
+ * @property tapPoint The `PreviewView` co-ordinates of user's touch event corresponding to this
+ *   focusing event. This can be null when a focusing event is not due to the user's touch event.
+ *   For example, `FocusOnTap(TAP_TO_FOCUS_NOT_STARTED, null)` is used when there is no focusing
+ *   event ongoing e.g. during initialization or after a focus event has been completed.
+ * @see CameraController
+ * @see CameraController.getTapToFocusInfoState
+ * @see CameraControl.startFocusAndMetering
+ */
+public class TapToFocusInfo(public val focusState: Int, public val tapPoint: PointF?)
diff --git a/camera/camera-view/src/test/java/androidx/camera/view/CameraControllerTest.kt b/camera/camera-view/src/test/java/androidx/camera/view/CameraControllerTest.kt
index 7dff925..2a8aab6 100644
--- a/camera/camera-view/src/test/java/androidx/camera/view/CameraControllerTest.kt
+++ b/camera/camera-view/src/test/java/androidx/camera/view/CameraControllerTest.kt
@@ -18,6 +18,7 @@
 
 import android.content.Context
 import android.graphics.Matrix
+import android.graphics.PointF
 import android.os.Build
 import android.os.Looper.getMainLooper
 import android.util.Range
@@ -28,6 +29,7 @@
 import androidx.camera.core.AspectRatio.RATIO_4_3
 import androidx.camera.core.CameraSelector
 import androidx.camera.core.DynamicRange
+import androidx.camera.core.FocusMeteringResult
 import androidx.camera.core.ImageAnalysis
 import androidx.camera.core.ImageAnalysis.COORDINATE_SYSTEM_ORIGINAL
 import androidx.camera.core.ImageAnalysis.COORDINATE_SYSTEM_VIEW_REFERENCED
@@ -37,6 +39,7 @@
 import androidx.camera.core.ImageProxy
 import androidx.camera.core.MirrorMode
 import androidx.camera.core.Preview.SurfaceProvider
+import androidx.camera.core.SurfaceOrientedMeteringPointFactory
 import androidx.camera.core.TorchState
 import androidx.camera.core.ViewPort
 import androidx.camera.core.impl.ImageAnalysisConfig
@@ -53,6 +56,10 @@
 import androidx.camera.testing.impl.fakes.FakeSurfaceProcessor
 import androidx.camera.video.Quality
 import androidx.camera.video.QualitySelector
+import androidx.camera.view.CameraController.TAP_TO_FOCUS_FOCUSED
+import androidx.camera.view.CameraController.TAP_TO_FOCUS_NOT_FOCUSED
+import androidx.camera.view.CameraController.TAP_TO_FOCUS_NOT_STARTED
+import androidx.camera.view.CameraController.TAP_TO_FOCUS_STARTED
 import androidx.camera.view.internal.ScreenFlashUiInfo
 import androidx.concurrent.futures.CallbackToFutureAdapter
 import androidx.test.annotation.UiThreadTest
@@ -60,7 +67,9 @@
 import com.google.common.truth.Truth.assertThat
 import com.google.common.util.concurrent.MoreExecutors
 import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
 import org.junit.Assert
+import org.junit.Assume.assumeTrue
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -68,16 +77,21 @@
 import org.robolectric.Shadows.shadowOf
 import org.robolectric.annotation.Config
 import org.robolectric.annotation.internal.DoNotInstrument
+import org.robolectric.shadows.ShadowSystemClock
 
 /** Unit tests for [CameraController]. */
 @RunWith(RobolectricTestRunner::class)
 @DoNotInstrument
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+@Config(
+    minSdk = Build.VERSION_CODES.LOLLIPOP,
+    instrumentedPackages = ["androidx.camera.view"], // required for shadow clock to work
+)
 class CameraControllerTest {
     companion object {
         const val LINEAR_ZOOM = .1F
         const val ZOOM_RATIO = .5F
         const val TORCH_ENABLED = true
+        const val FOCUS_AUTO_CANCEL_TIMEOUT_MILLIS = 5000L
     }
 
     private val previewViewTransform = Matrix().also { it.postRotate(90F) }
@@ -101,6 +115,8 @@
     private lateinit var lifecycleCameraProviderCompleter:
         CallbackToFutureAdapter.Completer<ProcessCameraProviderWrapper>
 
+    private val pointFactory = SurfaceOrientedMeteringPointFactory(1f, 1f)
+
     @Before
     fun setUp() {
         val lifecycleCameraProviderFuture =
@@ -717,4 +733,243 @@
         val imageAnalysisConfig = controller.mImageAnalysis.currentConfig as ImageOutputConfig
         assertThat(imageAnalysisConfig.getResolutionSelector(null)).isNull()
     }
+
+    @Test
+    fun onTapToFocus_focusMeteringActionSubmittedToCamera() {
+        completeCameraInitialization()
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+        assertThat(fakeCameraControl.lastSubmittedFocusMeteringAction).isNotNull()
+    }
+
+    @Test
+    fun getTapToFocusInfoState_defaultStateIsTapToFocusNotStarted() {
+        assertThat(controller.tapToFocusInfoState.value?.focusState)
+            .isEqualTo(TAP_TO_FOCUS_NOT_STARTED)
+    }
+
+    @Test
+    fun getTapToFocusInfoState_tapPointIsSameAsOriginal_whenOnTapToFocusIsCalled() {
+        val tapPoint = PointF(1F, 2F)
+        completeCameraInitialization()
+
+        controller.onTapToFocus(pointFactory, tapPoint.x, tapPoint.y)
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusInfoState.value?.tapPoint).isEqualTo(tapPoint)
+    }
+
+    @Test
+    fun getTapToFocusInfoState_tapPointIsSameAsLastOne_whenOnTapToFocusIsCalledTwice() {
+        val tapPoint1 = PointF(1F, 2F)
+        val tapPoint2 = PointF(1F, 2F)
+        completeCameraInitialization()
+
+        controller.onTapToFocus(pointFactory, tapPoint1.x, tapPoint1.y)
+        controller.onTapToFocus(pointFactory, tapPoint2.x, tapPoint2.y)
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusInfoState.value?.tapPoint).isEqualTo(tapPoint2)
+    }
+
+    @Test
+    fun getTapToFocusInfoState_stateIsTapToFocusStarted_whenOnTapToFocusIsCalled() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusInfoState.value?.focusState).isEqualTo(TAP_TO_FOCUS_STARTED)
+    }
+
+    @Suppress("DEPRECATION")
+    @Test
+    fun getTapToFocusState_stateIsTapToFocusStarted_whenOnTapToFocusIsCalled() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusState.value).isEqualTo(TAP_TO_FOCUS_STARTED)
+    }
+
+    @Test
+    fun getTapToFocusInfoState_stateIsTapToFocusFocused_whenSuccessfulResultIsSubmitted() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+        fakeCameraControl.submitFocusMeteringResult(FocusMeteringResult.create(true))
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusInfoState.value?.focusState).isEqualTo(TAP_TO_FOCUS_FOCUSED)
+    }
+
+    @Suppress("DEPRECATION")
+    @Test
+    fun getTapToFocusState_stateIsTapToFocusFocused_whenSuccessfulResultIsSubmitted() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+        fakeCameraControl.submitFocusMeteringResult(FocusMeteringResult.create(true))
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusState.value).isEqualTo(TAP_TO_FOCUS_FOCUSED)
+    }
+
+    @Test
+    fun getTapToFocusInfoState_stateIsTapToFocusNotFocused_whenUnsuccessfulResultIsSubmitted() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+        fakeCameraControl.submitFocusMeteringResult(FocusMeteringResult.create(false))
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusInfoState.value?.focusState)
+            .isEqualTo(TAP_TO_FOCUS_NOT_FOCUSED)
+    }
+
+    @Suppress("DEPRECATION")
+    @Test
+    fun getTapToFocusState_stateIsTapToFocusNotFocused_whenUnsuccessfulResultIsSubmitted() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+        fakeCameraControl.submitFocusMeteringResult(FocusMeteringResult.create(false))
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusState.value).isEqualTo(TAP_TO_FOCUS_NOT_FOCUSED)
+    }
+
+    @Test
+    fun getTapToFocusInfoState_stateIsTapToFocusStarted_beforeAutoCancelDurationIsElapsed() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+        ShadowSystemClock.advanceBy(FOCUS_AUTO_CANCEL_TIMEOUT_MILLIS - 1, TimeUnit.MILLISECONDS)
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusInfoState.value?.focusState).isEqualTo(TAP_TO_FOCUS_STARTED)
+    }
+
+    @Suppress("DEPRECATION")
+    @Test
+    fun getTapToFocusState_stateIsTapToFocusStarted_beforeAutoCancelDurationIsElapsed() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+        ShadowSystemClock.advanceBy(FOCUS_AUTO_CANCEL_TIMEOUT_MILLIS - 1, TimeUnit.MILLISECONDS)
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusState.value).isEqualTo(TAP_TO_FOCUS_STARTED)
+    }
+
+    @Test
+    fun getTapToFocusInfoState_stateIsNotStarted_whenAutoCancelDurationIsElapsedAfterStarted() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+
+        shadowOf(getMainLooper()).idle()
+        assumeTrue(controller.tapToFocusInfoState.value?.focusState == TAP_TO_FOCUS_STARTED)
+
+        ShadowSystemClock.advanceBy(FOCUS_AUTO_CANCEL_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusInfoState.value?.focusState)
+            .isEqualTo(TAP_TO_FOCUS_NOT_STARTED)
+    }
+
+    @Suppress("DEPRECATION")
+    @Test
+    fun getTapToFocusState_stateIsNotStarted_whenAutoCancelDurationIsElapsedAfterStarted() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+
+        shadowOf(getMainLooper()).idle()
+        assumeTrue(controller.tapToFocusState.value == TAP_TO_FOCUS_STARTED)
+
+        ShadowSystemClock.advanceBy(FOCUS_AUTO_CANCEL_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusState.value).isEqualTo(TAP_TO_FOCUS_NOT_STARTED)
+    }
+
+    @Test
+    fun getTapToFocusInfoState_stateIsNotStarted_whenAutoCancelDurationIsElapsedAfterFocused() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+        fakeCameraControl.submitFocusMeteringResult(FocusMeteringResult.create(true))
+        shadowOf(getMainLooper()).idle()
+        assumeTrue(controller.tapToFocusInfoState.value?.focusState == TAP_TO_FOCUS_FOCUSED)
+
+        ShadowSystemClock.advanceBy(FOCUS_AUTO_CANCEL_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusInfoState.value?.focusState)
+            .isEqualTo(TAP_TO_FOCUS_NOT_STARTED)
+    }
+
+    @Suppress("DEPRECATION")
+    @Test
+    fun getTapToFocusState_stateIsNotStarted_whenAutoCancelDurationIsElapsedAfterFocused() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+        fakeCameraControl.submitFocusMeteringResult(FocusMeteringResult.create(true))
+        shadowOf(getMainLooper()).idle()
+        assumeTrue(controller.tapToFocusState.value == TAP_TO_FOCUS_FOCUSED)
+
+        ShadowSystemClock.advanceBy(FOCUS_AUTO_CANCEL_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusState.value).isEqualTo(TAP_TO_FOCUS_NOT_STARTED)
+    }
+
+    @Test
+    fun getTapToFocusInfoState_stateIsNotStarted_whenAutoCancelDurationIsElapsedAfterNotFocused() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+        fakeCameraControl.submitFocusMeteringResult(FocusMeteringResult.create(false))
+        shadowOf(getMainLooper()).idle()
+        assumeTrue(controller.tapToFocusInfoState.value?.focusState == TAP_TO_FOCUS_NOT_FOCUSED)
+
+        ShadowSystemClock.advanceBy(FOCUS_AUTO_CANCEL_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusInfoState.value?.focusState)
+            .isEqualTo(TAP_TO_FOCUS_NOT_STARTED)
+    }
+
+    @Suppress("DEPRECATION")
+    @Test
+    fun getTapToFocusState_stateIsNotStarted_whenAutoCancelDurationIsElapsedAfterNotFocused() {
+        completeCameraInitialization()
+        fakeCameraControl.disableFocusMeteringAutoComplete(true)
+
+        controller.onTapToFocus(pointFactory, 0f, 0f)
+        fakeCameraControl.submitFocusMeteringResult(FocusMeteringResult.create(false))
+        shadowOf(getMainLooper()).idle()
+        assumeTrue(controller.tapToFocusState.value == TAP_TO_FOCUS_NOT_FOCUSED)
+
+        ShadowSystemClock.advanceBy(FOCUS_AUTO_CANCEL_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)
+
+        shadowOf(getMainLooper()).idle()
+        assertThat(controller.tapToFocusState.value).isEqualTo(TAP_TO_FOCUS_NOT_STARTED)
+    }
 }
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ZoomControlDeviceTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ZoomControlDeviceTest.kt
index 6d0d0c6..3be303b 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ZoomControlDeviceTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ZoomControlDeviceTest.kt
@@ -797,20 +797,22 @@
 
     @Test
     @SdkSuppress(minSdkVersion = 30)
-    fun zoomObserverValueIsCorrect_withSessionProcessor(): Unit = runBlocking {
-        val zoomRatio = 2f
-        val camera = bindWithSessionProcessorZoomLimitation(minZoom = MIN_ZOOM, maxZoom = MAX_ZOOM)
+    fun zoomObserverValueIsCorrect_withSessionProcessor(): Unit =
+        runBlocking(Dispatchers.Main) {
+            val zoomRatio = 2f
+            val camera =
+                bindWithSessionProcessorZoomLimitation(minZoom = MIN_ZOOM, maxZoom = MAX_ZOOM)
 
-        camera.cameraControl.setZoomRatio(zoomRatio)
-        camera.cameraInfo.zoomState.verifyZoomState(
-            ImmutableZoomState.create(
-                zoomRatio,
-                MAX_ZOOM,
-                MIN_ZOOM,
-                AdapterCameraInfo.getPercentageByRatio(zoomRatio, MIN_ZOOM, MAX_ZOOM)
+            camera.cameraControl.setZoomRatio(zoomRatio)
+            camera.cameraInfo.zoomState.verifyZoomState(
+                ImmutableZoomState.create(
+                    zoomRatio,
+                    MAX_ZOOM,
+                    MIN_ZOOM,
+                    AdapterCameraInfo.getPercentageByRatio(zoomRatio, MIN_ZOOM, MAX_ZOOM)
+                )
             )
-        )
-    }
+        }
 
     private fun Camera.verifyLinearZoom(linearZoom: Float, minZoom: Float, maxZoom: Float) {
         cameraControl.setLinearZoom(linearZoom)
@@ -842,20 +844,22 @@
 
     @Test
     @SdkSuppress(minSdkVersion = 30)
-    fun linearZoomObserverValueIsCorrect_withSessionProcessor(): Unit = runBlocking {
-        val linearZoom = 0.5f
-        val camera = bindWithSessionProcessorZoomLimitation(minZoom = MIN_ZOOM, maxZoom = MAX_ZOOM)
+    fun linearZoomObserverValueIsCorrect_withSessionProcessor(): Unit =
+        runBlocking(Dispatchers.Main) {
+            val linearZoom = 0.5f
+            val camera =
+                bindWithSessionProcessorZoomLimitation(minZoom = MIN_ZOOM, maxZoom = MAX_ZOOM)
 
-        camera.cameraControl.setLinearZoom(linearZoom)
-        camera.cameraInfo.zoomState.verifyZoomState(
-            ImmutableZoomState.create(
-                AdapterCameraInfo.getZoomRatioByPercentage(linearZoom, MIN_ZOOM, MAX_ZOOM),
-                MAX_ZOOM,
-                MIN_ZOOM,
-                linearZoom
+            camera.cameraControl.setLinearZoom(linearZoom)
+            camera.cameraInfo.zoomState.verifyZoomState(
+                ImmutableZoomState.create(
+                    AdapterCameraInfo.getZoomRatioByPercentage(linearZoom, MIN_ZOOM, MAX_ZOOM),
+                    MAX_ZOOM,
+                    MIN_ZOOM,
+                    linearZoom
+                )
             )
-        )
-    }
+        }
 
     private suspend fun LiveData<ZoomState>.verifyZoomState(expectZoomState: ZoomState) {
         val latch = CountDownLatch(1)
@@ -871,7 +875,7 @@
             }
         }
 
-        assertThat(latch.await(1, TimeUnit.SECONDS)).isTrue()
+        assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue()
         assertThat(zoomStates?.isEquivalentTo(expectZoomState)).isTrue()
     }
 
@@ -1055,7 +1059,7 @@
                     CameraSelector.DEFAULT_BACK_CAMERA,
                     CameraPipeConfig::class.simpleName,
                     CameraPipeConfig.defaultConfig()
-                ),
+                )
             )
 
         private fun ZoomState.isEquivalentTo(other: ZoomState): Boolean {
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/PreviewTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/PreviewTest.kt
index 8ebd52f..02c8e56 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/PreviewTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/camera2/PreviewTest.kt
@@ -1390,6 +1390,7 @@
 
         val previewBuilder = Preview.Builder().setPreviewStabilizationEnabled(true)
         verifyVideoStabilizationModeInResultAndFramesAvailable(
+            cameraSelector = cameraSelector,
             previewBuilder = previewBuilder,
             expectedMode = CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION
         )
@@ -1413,6 +1414,7 @@
                 .build()
 
         verifyVideoStabilizationModeInResultAndFramesAvailable(
+            cameraSelector = cameraSelector,
             previewBuilder = previewBuilder,
             videoCapture = videoCapture,
             expectedMode = CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_OFF
@@ -1438,6 +1440,7 @@
                     .build()
 
             verifyVideoStabilizationModeInResultAndFramesAvailable(
+                cameraSelector = cameraSelector,
                 previewBuilder = previewBuilder,
                 videoCapture = videoCapture,
                 expectedMode = CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION
@@ -1500,6 +1503,38 @@
     }
 
     @Test
+    @SdkSuppress(minSdkVersion = 23)
+    fun previewStabilizationCanBeSet_whenSupportedInExtensions() = runBlocking {
+        assumeTrue(isPreviewStabilizationModeSupported(CameraSelector.DEFAULT_BACK_CAMERA))
+        val sessionProcessor =
+            FakeSessionProcessor(
+                extensionSpecificChars =
+                    listOf(
+                        android.util.Pair(
+                            CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+                            intArrayOf(
+                                CameraCharacteristics
+                                    .CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION
+                            )
+                        )
+                    )
+            )
+        val cameraSelectorWithExtensions =
+            ExtensionsUtil.getCameraSelectorWithSessionProcessor(
+                cameraProvider,
+                CameraSelector.DEFAULT_BACK_CAMERA,
+                sessionProcessor
+            )
+
+        val previewBuilder = Preview.Builder().setPreviewStabilizationEnabled(true)
+        verifyVideoStabilizationModeInResultAndFramesAvailable(
+            cameraSelector = cameraSelectorWithExtensions,
+            previewBuilder = previewBuilder,
+            expectedMode = CaptureResult.CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION
+        )
+    }
+
+    @Test
     @SdkSuppress(minSdkVersion = 21, maxSdkVersion = 32)
     fun setMirrorModeIsNoOp_priorToAPI33() = runBlocking {
         verifyMirrorMode(
@@ -1627,6 +1662,7 @@
     }
 
     private suspend fun verifyVideoStabilizationModeInResultAndFramesAvailable(
+        cameraSelector: CameraSelector,
         previewBuilder: Preview.Builder,
         videoCapture: VideoCapture<Recorder>? = null,
         expectedMode: Int
diff --git a/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt b/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt
index 928b2d4..e284992 100644
--- a/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt
+++ b/camera/integration-tests/viewtestapp/src/androidTest/java/androidx/camera/integration/view/CameraControllerFragmentTest.kt
@@ -157,14 +157,14 @@
         var started = false
         var finalState = TAP_TO_FOCUS_NOT_STARTED
         instrumentation.runOnMainSync {
-            fragment.cameraController.tapToFocusState.observe(fragment) {
+            fragment.cameraController.tapToFocusInfoState.observe(fragment) {
                 // Make sure the LiveData receives STARTED first and then another update.
-                if (it == TAP_TO_FOCUS_STARTED) {
+                if (it.focusState == TAP_TO_FOCUS_STARTED) {
                     started = true
                     return@observe
                 }
                 if (started) {
-                    finalState = it
+                    finalState = it.focusState
                     focused.release()
                 }
             }
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java
index 330aef4..8b79e00 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/CameraControllerFragment.java
@@ -22,6 +22,7 @@
 import android.Manifest;
 import android.content.ContentResolver;
 import android.content.ContentValues;
+import android.graphics.Color;
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.MediaStore;
@@ -33,6 +34,7 @@
 import android.widget.CheckBox;
 import android.widget.CompoundButton;
 import android.widget.FrameLayout;
+import android.widget.ImageView;
 import android.widget.SeekBar;
 import android.widget.TextView;
 import android.widget.Toast;
@@ -56,6 +58,7 @@
 import androidx.camera.view.LifecycleCameraController;
 import androidx.camera.view.PreviewView;
 import androidx.camera.view.RotationProvider;
+import androidx.camera.view.TapToFocusInfo;
 import androidx.camera.view.video.AudioConfig;
 import androidx.core.util.Consumer;
 import androidx.fragment.app.Fragment;
@@ -70,7 +73,6 @@
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Locale;
-import java.util.Objects;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -101,6 +103,7 @@
     private TextView mTorchStateText;
     private TextView mLuminance;
     private CheckBox mOnDisk;
+    private ImageView mFocusOnTapCircle;
     private boolean mIsAnalyzerSet = true;
     // Listen to accelerometer rotation change and pass it to tests.
     private RotationProvider mRotationProvider;
@@ -327,12 +330,10 @@
         mCameraController.getZoomState().observe(getViewLifecycleOwner(),
                 this::updateZoomStateText);
 
+        mFocusOnTapCircle = view.findViewById(R.id.focus_on_tap_circle);
         mFocusResultText = view.findViewById(R.id.focus_result_text);
-        LiveData<Integer> focusMeteringResult =
-                mCameraController.getTapToFocusState();
-        updateFocusStateText(Objects.requireNonNull(focusMeteringResult.getValue()));
-        focusMeteringResult.observe(getViewLifecycleOwner(),
-                this::updateFocusStateText);
+        LiveData<TapToFocusInfo> focusOnTapState = mCameraController.getTapToFocusInfoState();
+        focusOnTapState.observe(getViewLifecycleOwner(), this::applyFocusOnTap);
 
         mTorchStateText = view.findViewById(R.id.torch_state_text);
         updateTorchStateText(mCameraController.getTorchState().getValue());
@@ -389,6 +390,41 @@
         }
     }
 
+    private void applyFocusOnTap(@NonNull TapToFocusInfo tapToFocusInfo) {
+        if (mFocusOnTapCircle == null) {
+            return;
+        }
+
+        switch (tapToFocusInfo.getFocusState()) {
+            case CameraController.TAP_TO_FOCUS_NOT_STARTED:
+            case CameraController.TAP_TO_FOCUS_NOT_FOCUSED:
+            case CameraController.TAP_TO_FOCUS_FAILED:
+                mFocusOnTapCircle.setVisibility(View.INVISIBLE);
+                break;
+            case CameraController.TAP_TO_FOCUS_STARTED:
+                mFocusOnTapCircle.setVisibility(View.VISIBLE);
+                mFocusOnTapCircle.setColorFilter(Color.GRAY);
+                updateFocusOnTapCirclePosition(tapToFocusInfo);
+                break;
+            case CameraController.TAP_TO_FOCUS_FOCUSED:
+                mFocusOnTapCircle.setVisibility(View.VISIBLE);
+                mFocusOnTapCircle.setColorFilter(Color.WHITE);
+                updateFocusOnTapCirclePosition(tapToFocusInfo);
+                break;
+        }
+
+        updateFocusStateText(tapToFocusInfo.getFocusState());
+    }
+
+    private void updateFocusOnTapCirclePosition(@NonNull TapToFocusInfo tapToFocusInfo) {
+        if (tapToFocusInfo.getTapPoint() != null) {
+            mFocusOnTapCircle.setX(
+                    tapToFocusInfo.getTapPoint().x - (float) mFocusOnTapCircle.getWidth() / 2);
+            mFocusOnTapCircle.setY(
+                    tapToFocusInfo.getTapPoint().y - (float) mFocusOnTapCircle.getHeight() / 2);
+        }
+    }
+
     private void updateFocusStateText(@NonNull Integer tapToFocusState) {
         SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
         String text = "";
diff --git a/camera/integration-tests/viewtestapp/src/main/res/drawable/outline_circle_24.xml b/camera/integration-tests/viewtestapp/src/main/res/drawable/outline_circle_24.xml
new file mode 100644
index 0000000..fef44ee
--- /dev/null
+++ b/camera/integration-tests/viewtestapp/src/main/res/drawable/outline_circle_24.xml
@@ -0,0 +1,5 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="48dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="48dp">
+
+    <path android:fillColor="@android:color/white" android:pathData="M12,2C6.47,2 2,6.47 2,12c0,5.53 4.47,10 10,10s10,-4.47 10,-10C22,6.47 17.53,2 12,2zM12,20c-4.42,0 -8,-3.58 -8,-8c0,-4.42 3.58,-8 8,-8s8,3.58 8,8C20,16.42 16.42,20 12,20z"/>
+
+</vector>
diff --git a/camera/integration-tests/viewtestapp/src/main/res/layout/camera_controller_view.xml b/camera/integration-tests/viewtestapp/src/main/res/layout/camera_controller_view.xml
index 648cf04..9b307a5 100644
--- a/camera/integration-tests/viewtestapp/src/main/res/layout/camera_controller_view.xml
+++ b/camera/integration-tests/viewtestapp/src/main/res/layout/camera_controller_view.xml
@@ -167,4 +167,9 @@
         android:id="@+id/torch_state_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"/>
+    <ImageView
+        android:id="@+id/focus_on_tap_circle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:src="@drawable/outline_circle_24" />
 </LinearLayout>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-ar/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-ar/strings.xml
index f6fb1cc..2f9eab2 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-ar/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-ar/strings.xml
@@ -165,7 +165,7 @@
     <string name="gas_station" msgid="1203313937444666161">"محطة وقود"</string>
     <string name="short_route" msgid="4831864276538141265">"مسار طريق قصير"</string>
     <string name="less_busy" msgid="310625272281710983">"أقل انشغالاً"</string>
-    <string name="hov_friendly" msgid="6956152104754594971">"المركبات الملائمة التي تشغل حيزًا كبيرًا"</string>
+    <string name="hov_friendly" msgid="6956152104754594971">"المركبات الملائمة العالية الإشغال"</string>
     <string name="long_route" msgid="4737969235741057506">"مسار الرحلة طويل"</string>
     <string name="continue_start_nav" msgid="6231797535084469163">"المتابعة لبدء التنقّل"</string>
     <string name="continue_route" msgid="5172258139245088080">"المتابعة إلى مسار الرحلة"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-eu/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-eu/strings.xml
index 07c63dc..d4cf4f3 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-eu/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-eu/strings.xml
@@ -222,7 +222,7 @@
     <string name="clicked_row_prefix" msgid="9068303427922069941">"Errenkada sakatuta dago"</string>
     <string name="first_line_text" msgid="6648055806656590336">"Lehen testu-errenkada"</string>
     <string name="second_line_text" msgid="38664490158836864">"Bigarren testu-errenkada"</string>
-    <string name="long_line_text" msgid="8082962600953333087">"Azpitestua osorik bistara daiteke murriztapenik gabeko moduan (adibidez, aparkatzeko modua edo abiadura txikiko modu mugatua). Alabaina, modu mugatuan egon bitartean (adibidez, gidatzeko modua), bi lerrotara soilik moztuko da. Probatzeko: azpitestu hau oso oso oso oso oso oso oso oso oso luzea da."</string>
+    <string name="long_line_text" msgid="8082962600953333087">"Azpitestua osorik bistara daiteke murriztapenik gabeko moduan (adibidez, aparkatzeko modua edo abiadura txikiko modu murriztua). Alabaina, modu murriztuan egon bitartean (adibidez, gidatzeko modua), bi lerrotara soilik moztuko da. Probatzeko: azpitestu hau oso oso oso oso oso oso oso oso oso luzea da."</string>
     <string name="title_prefix" msgid="3991742709199357049">"Izena"</string>
     <string name="list_template_demo_title" msgid="1740208242737246151">"Zerrenden txantiloien demo-bertsioa"</string>
     <string name="long_msg_template_demo_title" msgid="1793748562161438131">"Mezu luzeen txantiloien demo-bertsioa"</string>
diff --git a/compose/animation/animation-core/bcv/native/1.7.0.txt b/compose/animation/animation-core/bcv/native/1.7.0.txt
new file mode 100644
index 0000000..41358e6
--- /dev/null
+++ b/compose/animation/animation-core/bcv/native/1.7.0.txt
@@ -0,0 +1,803 @@
+// Klib ABI Dump
+// Targets: [linuxX64.linuxx64Stubs]
+// Rendering settings:
+// - Signature version: 2
+// - Show manifest properties: true
+// - Show declarations: true
+
+// Library unique name: <androidx.compose.animation:animation-core>
+abstract fun interface androidx.compose.animation.core/Easing { // androidx.compose.animation.core/Easing|null[0]
+    abstract fun transform(kotlin/Float): kotlin/Float // androidx.compose.animation.core/Easing.transform|transform(kotlin.Float){}[0]
+}
+abstract interface <#A: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/VectorizedAnimationSpec { // androidx.compose.animation.core/VectorizedAnimationSpec|null[0]
+    abstract fun getDurationNanos(#A, #A, #A): kotlin/Long // androidx.compose.animation.core/VectorizedAnimationSpec.getDurationNanos|getDurationNanos(1:0;1:0;1:0){}[0]
+    abstract fun getValueFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedAnimationSpec.getValueFromNanos|getValueFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    abstract fun getVelocityFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedAnimationSpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    abstract val isInfinite // androidx.compose.animation.core/VectorizedAnimationSpec.isInfinite|{}isInfinite[0]
+        abstract fun <get-isInfinite>(): kotlin/Boolean // androidx.compose.animation.core/VectorizedAnimationSpec.isInfinite.<get-isInfinite>|<get-isInfinite>(){}[0]
+    open fun getEndVelocity(#A, #A, #A): #A // androidx.compose.animation.core/VectorizedAnimationSpec.getEndVelocity|getEndVelocity(1:0;1:0;1:0){}[0]
+}
+abstract interface <#A: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/VectorizedDecayAnimationSpec { // androidx.compose.animation.core/VectorizedDecayAnimationSpec|null[0]
+    abstract fun getDurationNanos(#A, #A): kotlin/Long // androidx.compose.animation.core/VectorizedDecayAnimationSpec.getDurationNanos|getDurationNanos(1:0;1:0){}[0]
+    abstract fun getTargetValue(#A, #A): #A // androidx.compose.animation.core/VectorizedDecayAnimationSpec.getTargetValue|getTargetValue(1:0;1:0){}[0]
+    abstract fun getValueFromNanos(kotlin/Long, #A, #A): #A // androidx.compose.animation.core/VectorizedDecayAnimationSpec.getValueFromNanos|getValueFromNanos(kotlin.Long;1:0;1:0){}[0]
+    abstract fun getVelocityFromNanos(kotlin/Long, #A, #A): #A // androidx.compose.animation.core/VectorizedDecayAnimationSpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;1:0;1:0){}[0]
+    abstract val absVelocityThreshold // androidx.compose.animation.core/VectorizedDecayAnimationSpec.absVelocityThreshold|{}absVelocityThreshold[0]
+        abstract fun <get-absVelocityThreshold>(): kotlin/Float // androidx.compose.animation.core/VectorizedDecayAnimationSpec.absVelocityThreshold.<get-absVelocityThreshold>|<get-absVelocityThreshold>(){}[0]
+}
+abstract interface <#A: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec : androidx.compose.animation.core/VectorizedFiniteAnimationSpec<#A> { // androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec|null[0]
+    abstract val delayMillis // androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec.delayMillis|{}delayMillis[0]
+        abstract fun <get-delayMillis>(): kotlin/Int // androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec.delayMillis.<get-delayMillis>|<get-delayMillis>(){}[0]
+    abstract val durationMillis // androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec.durationMillis|{}durationMillis[0]
+        abstract fun <get-durationMillis>(): kotlin/Int // androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec.durationMillis.<get-durationMillis>|<get-durationMillis>(){}[0]
+    open fun getDurationNanos(#A, #A, #A): kotlin/Long // androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec.getDurationNanos|getDurationNanos(1:0;1:0;1:0){}[0]
+}
+abstract interface <#A: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/VectorizedFiniteAnimationSpec : androidx.compose.animation.core/VectorizedAnimationSpec<#A> { // androidx.compose.animation.core/VectorizedFiniteAnimationSpec|null[0]
+    open val isInfinite // androidx.compose.animation.core/VectorizedFiniteAnimationSpec.isInfinite|{}isInfinite[0]
+        open fun <get-isInfinite>(): kotlin/Boolean // androidx.compose.animation.core/VectorizedFiniteAnimationSpec.isInfinite.<get-isInfinite>|<get-isInfinite>(){}[0]
+}
+abstract interface <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/Animation { // androidx.compose.animation.core/Animation|null[0]
+    abstract fun getValueFromNanos(kotlin/Long): #A // androidx.compose.animation.core/Animation.getValueFromNanos|getValueFromNanos(kotlin.Long){}[0]
+    abstract fun getVelocityVectorFromNanos(kotlin/Long): #B // androidx.compose.animation.core/Animation.getVelocityVectorFromNanos|getVelocityVectorFromNanos(kotlin.Long){}[0]
+    abstract val durationNanos // androidx.compose.animation.core/Animation.durationNanos|{}durationNanos[0]
+        abstract fun <get-durationNanos>(): kotlin/Long // androidx.compose.animation.core/Animation.durationNanos.<get-durationNanos>|<get-durationNanos>(){}[0]
+    abstract val isInfinite // androidx.compose.animation.core/Animation.isInfinite|{}isInfinite[0]
+        abstract fun <get-isInfinite>(): kotlin/Boolean // androidx.compose.animation.core/Animation.isInfinite.<get-isInfinite>|<get-isInfinite>(){}[0]
+    abstract val targetValue // androidx.compose.animation.core/Animation.targetValue|{}targetValue[0]
+        abstract fun <get-targetValue>(): #A // androidx.compose.animation.core/Animation.targetValue.<get-targetValue>|<get-targetValue>(){}[0]
+    abstract val typeConverter // androidx.compose.animation.core/Animation.typeConverter|{}typeConverter[0]
+        abstract fun <get-typeConverter>(): androidx.compose.animation.core/TwoWayConverter<#A, #B> // androidx.compose.animation.core/Animation.typeConverter.<get-typeConverter>|<get-typeConverter>(){}[0]
+    open fun isFinishedFromNanos(kotlin/Long): kotlin/Boolean // androidx.compose.animation.core/Animation.isFinishedFromNanos|isFinishedFromNanos(kotlin.Long){}[0]
+}
+abstract interface <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/TwoWayConverter { // androidx.compose.animation.core/TwoWayConverter|null[0]
+    abstract val convertFromVector // androidx.compose.animation.core/TwoWayConverter.convertFromVector|{}convertFromVector[0]
+        abstract fun <get-convertFromVector>(): kotlin/Function1<#B, #A> // androidx.compose.animation.core/TwoWayConverter.convertFromVector.<get-convertFromVector>|<get-convertFromVector>(){}[0]
+    abstract val convertToVector // androidx.compose.animation.core/TwoWayConverter.convertToVector|{}convertToVector[0]
+        abstract fun <get-convertToVector>(): kotlin/Function1<#A, #B> // androidx.compose.animation.core/TwoWayConverter.convertToVector.<get-convertToVector>|<get-convertToVector>(){}[0]
+}
+abstract interface <#A: kotlin/Any?> androidx.compose.animation.core/AnimationSpec { // androidx.compose.animation.core/AnimationSpec|null[0]
+    abstract fun <#A1: androidx.compose.animation.core/AnimationVector> vectorize(androidx.compose.animation.core/TwoWayConverter<#A, #A1>): androidx.compose.animation.core/VectorizedAnimationSpec<#A1> // androidx.compose.animation.core/AnimationSpec.vectorize|vectorize(androidx.compose.animation.core.TwoWayConverter<1:0,0:0>){0§<androidx.compose.animation.core.AnimationVector>}[0]
+}
+abstract interface <#A: kotlin/Any?> androidx.compose.animation.core/DecayAnimationSpec { // androidx.compose.animation.core/DecayAnimationSpec|null[0]
+    abstract fun <#A1: androidx.compose.animation.core/AnimationVector> vectorize(androidx.compose.animation.core/TwoWayConverter<#A, #A1>): androidx.compose.animation.core/VectorizedDecayAnimationSpec<#A1> // androidx.compose.animation.core/DecayAnimationSpec.vectorize|vectorize(androidx.compose.animation.core.TwoWayConverter<1:0,0:0>){0§<androidx.compose.animation.core.AnimationVector>}[0]
+}
+abstract interface <#A: kotlin/Any?> androidx.compose.animation.core/DurationBasedAnimationSpec : androidx.compose.animation.core/FiniteAnimationSpec<#A> { // androidx.compose.animation.core/DurationBasedAnimationSpec|null[0]
+    abstract fun <#A1: androidx.compose.animation.core/AnimationVector> vectorize(androidx.compose.animation.core/TwoWayConverter<#A, #A1>): androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec<#A1> // androidx.compose.animation.core/DurationBasedAnimationSpec.vectorize|vectorize(androidx.compose.animation.core.TwoWayConverter<1:0,0:0>){0§<androidx.compose.animation.core.AnimationVector>}[0]
+}
+abstract interface <#A: kotlin/Any?> androidx.compose.animation.core/FiniteAnimationSpec : androidx.compose.animation.core/AnimationSpec<#A> { // androidx.compose.animation.core/FiniteAnimationSpec|null[0]
+    abstract fun <#A1: androidx.compose.animation.core/AnimationVector> vectorize(androidx.compose.animation.core/TwoWayConverter<#A, #A1>): androidx.compose.animation.core/VectorizedFiniteAnimationSpec<#A1> // androidx.compose.animation.core/FiniteAnimationSpec.vectorize|vectorize(androidx.compose.animation.core.TwoWayConverter<1:0,0:0>){0§<androidx.compose.animation.core.AnimationVector>}[0]
+}
+abstract interface androidx.compose.animation.core/FloatAnimationSpec : androidx.compose.animation.core/AnimationSpec<kotlin/Float> { // androidx.compose.animation.core/FloatAnimationSpec|null[0]
+    abstract fun getDurationNanos(kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Long // androidx.compose.animation.core/FloatAnimationSpec.getDurationNanos|getDurationNanos(kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    abstract fun getValueFromNanos(kotlin/Long, kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatAnimationSpec.getValueFromNanos|getValueFromNanos(kotlin.Long;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    abstract fun getVelocityFromNanos(kotlin/Long, kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatAnimationSpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    open fun <#A1: androidx.compose.animation.core/AnimationVector> vectorize(androidx.compose.animation.core/TwoWayConverter<kotlin/Float, #A1>): androidx.compose.animation.core/VectorizedFloatAnimationSpec<#A1> // androidx.compose.animation.core/FloatAnimationSpec.vectorize|vectorize(androidx.compose.animation.core.TwoWayConverter<kotlin.Float,0:0>){0§<androidx.compose.animation.core.AnimationVector>}[0]
+    open fun getEndVelocity(kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatAnimationSpec.getEndVelocity|getEndVelocity(kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+}
+abstract interface androidx.compose.animation.core/FloatDecayAnimationSpec { // androidx.compose.animation.core/FloatDecayAnimationSpec|null[0]
+    abstract fun getDurationNanos(kotlin/Float, kotlin/Float): kotlin/Long // androidx.compose.animation.core/FloatDecayAnimationSpec.getDurationNanos|getDurationNanos(kotlin.Float;kotlin.Float){}[0]
+    abstract fun getTargetValue(kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatDecayAnimationSpec.getTargetValue|getTargetValue(kotlin.Float;kotlin.Float){}[0]
+    abstract fun getValueFromNanos(kotlin/Long, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatDecayAnimationSpec.getValueFromNanos|getValueFromNanos(kotlin.Long;kotlin.Float;kotlin.Float){}[0]
+    abstract fun getVelocityFromNanos(kotlin/Long, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatDecayAnimationSpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;kotlin.Float;kotlin.Float){}[0]
+    abstract val absVelocityThreshold // androidx.compose.animation.core/FloatDecayAnimationSpec.absVelocityThreshold|{}absVelocityThreshold[0]
+        abstract fun <get-absVelocityThreshold>(): kotlin/Float // androidx.compose.animation.core/FloatDecayAnimationSpec.absVelocityThreshold.<get-absVelocityThreshold>|<get-absVelocityThreshold>(){}[0]
+}
+final class <#A: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/VectorizedFloatAnimationSpec : androidx.compose.animation.core/VectorizedFiniteAnimationSpec<#A> { // androidx.compose.animation.core/VectorizedFloatAnimationSpec|null[0]
+    constructor <init>(androidx.compose.animation.core/FloatAnimationSpec) // androidx.compose.animation.core/VectorizedFloatAnimationSpec.<init>|<init>(androidx.compose.animation.core.FloatAnimationSpec){}[0]
+    final fun getDurationNanos(#A, #A, #A): kotlin/Long // androidx.compose.animation.core/VectorizedFloatAnimationSpec.getDurationNanos|getDurationNanos(1:0;1:0;1:0){}[0]
+    final fun getEndVelocity(#A, #A, #A): #A // androidx.compose.animation.core/VectorizedFloatAnimationSpec.getEndVelocity|getEndVelocity(1:0;1:0;1:0){}[0]
+    final fun getValueFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedFloatAnimationSpec.getValueFromNanos|getValueFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    final fun getVelocityFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedFloatAnimationSpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+}
+final class <#A: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/VectorizedInfiniteRepeatableSpec : androidx.compose.animation.core/VectorizedAnimationSpec<#A> { // androidx.compose.animation.core/VectorizedInfiniteRepeatableSpec|null[0]
+    constructor <init>(androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec<#A>, androidx.compose.animation.core/RepeatMode =...) // androidx.compose.animation.core/VectorizedInfiniteRepeatableSpec.<init>|<init>(androidx.compose.animation.core.VectorizedDurationBasedAnimationSpec<1:0>;androidx.compose.animation.core.RepeatMode){}[0]
+    constructor <init>(androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec<#A>, androidx.compose.animation.core/RepeatMode =..., androidx.compose.animation.core/StartOffset =...) // androidx.compose.animation.core/VectorizedInfiniteRepeatableSpec.<init>|<init>(androidx.compose.animation.core.VectorizedDurationBasedAnimationSpec<1:0>;androidx.compose.animation.core.RepeatMode;androidx.compose.animation.core.StartOffset){}[0]
+    final fun getDurationNanos(#A, #A, #A): kotlin/Long // androidx.compose.animation.core/VectorizedInfiniteRepeatableSpec.getDurationNanos|getDurationNanos(1:0;1:0;1:0){}[0]
+    final fun getValueFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedInfiniteRepeatableSpec.getValueFromNanos|getValueFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    final fun getVelocityFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedInfiniteRepeatableSpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    final val isInfinite // androidx.compose.animation.core/VectorizedInfiniteRepeatableSpec.isInfinite|{}isInfinite[0]
+        final fun <get-isInfinite>(): kotlin/Boolean // androidx.compose.animation.core/VectorizedInfiniteRepeatableSpec.isInfinite.<get-isInfinite>|<get-isInfinite>(){}[0]
+}
+final class <#A: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/VectorizedKeyframesSpec : androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec<#A> { // androidx.compose.animation.core/VectorizedKeyframesSpec|null[0]
+    constructor <init>(kotlin.collections/Map<kotlin/Int, kotlin/Pair<#A, androidx.compose.animation.core/Easing>>, kotlin/Int, kotlin/Int =...) // androidx.compose.animation.core/VectorizedKeyframesSpec.<init>|<init>(kotlin.collections.Map<kotlin.Int,kotlin.Pair<1:0,androidx.compose.animation.core.Easing>>;kotlin.Int;kotlin.Int){}[0]
+    final fun getValueFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedKeyframesSpec.getValueFromNanos|getValueFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    final fun getVelocityFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedKeyframesSpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    final val delayMillis // androidx.compose.animation.core/VectorizedKeyframesSpec.delayMillis|{}delayMillis[0]
+        final fun <get-delayMillis>(): kotlin/Int // androidx.compose.animation.core/VectorizedKeyframesSpec.delayMillis.<get-delayMillis>|<get-delayMillis>(){}[0]
+    final val durationMillis // androidx.compose.animation.core/VectorizedKeyframesSpec.durationMillis|{}durationMillis[0]
+        final fun <get-durationMillis>(): kotlin/Int // androidx.compose.animation.core/VectorizedKeyframesSpec.durationMillis.<get-durationMillis>|<get-durationMillis>(){}[0]
+}
+final class <#A: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/VectorizedRepeatableSpec : androidx.compose.animation.core/VectorizedFiniteAnimationSpec<#A> { // androidx.compose.animation.core/VectorizedRepeatableSpec|null[0]
+    constructor <init>(kotlin/Int, androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec<#A>, androidx.compose.animation.core/RepeatMode =...) // androidx.compose.animation.core/VectorizedRepeatableSpec.<init>|<init>(kotlin.Int;androidx.compose.animation.core.VectorizedDurationBasedAnimationSpec<1:0>;androidx.compose.animation.core.RepeatMode){}[0]
+    constructor <init>(kotlin/Int, androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec<#A>, androidx.compose.animation.core/RepeatMode =..., androidx.compose.animation.core/StartOffset =...) // androidx.compose.animation.core/VectorizedRepeatableSpec.<init>|<init>(kotlin.Int;androidx.compose.animation.core.VectorizedDurationBasedAnimationSpec<1:0>;androidx.compose.animation.core.RepeatMode;androidx.compose.animation.core.StartOffset){}[0]
+    final fun getDurationNanos(#A, #A, #A): kotlin/Long // androidx.compose.animation.core/VectorizedRepeatableSpec.getDurationNanos|getDurationNanos(1:0;1:0;1:0){}[0]
+    final fun getValueFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedRepeatableSpec.getValueFromNanos|getValueFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    final fun getVelocityFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedRepeatableSpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+}
+final class <#A: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/VectorizedSnapSpec : androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec<#A> { // androidx.compose.animation.core/VectorizedSnapSpec|null[0]
+    constructor <init>(kotlin/Int =...) // androidx.compose.animation.core/VectorizedSnapSpec.<init>|<init>(kotlin.Int){}[0]
+    final fun getValueFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedSnapSpec.getValueFromNanos|getValueFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    final fun getVelocityFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedSnapSpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    final val delayMillis // androidx.compose.animation.core/VectorizedSnapSpec.delayMillis|{}delayMillis[0]
+        final fun <get-delayMillis>(): kotlin/Int // androidx.compose.animation.core/VectorizedSnapSpec.delayMillis.<get-delayMillis>|<get-delayMillis>(){}[0]
+    final val durationMillis // androidx.compose.animation.core/VectorizedSnapSpec.durationMillis|{}durationMillis[0]
+        final fun <get-durationMillis>(): kotlin/Int // androidx.compose.animation.core/VectorizedSnapSpec.durationMillis.<get-durationMillis>|<get-durationMillis>(){}[0]
+}
+final class <#A: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/VectorizedSpringSpec : androidx.compose.animation.core/VectorizedFiniteAnimationSpec<#A> { // androidx.compose.animation.core/VectorizedSpringSpec|null[0]
+    constructor <init>(kotlin/Float =..., kotlin/Float =..., #A? =...) // androidx.compose.animation.core/VectorizedSpringSpec.<init>|<init>(kotlin.Float;kotlin.Float;1:0?){}[0]
+    final fun getDurationNanos(#A, #A, #A): kotlin/Long // androidx.compose.animation.core/VectorizedSpringSpec.getDurationNanos|getDurationNanos(1:0;1:0;1:0){}[0]
+    final fun getEndVelocity(#A, #A, #A): #A // androidx.compose.animation.core/VectorizedSpringSpec.getEndVelocity|getEndVelocity(1:0;1:0;1:0){}[0]
+    final fun getValueFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedSpringSpec.getValueFromNanos|getValueFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    final fun getVelocityFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedSpringSpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    final val dampingRatio // androidx.compose.animation.core/VectorizedSpringSpec.dampingRatio|{}dampingRatio[0]
+        final fun <get-dampingRatio>(): kotlin/Float // androidx.compose.animation.core/VectorizedSpringSpec.dampingRatio.<get-dampingRatio>|<get-dampingRatio>(){}[0]
+    final val isInfinite // androidx.compose.animation.core/VectorizedSpringSpec.isInfinite|{}isInfinite[0]
+        final fun <get-isInfinite>(): kotlin/Boolean // androidx.compose.animation.core/VectorizedSpringSpec.isInfinite.<get-isInfinite>|<get-isInfinite>(){}[0]
+    final val stiffness // androidx.compose.animation.core/VectorizedSpringSpec.stiffness|{}stiffness[0]
+        final fun <get-stiffness>(): kotlin/Float // androidx.compose.animation.core/VectorizedSpringSpec.stiffness.<get-stiffness>|<get-stiffness>(){}[0]
+}
+final class <#A: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/VectorizedTweenSpec : androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec<#A> { // androidx.compose.animation.core/VectorizedTweenSpec|null[0]
+    constructor <init>(kotlin/Int =..., kotlin/Int =..., androidx.compose.animation.core/Easing =...) // androidx.compose.animation.core/VectorizedTweenSpec.<init>|<init>(kotlin.Int;kotlin.Int;androidx.compose.animation.core.Easing){}[0]
+    final fun getValueFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedTweenSpec.getValueFromNanos|getValueFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    final fun getVelocityFromNanos(kotlin/Long, #A, #A, #A): #A // androidx.compose.animation.core/VectorizedTweenSpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;1:0;1:0;1:0){}[0]
+    final val delayMillis // androidx.compose.animation.core/VectorizedTweenSpec.delayMillis|{}delayMillis[0]
+        final fun <get-delayMillis>(): kotlin/Int // androidx.compose.animation.core/VectorizedTweenSpec.delayMillis.<get-delayMillis>|<get-delayMillis>(){}[0]
+    final val durationMillis // androidx.compose.animation.core/VectorizedTweenSpec.durationMillis|{}durationMillis[0]
+        final fun <get-durationMillis>(): kotlin/Int // androidx.compose.animation.core/VectorizedTweenSpec.durationMillis.<get-durationMillis>|<get-durationMillis>(){}[0]
+    final val easing // androidx.compose.animation.core/VectorizedTweenSpec.easing|{}easing[0]
+        final fun <get-easing>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/VectorizedTweenSpec.easing.<get-easing>|<get-easing>(){}[0]
+}
+final class <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/Animatable { // androidx.compose.animation.core/Animatable|null[0]
+    constructor <init>(#A, androidx.compose.animation.core/TwoWayConverter<#A, #B>, #A? =...) // androidx.compose.animation.core/Animatable.<init>|<init>(1:0;androidx.compose.animation.core.TwoWayConverter<1:0,1:1>;1:0?){}[0]
+    constructor <init>(#A, androidx.compose.animation.core/TwoWayConverter<#A, #B>, #A? =..., kotlin/String =...) // androidx.compose.animation.core/Animatable.<init>|<init>(1:0;androidx.compose.animation.core.TwoWayConverter<1:0,1:1>;1:0?;kotlin.String){}[0]
+    final fun asState(): androidx.compose.runtime/State<#A> // androidx.compose.animation.core/Animatable.asState|asState(){}[0]
+    final fun updateBounds(#A? =..., #A? =...) // androidx.compose.animation.core/Animatable.updateBounds|updateBounds(1:0?;1:0?){}[0]
+    final suspend fun animateDecay(#A, androidx.compose.animation.core/DecayAnimationSpec<#A>, kotlin/Function1<androidx.compose.animation.core/Animatable<#A, #B>, kotlin/Unit>? =...): androidx.compose.animation.core/AnimationResult<#A, #B> // androidx.compose.animation.core/Animatable.animateDecay|animateDecay(1:0;androidx.compose.animation.core.DecayAnimationSpec<1:0>;kotlin.Function1<androidx.compose.animation.core.Animatable<1:0,1:1>,kotlin.Unit>?){}[0]
+    final suspend fun animateTo(#A, androidx.compose.animation.core/AnimationSpec<#A> =..., #A =..., kotlin/Function1<androidx.compose.animation.core/Animatable<#A, #B>, kotlin/Unit>? =...): androidx.compose.animation.core/AnimationResult<#A, #B> // androidx.compose.animation.core/Animatable.animateTo|animateTo(1:0;androidx.compose.animation.core.AnimationSpec<1:0>;1:0;kotlin.Function1<androidx.compose.animation.core.Animatable<1:0,1:1>,kotlin.Unit>?){}[0]
+    final suspend fun snapTo(#A) // androidx.compose.animation.core/Animatable.snapTo|snapTo(1:0){}[0]
+    final suspend fun stop() // androidx.compose.animation.core/Animatable.stop|stop(){}[0]
+    final val label // androidx.compose.animation.core/Animatable.label|{}label[0]
+        final fun <get-label>(): kotlin/String // androidx.compose.animation.core/Animatable.label.<get-label>|<get-label>(){}[0]
+    final val typeConverter // androidx.compose.animation.core/Animatable.typeConverter|{}typeConverter[0]
+        final fun <get-typeConverter>(): androidx.compose.animation.core/TwoWayConverter<#A, #B> // androidx.compose.animation.core/Animatable.typeConverter.<get-typeConverter>|<get-typeConverter>(){}[0]
+    final val value // androidx.compose.animation.core/Animatable.value|{}value[0]
+        final fun <get-value>(): #A // androidx.compose.animation.core/Animatable.value.<get-value>|<get-value>(){}[0]
+    final val velocity // androidx.compose.animation.core/Animatable.velocity|{}velocity[0]
+        final fun <get-velocity>(): #A // androidx.compose.animation.core/Animatable.velocity.<get-velocity>|<get-velocity>(){}[0]
+    final val velocityVector // androidx.compose.animation.core/Animatable.velocityVector|{}velocityVector[0]
+        final fun <get-velocityVector>(): #B // androidx.compose.animation.core/Animatable.velocityVector.<get-velocityVector>|<get-velocityVector>(){}[0]
+    final var isRunning // androidx.compose.animation.core/Animatable.isRunning|{}isRunning[0]
+        final fun <get-isRunning>(): kotlin/Boolean // androidx.compose.animation.core/Animatable.isRunning.<get-isRunning>|<get-isRunning>(){}[0]
+    final var lowerBound // androidx.compose.animation.core/Animatable.lowerBound|{}lowerBound[0]
+        final fun <get-lowerBound>(): #A? // androidx.compose.animation.core/Animatable.lowerBound.<get-lowerBound>|<get-lowerBound>(){}[0]
+    final var targetValue // androidx.compose.animation.core/Animatable.targetValue|{}targetValue[0]
+        final fun <get-targetValue>(): #A // androidx.compose.animation.core/Animatable.targetValue.<get-targetValue>|<get-targetValue>(){}[0]
+    final var upperBound // androidx.compose.animation.core/Animatable.upperBound|{}upperBound[0]
+        final fun <get-upperBound>(): #A? // androidx.compose.animation.core/Animatable.upperBound.<get-upperBound>|<get-upperBound>(){}[0]
+}
+final class <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/AnimationResult { // androidx.compose.animation.core/AnimationResult|null[0]
+    constructor <init>(androidx.compose.animation.core/AnimationState<#A, #B>, androidx.compose.animation.core/AnimationEndReason) // androidx.compose.animation.core/AnimationResult.<init>|<init>(androidx.compose.animation.core.AnimationState<1:0,1:1>;androidx.compose.animation.core.AnimationEndReason){}[0]
+    final fun toString(): kotlin/String // androidx.compose.animation.core/AnimationResult.toString|toString(){}[0]
+    final val endReason // androidx.compose.animation.core/AnimationResult.endReason|{}endReason[0]
+        final fun <get-endReason>(): androidx.compose.animation.core/AnimationEndReason // androidx.compose.animation.core/AnimationResult.endReason.<get-endReason>|<get-endReason>(){}[0]
+    final val endState // androidx.compose.animation.core/AnimationResult.endState|{}endState[0]
+        final fun <get-endState>(): androidx.compose.animation.core/AnimationState<#A, #B> // androidx.compose.animation.core/AnimationResult.endState.<get-endState>|<get-endState>(){}[0]
+}
+final class <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/AnimationScope { // androidx.compose.animation.core/AnimationScope|null[0]
+    final fun cancelAnimation() // androidx.compose.animation.core/AnimationScope.cancelAnimation|cancelAnimation(){}[0]
+    final fun toAnimationState(): androidx.compose.animation.core/AnimationState<#A, #B> // androidx.compose.animation.core/AnimationScope.toAnimationState|toAnimationState(){}[0]
+    final val startTimeNanos // androidx.compose.animation.core/AnimationScope.startTimeNanos|{}startTimeNanos[0]
+        final fun <get-startTimeNanos>(): kotlin/Long // androidx.compose.animation.core/AnimationScope.startTimeNanos.<get-startTimeNanos>|<get-startTimeNanos>(){}[0]
+    final val targetValue // androidx.compose.animation.core/AnimationScope.targetValue|{}targetValue[0]
+        final fun <get-targetValue>(): #A // androidx.compose.animation.core/AnimationScope.targetValue.<get-targetValue>|<get-targetValue>(){}[0]
+    final val typeConverter // androidx.compose.animation.core/AnimationScope.typeConverter|{}typeConverter[0]
+        final fun <get-typeConverter>(): androidx.compose.animation.core/TwoWayConverter<#A, #B> // androidx.compose.animation.core/AnimationScope.typeConverter.<get-typeConverter>|<get-typeConverter>(){}[0]
+    final val velocity // androidx.compose.animation.core/AnimationScope.velocity|{}velocity[0]
+        final fun <get-velocity>(): #A // androidx.compose.animation.core/AnimationScope.velocity.<get-velocity>|<get-velocity>(){}[0]
+    final var finishedTimeNanos // androidx.compose.animation.core/AnimationScope.finishedTimeNanos|{}finishedTimeNanos[0]
+        final fun <get-finishedTimeNanos>(): kotlin/Long // androidx.compose.animation.core/AnimationScope.finishedTimeNanos.<get-finishedTimeNanos>|<get-finishedTimeNanos>(){}[0]
+    final var isRunning // androidx.compose.animation.core/AnimationScope.isRunning|{}isRunning[0]
+        final fun <get-isRunning>(): kotlin/Boolean // androidx.compose.animation.core/AnimationScope.isRunning.<get-isRunning>|<get-isRunning>(){}[0]
+    final var lastFrameTimeNanos // androidx.compose.animation.core/AnimationScope.lastFrameTimeNanos|{}lastFrameTimeNanos[0]
+        final fun <get-lastFrameTimeNanos>(): kotlin/Long // androidx.compose.animation.core/AnimationScope.lastFrameTimeNanos.<get-lastFrameTimeNanos>|<get-lastFrameTimeNanos>(){}[0]
+    final var value // androidx.compose.animation.core/AnimationScope.value|{}value[0]
+        final fun <get-value>(): #A // androidx.compose.animation.core/AnimationScope.value.<get-value>|<get-value>(){}[0]
+    final var velocityVector // androidx.compose.animation.core/AnimationScope.velocityVector|{}velocityVector[0]
+        final fun <get-velocityVector>(): #B // androidx.compose.animation.core/AnimationScope.velocityVector.<get-velocityVector>|<get-velocityVector>(){}[0]
+}
+final class <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/AnimationState : androidx.compose.runtime/State<#A> { // androidx.compose.animation.core/AnimationState|null[0]
+    constructor <init>(androidx.compose.animation.core/TwoWayConverter<#A, #B>, #A, #B? =..., kotlin/Long =..., kotlin/Long =..., kotlin/Boolean =...) // androidx.compose.animation.core/AnimationState.<init>|<init>(androidx.compose.animation.core.TwoWayConverter<1:0,1:1>;1:0;1:1?;kotlin.Long;kotlin.Long;kotlin.Boolean){}[0]
+    final fun toString(): kotlin/String // androidx.compose.animation.core/AnimationState.toString|toString(){}[0]
+    final val typeConverter // androidx.compose.animation.core/AnimationState.typeConverter|{}typeConverter[0]
+        final fun <get-typeConverter>(): androidx.compose.animation.core/TwoWayConverter<#A, #B> // androidx.compose.animation.core/AnimationState.typeConverter.<get-typeConverter>|<get-typeConverter>(){}[0]
+    final val velocity // androidx.compose.animation.core/AnimationState.velocity|{}velocity[0]
+        final fun <get-velocity>(): #A // androidx.compose.animation.core/AnimationState.velocity.<get-velocity>|<get-velocity>(){}[0]
+    final var finishedTimeNanos // androidx.compose.animation.core/AnimationState.finishedTimeNanos|{}finishedTimeNanos[0]
+        final fun <get-finishedTimeNanos>(): kotlin/Long // androidx.compose.animation.core/AnimationState.finishedTimeNanos.<get-finishedTimeNanos>|<get-finishedTimeNanos>(){}[0]
+    final var isRunning // androidx.compose.animation.core/AnimationState.isRunning|{}isRunning[0]
+        final fun <get-isRunning>(): kotlin/Boolean // androidx.compose.animation.core/AnimationState.isRunning.<get-isRunning>|<get-isRunning>(){}[0]
+    final var lastFrameTimeNanos // androidx.compose.animation.core/AnimationState.lastFrameTimeNanos|{}lastFrameTimeNanos[0]
+        final fun <get-lastFrameTimeNanos>(): kotlin/Long // androidx.compose.animation.core/AnimationState.lastFrameTimeNanos.<get-lastFrameTimeNanos>|<get-lastFrameTimeNanos>(){}[0]
+    final var value // androidx.compose.animation.core/AnimationState.value|{}value[0]
+        final fun <get-value>(): #A // androidx.compose.animation.core/AnimationState.value.<get-value>|<get-value>(){}[0]
+    final var velocityVector // androidx.compose.animation.core/AnimationState.velocityVector|{}velocityVector[0]
+        final fun <get-velocityVector>(): #B // androidx.compose.animation.core/AnimationState.velocityVector.<get-velocityVector>|<get-velocityVector>(){}[0]
+}
+final class <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/DecayAnimation : androidx.compose.animation.core/Animation<#A, #B> { // androidx.compose.animation.core/DecayAnimation|null[0]
+    constructor <init>(androidx.compose.animation.core/DecayAnimationSpec<#A>, androidx.compose.animation.core/TwoWayConverter<#A, #B>, #A, #A) // androidx.compose.animation.core/DecayAnimation.<init>|<init>(androidx.compose.animation.core.DecayAnimationSpec<1:0>;androidx.compose.animation.core.TwoWayConverter<1:0,1:1>;1:0;1:0){}[0]
+    constructor <init>(androidx.compose.animation.core/DecayAnimationSpec<#A>, androidx.compose.animation.core/TwoWayConverter<#A, #B>, #A, #B) // androidx.compose.animation.core/DecayAnimation.<init>|<init>(androidx.compose.animation.core.DecayAnimationSpec<1:0>;androidx.compose.animation.core.TwoWayConverter<1:0,1:1>;1:0;1:1){}[0]
+    constructor <init>(androidx.compose.animation.core/VectorizedDecayAnimationSpec<#B>, androidx.compose.animation.core/TwoWayConverter<#A, #B>, #A, #B) // androidx.compose.animation.core/DecayAnimation.<init>|<init>(androidx.compose.animation.core.VectorizedDecayAnimationSpec<1:1>;androidx.compose.animation.core.TwoWayConverter<1:0,1:1>;1:0;1:1){}[0]
+    final fun getValueFromNanos(kotlin/Long): #A // androidx.compose.animation.core/DecayAnimation.getValueFromNanos|getValueFromNanos(kotlin.Long){}[0]
+    final fun getVelocityVectorFromNanos(kotlin/Long): #B // androidx.compose.animation.core/DecayAnimation.getVelocityVectorFromNanos|getVelocityVectorFromNanos(kotlin.Long){}[0]
+    final val durationNanos // androidx.compose.animation.core/DecayAnimation.durationNanos|{}durationNanos[0]
+        final fun <get-durationNanos>(): kotlin/Long // androidx.compose.animation.core/DecayAnimation.durationNanos.<get-durationNanos>|<get-durationNanos>(){}[0]
+    final val initialValue // androidx.compose.animation.core/DecayAnimation.initialValue|{}initialValue[0]
+        final fun <get-initialValue>(): #A // androidx.compose.animation.core/DecayAnimation.initialValue.<get-initialValue>|<get-initialValue>(){}[0]
+    final val initialVelocityVector // androidx.compose.animation.core/DecayAnimation.initialVelocityVector|{}initialVelocityVector[0]
+        final fun <get-initialVelocityVector>(): #B // androidx.compose.animation.core/DecayAnimation.initialVelocityVector.<get-initialVelocityVector>|<get-initialVelocityVector>(){}[0]
+    final val isInfinite // androidx.compose.animation.core/DecayAnimation.isInfinite|{}isInfinite[0]
+        final fun <get-isInfinite>(): kotlin/Boolean // androidx.compose.animation.core/DecayAnimation.isInfinite.<get-isInfinite>|<get-isInfinite>(){}[0]
+    final val targetValue // androidx.compose.animation.core/DecayAnimation.targetValue|{}targetValue[0]
+        final fun <get-targetValue>(): #A // androidx.compose.animation.core/DecayAnimation.targetValue.<get-targetValue>|<get-targetValue>(){}[0]
+    final val typeConverter // androidx.compose.animation.core/DecayAnimation.typeConverter|{}typeConverter[0]
+        final fun <get-typeConverter>(): androidx.compose.animation.core/TwoWayConverter<#A, #B> // androidx.compose.animation.core/DecayAnimation.typeConverter.<get-typeConverter>|<get-typeConverter>(){}[0]
+}
+final class <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/TargetBasedAnimation : androidx.compose.animation.core/Animation<#A, #B> { // androidx.compose.animation.core/TargetBasedAnimation|null[0]
+    constructor <init>(androidx.compose.animation.core/AnimationSpec<#A>, androidx.compose.animation.core/TwoWayConverter<#A, #B>, #A, #A, #B? =...) // androidx.compose.animation.core/TargetBasedAnimation.<init>|<init>(androidx.compose.animation.core.AnimationSpec<1:0>;androidx.compose.animation.core.TwoWayConverter<1:0,1:1>;1:0;1:0;1:1?){}[0]
+    final fun getValueFromNanos(kotlin/Long): #A // androidx.compose.animation.core/TargetBasedAnimation.getValueFromNanos|getValueFromNanos(kotlin.Long){}[0]
+    final fun getVelocityVectorFromNanos(kotlin/Long): #B // androidx.compose.animation.core/TargetBasedAnimation.getVelocityVectorFromNanos|getVelocityVectorFromNanos(kotlin.Long){}[0]
+    final fun toString(): kotlin/String // androidx.compose.animation.core/TargetBasedAnimation.toString|toString(){}[0]
+    final val durationNanos // androidx.compose.animation.core/TargetBasedAnimation.durationNanos|{}durationNanos[0]
+        final fun <get-durationNanos>(): kotlin/Long // androidx.compose.animation.core/TargetBasedAnimation.durationNanos.<get-durationNanos>|<get-durationNanos>(){}[0]
+    final val initialValue // androidx.compose.animation.core/TargetBasedAnimation.initialValue|{}initialValue[0]
+        final fun <get-initialValue>(): #A // androidx.compose.animation.core/TargetBasedAnimation.initialValue.<get-initialValue>|<get-initialValue>(){}[0]
+    final val isInfinite // androidx.compose.animation.core/TargetBasedAnimation.isInfinite|{}isInfinite[0]
+        final fun <get-isInfinite>(): kotlin/Boolean // androidx.compose.animation.core/TargetBasedAnimation.isInfinite.<get-isInfinite>|<get-isInfinite>(){}[0]
+    final val targetValue // androidx.compose.animation.core/TargetBasedAnimation.targetValue|{}targetValue[0]
+        final fun <get-targetValue>(): #A // androidx.compose.animation.core/TargetBasedAnimation.targetValue.<get-targetValue>|<get-targetValue>(){}[0]
+    final val typeConverter // androidx.compose.animation.core/TargetBasedAnimation.typeConverter|{}typeConverter[0]
+        final fun <get-typeConverter>(): androidx.compose.animation.core/TwoWayConverter<#A, #B> // androidx.compose.animation.core/TargetBasedAnimation.typeConverter.<get-typeConverter>|<get-typeConverter>(){}[0]
+}
+final class <#A: kotlin/Any?> androidx.compose.animation.core/InfiniteRepeatableSpec : androidx.compose.animation.core/AnimationSpec<#A> { // androidx.compose.animation.core/InfiniteRepeatableSpec|null[0]
+    constructor <init>(androidx.compose.animation.core/DurationBasedAnimationSpec<#A>, androidx.compose.animation.core/RepeatMode =...) // androidx.compose.animation.core/InfiniteRepeatableSpec.<init>|<init>(androidx.compose.animation.core.DurationBasedAnimationSpec<1:0>;androidx.compose.animation.core.RepeatMode){}[0]
+    constructor <init>(androidx.compose.animation.core/DurationBasedAnimationSpec<#A>, androidx.compose.animation.core/RepeatMode =..., androidx.compose.animation.core/StartOffset =...) // androidx.compose.animation.core/InfiniteRepeatableSpec.<init>|<init>(androidx.compose.animation.core.DurationBasedAnimationSpec<1:0>;androidx.compose.animation.core.RepeatMode;androidx.compose.animation.core.StartOffset){}[0]
+    final fun <#A1: androidx.compose.animation.core/AnimationVector> vectorize(androidx.compose.animation.core/TwoWayConverter<#A, #A1>): androidx.compose.animation.core/VectorizedAnimationSpec<#A1> // androidx.compose.animation.core/InfiniteRepeatableSpec.vectorize|vectorize(androidx.compose.animation.core.TwoWayConverter<1:0,0:0>){0§<androidx.compose.animation.core.AnimationVector>}[0]
+    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.animation.core/InfiniteRepeatableSpec.equals|equals(kotlin.Any?){}[0]
+    final fun hashCode(): kotlin/Int // androidx.compose.animation.core/InfiniteRepeatableSpec.hashCode|hashCode(){}[0]
+    final val animation // androidx.compose.animation.core/InfiniteRepeatableSpec.animation|{}animation[0]
+        final fun <get-animation>(): androidx.compose.animation.core/DurationBasedAnimationSpec<#A> // androidx.compose.animation.core/InfiniteRepeatableSpec.animation.<get-animation>|<get-animation>(){}[0]
+    final val initialStartOffset // androidx.compose.animation.core/InfiniteRepeatableSpec.initialStartOffset|{}initialStartOffset[0]
+        final fun <get-initialStartOffset>(): androidx.compose.animation.core/StartOffset // androidx.compose.animation.core/InfiniteRepeatableSpec.initialStartOffset.<get-initialStartOffset>|<get-initialStartOffset>(){}[0]
+    final val repeatMode // androidx.compose.animation.core/InfiniteRepeatableSpec.repeatMode|{}repeatMode[0]
+        final fun <get-repeatMode>(): androidx.compose.animation.core/RepeatMode // androidx.compose.animation.core/InfiniteRepeatableSpec.repeatMode.<get-repeatMode>|<get-repeatMode>(){}[0]
+}
+final class <#A: kotlin/Any?> androidx.compose.animation.core/KeyframesSpec : androidx.compose.animation.core/DurationBasedAnimationSpec<#A> { // androidx.compose.animation.core/KeyframesSpec|null[0]
+    constructor <init>(androidx.compose.animation.core/KeyframesSpec.KeyframesSpecConfig<#A>) // androidx.compose.animation.core/KeyframesSpec.<init>|<init>(androidx.compose.animation.core.KeyframesSpec.KeyframesSpecConfig<1:0>){}[0]
+    final class <#A1: kotlin/Any?> KeyframeEntity : androidx.compose.animation.core/KeyframeBaseEntity<#A1> { // androidx.compose.animation.core/KeyframesSpec.KeyframeEntity|null[0]
+        final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.animation.core/KeyframesSpec.KeyframeEntity.equals|equals(kotlin.Any?){}[0]
+        final fun hashCode(): kotlin/Int // androidx.compose.animation.core/KeyframesSpec.KeyframeEntity.hashCode|hashCode(){}[0]
+    }
+    final class <#A1: kotlin/Any?> KeyframesSpecConfig : androidx.compose.animation.core/KeyframesSpecBaseConfig<#A1, androidx.compose.animation.core/KeyframesSpec.KeyframeEntity<#A1>> { // androidx.compose.animation.core/KeyframesSpec.KeyframesSpecConfig|null[0]
+        constructor <init>() // androidx.compose.animation.core/KeyframesSpec.KeyframesSpecConfig.<init>|<init>(){}[0]
+        final fun (#A1).at(kotlin/Int): androidx.compose.animation.core/KeyframesSpec.KeyframeEntity<#A1> // androidx.compose.animation.core/KeyframesSpec.KeyframesSpecConfig.at|at@1:0(kotlin.Int){}[0]
+        final fun (#A1).atFraction(kotlin/Float): androidx.compose.animation.core/KeyframesSpec.KeyframeEntity<#A1> // androidx.compose.animation.core/KeyframesSpec.KeyframesSpecConfig.atFraction|atFraction@1:0(kotlin.Float){}[0]
+        final fun (androidx.compose.animation.core/KeyframesSpec.KeyframeEntity<#A1>).with(androidx.compose.animation.core/Easing) // androidx.compose.animation.core/KeyframesSpec.KeyframesSpecConfig.with|with@androidx.compose.animation.core.KeyframesSpec.KeyframeEntity<1:0>(androidx.compose.animation.core.Easing){}[0]
+    }
+    final fun <#A1: androidx.compose.animation.core/AnimationVector> vectorize(androidx.compose.animation.core/TwoWayConverter<#A, #A1>): androidx.compose.animation.core/VectorizedKeyframesSpec<#A1> // androidx.compose.animation.core/KeyframesSpec.vectorize|vectorize(androidx.compose.animation.core.TwoWayConverter<1:0,0:0>){0§<androidx.compose.animation.core.AnimationVector>}[0]
+    final val config // androidx.compose.animation.core/KeyframesSpec.config|{}config[0]
+        final fun <get-config>(): androidx.compose.animation.core/KeyframesSpec.KeyframesSpecConfig<#A> // androidx.compose.animation.core/KeyframesSpec.config.<get-config>|<get-config>(){}[0]
+}
+final class <#A: kotlin/Any?> androidx.compose.animation.core/MutableTransitionState : androidx.compose.animation.core/TransitionState<#A> { // androidx.compose.animation.core/MutableTransitionState|null[0]
+    constructor <init>(#A) // androidx.compose.animation.core/MutableTransitionState.<init>|<init>(1:0){}[0]
+    final val isIdle // androidx.compose.animation.core/MutableTransitionState.isIdle|{}isIdle[0]
+        final fun <get-isIdle>(): kotlin/Boolean // androidx.compose.animation.core/MutableTransitionState.isIdle.<get-isIdle>|<get-isIdle>(){}[0]
+    final var currentState // androidx.compose.animation.core/MutableTransitionState.currentState|{}currentState[0]
+        final fun <get-currentState>(): #A // androidx.compose.animation.core/MutableTransitionState.currentState.<get-currentState>|<get-currentState>(){}[0]
+    final var targetState // androidx.compose.animation.core/MutableTransitionState.targetState|{}targetState[0]
+        final fun <get-targetState>(): #A // androidx.compose.animation.core/MutableTransitionState.targetState.<get-targetState>|<get-targetState>(){}[0]
+        final fun <set-targetState>(#A) // androidx.compose.animation.core/MutableTransitionState.targetState.<set-targetState>|<set-targetState>(1:0){}[0]
+}
+final class <#A: kotlin/Any?> androidx.compose.animation.core/RepeatableSpec : androidx.compose.animation.core/FiniteAnimationSpec<#A> { // androidx.compose.animation.core/RepeatableSpec|null[0]
+    constructor <init>(kotlin/Int, androidx.compose.animation.core/DurationBasedAnimationSpec<#A>, androidx.compose.animation.core/RepeatMode =...) // androidx.compose.animation.core/RepeatableSpec.<init>|<init>(kotlin.Int;androidx.compose.animation.core.DurationBasedAnimationSpec<1:0>;androidx.compose.animation.core.RepeatMode){}[0]
+    constructor <init>(kotlin/Int, androidx.compose.animation.core/DurationBasedAnimationSpec<#A>, androidx.compose.animation.core/RepeatMode =..., androidx.compose.animation.core/StartOffset =...) // androidx.compose.animation.core/RepeatableSpec.<init>|<init>(kotlin.Int;androidx.compose.animation.core.DurationBasedAnimationSpec<1:0>;androidx.compose.animation.core.RepeatMode;androidx.compose.animation.core.StartOffset){}[0]
+    final fun <#A1: androidx.compose.animation.core/AnimationVector> vectorize(androidx.compose.animation.core/TwoWayConverter<#A, #A1>): androidx.compose.animation.core/VectorizedFiniteAnimationSpec<#A1> // androidx.compose.animation.core/RepeatableSpec.vectorize|vectorize(androidx.compose.animation.core.TwoWayConverter<1:0,0:0>){0§<androidx.compose.animation.core.AnimationVector>}[0]
+    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.animation.core/RepeatableSpec.equals|equals(kotlin.Any?){}[0]
+    final fun hashCode(): kotlin/Int // androidx.compose.animation.core/RepeatableSpec.hashCode|hashCode(){}[0]
+    final val animation // androidx.compose.animation.core/RepeatableSpec.animation|{}animation[0]
+        final fun <get-animation>(): androidx.compose.animation.core/DurationBasedAnimationSpec<#A> // androidx.compose.animation.core/RepeatableSpec.animation.<get-animation>|<get-animation>(){}[0]
+    final val initialStartOffset // androidx.compose.animation.core/RepeatableSpec.initialStartOffset|{}initialStartOffset[0]
+        final fun <get-initialStartOffset>(): androidx.compose.animation.core/StartOffset // androidx.compose.animation.core/RepeatableSpec.initialStartOffset.<get-initialStartOffset>|<get-initialStartOffset>(){}[0]
+    final val iterations // androidx.compose.animation.core/RepeatableSpec.iterations|{}iterations[0]
+        final fun <get-iterations>(): kotlin/Int // androidx.compose.animation.core/RepeatableSpec.iterations.<get-iterations>|<get-iterations>(){}[0]
+    final val repeatMode // androidx.compose.animation.core/RepeatableSpec.repeatMode|{}repeatMode[0]
+        final fun <get-repeatMode>(): androidx.compose.animation.core/RepeatMode // androidx.compose.animation.core/RepeatableSpec.repeatMode.<get-repeatMode>|<get-repeatMode>(){}[0]
+}
+final class <#A: kotlin/Any?> androidx.compose.animation.core/SeekableTransitionState : androidx.compose.animation.core/TransitionState<#A> { // androidx.compose.animation.core/SeekableTransitionState|null[0]
+    constructor <init>(#A) // androidx.compose.animation.core/SeekableTransitionState.<init>|<init>(1:0){}[0]
+    final suspend fun animateTo(#A =..., androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float>? =...) // androidx.compose.animation.core/SeekableTransitionState.animateTo|animateTo(1:0;androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>?){}[0]
+    final suspend fun seekTo(kotlin/Float, #A =...) // androidx.compose.animation.core/SeekableTransitionState.seekTo|seekTo(kotlin.Float;1:0){}[0]
+    final suspend fun snapTo(#A) // androidx.compose.animation.core/SeekableTransitionState.snapTo|snapTo(1:0){}[0]
+    final var currentState // androidx.compose.animation.core/SeekableTransitionState.currentState|{}currentState[0]
+        final fun <get-currentState>(): #A // androidx.compose.animation.core/SeekableTransitionState.currentState.<get-currentState>|<get-currentState>(){}[0]
+    final var fraction // androidx.compose.animation.core/SeekableTransitionState.fraction|{}fraction[0]
+        final fun <get-fraction>(): kotlin/Float // androidx.compose.animation.core/SeekableTransitionState.fraction.<get-fraction>|<get-fraction>(){}[0]
+    final var targetState // androidx.compose.animation.core/SeekableTransitionState.targetState|{}targetState[0]
+        final fun <get-targetState>(): #A // androidx.compose.animation.core/SeekableTransitionState.targetState.<get-targetState>|<get-targetState>(){}[0]
+}
+final class <#A: kotlin/Any?> androidx.compose.animation.core/SnapSpec : androidx.compose.animation.core/DurationBasedAnimationSpec<#A> { // androidx.compose.animation.core/SnapSpec|null[0]
+    constructor <init>(kotlin/Int =...) // androidx.compose.animation.core/SnapSpec.<init>|<init>(kotlin.Int){}[0]
+    final fun <#A1: androidx.compose.animation.core/AnimationVector> vectorize(androidx.compose.animation.core/TwoWayConverter<#A, #A1>): androidx.compose.animation.core/VectorizedDurationBasedAnimationSpec<#A1> // androidx.compose.animation.core/SnapSpec.vectorize|vectorize(androidx.compose.animation.core.TwoWayConverter<1:0,0:0>){0§<androidx.compose.animation.core.AnimationVector>}[0]
+    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.animation.core/SnapSpec.equals|equals(kotlin.Any?){}[0]
+    final fun hashCode(): kotlin/Int // androidx.compose.animation.core/SnapSpec.hashCode|hashCode(){}[0]
+    final val delay // androidx.compose.animation.core/SnapSpec.delay|{}delay[0]
+        final fun <get-delay>(): kotlin/Int // androidx.compose.animation.core/SnapSpec.delay.<get-delay>|<get-delay>(){}[0]
+}
+final class <#A: kotlin/Any?> androidx.compose.animation.core/SpringSpec : androidx.compose.animation.core/FiniteAnimationSpec<#A> { // androidx.compose.animation.core/SpringSpec|null[0]
+    constructor <init>(kotlin/Float =..., kotlin/Float =..., #A? =...) // androidx.compose.animation.core/SpringSpec.<init>|<init>(kotlin.Float;kotlin.Float;1:0?){}[0]
+    final fun <#A1: androidx.compose.animation.core/AnimationVector> vectorize(androidx.compose.animation.core/TwoWayConverter<#A, #A1>): androidx.compose.animation.core/VectorizedSpringSpec<#A1> // androidx.compose.animation.core/SpringSpec.vectorize|vectorize(androidx.compose.animation.core.TwoWayConverter<1:0,0:0>){0§<androidx.compose.animation.core.AnimationVector>}[0]
+    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.animation.core/SpringSpec.equals|equals(kotlin.Any?){}[0]
+    final fun hashCode(): kotlin/Int // androidx.compose.animation.core/SpringSpec.hashCode|hashCode(){}[0]
+    final val dampingRatio // androidx.compose.animation.core/SpringSpec.dampingRatio|{}dampingRatio[0]
+        final fun <get-dampingRatio>(): kotlin/Float // androidx.compose.animation.core/SpringSpec.dampingRatio.<get-dampingRatio>|<get-dampingRatio>(){}[0]
+    final val stiffness // androidx.compose.animation.core/SpringSpec.stiffness|{}stiffness[0]
+        final fun <get-stiffness>(): kotlin/Float // androidx.compose.animation.core/SpringSpec.stiffness.<get-stiffness>|<get-stiffness>(){}[0]
+    final val visibilityThreshold // androidx.compose.animation.core/SpringSpec.visibilityThreshold|{}visibilityThreshold[0]
+        final fun <get-visibilityThreshold>(): #A? // androidx.compose.animation.core/SpringSpec.visibilityThreshold.<get-visibilityThreshold>|<get-visibilityThreshold>(){}[0]
+}
+final class <#A: kotlin/Any?> androidx.compose.animation.core/Transition { // androidx.compose.animation.core/Transition|null[0]
+    abstract interface <#A1: kotlin/Any?> Segment { // androidx.compose.animation.core/Transition.Segment|null[0]
+        abstract val initialState // androidx.compose.animation.core/Transition.Segment.initialState|<get-initialState>(){}[0]
+            abstract fun <get-initialState>(): #A1 // androidx.compose.animation.core/Transition.Segment.initialState.<get-initialState>|<get-initialState>(){}[0]
+        abstract val targetState // androidx.compose.animation.core/Transition.Segment.targetState|<get-targetState>(){}[0]
+            abstract fun <get-targetState>(): #A1 // androidx.compose.animation.core/Transition.Segment.targetState.<get-targetState>|<get-targetState>(){}[0]
+        open fun (#A1).isTransitioningTo(#A1): kotlin/Boolean // androidx.compose.animation.core/Transition.Segment.isTransitioningTo|isTransitioningTo@1:0(1:0){}[0]
+    }
+    constructor <init>(androidx.compose.animation.core/MutableTransitionState<#A>, kotlin/String? =...) // androidx.compose.animation.core/Transition.<init>|<init>(androidx.compose.animation.core.MutableTransitionState<1:0>;kotlin.String?){}[0]
+    constructor <init>(androidx.compose.animation.core/TransitionState<#A>, kotlin/String? =...) // androidx.compose.animation.core/Transition.<init>|<init>(androidx.compose.animation.core.TransitionState<1:0>;kotlin.String?){}[0]
+    final fun setPlaytimeAfterInitialAndTargetStateEstablished(#A, #A, kotlin/Long) // androidx.compose.animation.core/Transition.setPlaytimeAfterInitialAndTargetStateEstablished|setPlaytimeAfterInitialAndTargetStateEstablished(1:0;1:0;kotlin.Long){}[0]
+    final fun toString(): kotlin/String // androidx.compose.animation.core/Transition.toString|toString(){}[0]
+    final inner class <#A1: kotlin/Any?, #B1: androidx.compose.animation.core/AnimationVector> DeferredAnimation { // androidx.compose.animation.core/Transition.DeferredAnimation|null[0]
+        final fun animate(kotlin/Function1<androidx.compose.animation.core/Transition.Segment<#A>, androidx.compose.animation.core/FiniteAnimationSpec<#A1>>, kotlin/Function1<#A, #A1>): androidx.compose.runtime/State<#A1> // androidx.compose.animation.core/Transition.DeferredAnimation.animate|animate(kotlin.Function1<androidx.compose.animation.core.Transition.Segment<2:0>,androidx.compose.animation.core.FiniteAnimationSpec<1:0>>;kotlin.Function1<2:0,1:0>){}[0]
+        final val label // androidx.compose.animation.core/Transition.DeferredAnimation.label|{}label[0]
+            final fun <get-label>(): kotlin/String // androidx.compose.animation.core/Transition.DeferredAnimation.label.<get-label>|<get-label>(){}[0]
+        final val typeConverter // androidx.compose.animation.core/Transition.DeferredAnimation.typeConverter|{}typeConverter[0]
+            final fun <get-typeConverter>(): androidx.compose.animation.core/TwoWayConverter<#A1, #B1> // androidx.compose.animation.core/Transition.DeferredAnimation.typeConverter.<get-typeConverter>|<get-typeConverter>(){}[0]
+    }
+    final inner class <#A1: kotlin/Any?, #B1: androidx.compose.animation.core/AnimationVector> TransitionAnimationState : androidx.compose.runtime/State<#A1> { // androidx.compose.animation.core/Transition.TransitionAnimationState|null[0]
+        final fun toString(): kotlin/String // androidx.compose.animation.core/Transition.TransitionAnimationState.toString|toString(){}[0]
+        final val label // androidx.compose.animation.core/Transition.TransitionAnimationState.label|{}label[0]
+            final fun <get-label>(): kotlin/String // androidx.compose.animation.core/Transition.TransitionAnimationState.label.<get-label>|<get-label>(){}[0]
+        final val typeConverter // androidx.compose.animation.core/Transition.TransitionAnimationState.typeConverter|{}typeConverter[0]
+            final fun <get-typeConverter>(): androidx.compose.animation.core/TwoWayConverter<#A1, #B1> // androidx.compose.animation.core/Transition.TransitionAnimationState.typeConverter.<get-typeConverter>|<get-typeConverter>(){}[0]
+        final var animation // androidx.compose.animation.core/Transition.TransitionAnimationState.animation|{}animation[0]
+            final fun <get-animation>(): androidx.compose.animation.core/TargetBasedAnimation<#A1, #B1> // androidx.compose.animation.core/Transition.TransitionAnimationState.animation.<get-animation>|<get-animation>(){}[0]
+        final var animationSpec // androidx.compose.animation.core/Transition.TransitionAnimationState.animationSpec|{}animationSpec[0]
+            final fun <get-animationSpec>(): androidx.compose.animation.core/FiniteAnimationSpec<#A1> // androidx.compose.animation.core/Transition.TransitionAnimationState.animationSpec.<get-animationSpec>|<get-animationSpec>(){}[0]
+        final var value // androidx.compose.animation.core/Transition.TransitionAnimationState.value|{}value[0]
+            final fun <get-value>(): #A1 // androidx.compose.animation.core/Transition.TransitionAnimationState.value.<get-value>|<get-value>(){}[0]
+    }
+    final val animations // androidx.compose.animation.core/Transition.animations|{}animations[0]
+        final fun <get-animations>(): kotlin.collections/List<androidx.compose.animation.core/Transition.TransitionAnimationState<*, *, #A>> // androidx.compose.animation.core/Transition.animations.<get-animations>|<get-animations>(){}[0]
+    final val currentState // androidx.compose.animation.core/Transition.currentState|{}currentState[0]
+        final fun <get-currentState>(): #A // androidx.compose.animation.core/Transition.currentState.<get-currentState>|<get-currentState>(){}[0]
+    final val isRunning // androidx.compose.animation.core/Transition.isRunning|{}isRunning[0]
+        final fun <get-isRunning>(): kotlin/Boolean // androidx.compose.animation.core/Transition.isRunning.<get-isRunning>|<get-isRunning>(){}[0]
+    final val label // androidx.compose.animation.core/Transition.label|{}label[0]
+        final fun <get-label>(): kotlin/String? // androidx.compose.animation.core/Transition.label.<get-label>|<get-label>(){}[0]
+    final val parentTransition // androidx.compose.animation.core/Transition.parentTransition|{}parentTransition[0]
+        final fun <get-parentTransition>(): androidx.compose.animation.core/Transition<*>? // androidx.compose.animation.core/Transition.parentTransition.<get-parentTransition>|<get-parentTransition>(){}[0]
+    final val totalDurationNanos // androidx.compose.animation.core/Transition.totalDurationNanos|<get-totalDurationNanos>(){}[0]
+        final fun <get-totalDurationNanos>(): kotlin/Long // androidx.compose.animation.core/Transition.totalDurationNanos.<get-totalDurationNanos>|<get-totalDurationNanos>(){}[0]
+    final val transitions // androidx.compose.animation.core/Transition.transitions|{}transitions[0]
+        final fun <get-transitions>(): kotlin.collections/List<androidx.compose.animation.core/Transition<*>> // androidx.compose.animation.core/Transition.transitions.<get-transitions>|<get-transitions>(){}[0]
+    final var isSeeking // androidx.compose.animation.core/Transition.isSeeking|{}isSeeking[0]
+        final fun <get-isSeeking>(): kotlin/Boolean // androidx.compose.animation.core/Transition.isSeeking.<get-isSeeking>|<get-isSeeking>(){}[0]
+    final var playTimeNanos // androidx.compose.animation.core/Transition.playTimeNanos|<set-playTimeNanos>(kotlin.Long){}[0]
+        final fun <get-playTimeNanos>(): kotlin/Long // androidx.compose.animation.core/Transition.playTimeNanos.<get-playTimeNanos>|<get-playTimeNanos>(){}[0]
+        final fun <set-playTimeNanos>(kotlin/Long) // androidx.compose.animation.core/Transition.playTimeNanos.<set-playTimeNanos>|<set-playTimeNanos>(kotlin.Long){}[0]
+    final var segment // androidx.compose.animation.core/Transition.segment|{}segment[0]
+        final fun <get-segment>(): androidx.compose.animation.core/Transition.Segment<#A> // androidx.compose.animation.core/Transition.segment.<get-segment>|<get-segment>(){}[0]
+    final var targetState // androidx.compose.animation.core/Transition.targetState|{}targetState[0]
+        final fun <get-targetState>(): #A // androidx.compose.animation.core/Transition.targetState.<get-targetState>|<get-targetState>(){}[0]
+}
+final class <#A: kotlin/Any?> androidx.compose.animation.core/TweenSpec : androidx.compose.animation.core/DurationBasedAnimationSpec<#A> { // androidx.compose.animation.core/TweenSpec|null[0]
+    constructor <init>(kotlin/Int =..., kotlin/Int =..., androidx.compose.animation.core/Easing =...) // androidx.compose.animation.core/TweenSpec.<init>|<init>(kotlin.Int;kotlin.Int;androidx.compose.animation.core.Easing){}[0]
+    final fun <#A1: androidx.compose.animation.core/AnimationVector> vectorize(androidx.compose.animation.core/TwoWayConverter<#A, #A1>): androidx.compose.animation.core/VectorizedTweenSpec<#A1> // androidx.compose.animation.core/TweenSpec.vectorize|vectorize(androidx.compose.animation.core.TwoWayConverter<1:0,0:0>){0§<androidx.compose.animation.core.AnimationVector>}[0]
+    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.animation.core/TweenSpec.equals|equals(kotlin.Any?){}[0]
+    final fun hashCode(): kotlin/Int // androidx.compose.animation.core/TweenSpec.hashCode|hashCode(){}[0]
+    final val delay // androidx.compose.animation.core/TweenSpec.delay|{}delay[0]
+        final fun <get-delay>(): kotlin/Int // androidx.compose.animation.core/TweenSpec.delay.<get-delay>|<get-delay>(){}[0]
+    final val durationMillis // androidx.compose.animation.core/TweenSpec.durationMillis|{}durationMillis[0]
+        final fun <get-durationMillis>(): kotlin/Int // androidx.compose.animation.core/TweenSpec.durationMillis.<get-durationMillis>|<get-durationMillis>(){}[0]
+    final val easing // androidx.compose.animation.core/TweenSpec.easing|{}easing[0]
+        final fun <get-easing>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/TweenSpec.easing.<get-easing>|<get-easing>(){}[0]
+}
+final class androidx.compose.animation.core/AnimationVector1D : androidx.compose.animation.core/AnimationVector { // androidx.compose.animation.core/AnimationVector1D|null[0]
+    constructor <init>(kotlin/Float) // androidx.compose.animation.core/AnimationVector1D.<init>|<init>(kotlin.Float){}[0]
+    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.animation.core/AnimationVector1D.equals|equals(kotlin.Any?){}[0]
+    final fun hashCode(): kotlin/Int // androidx.compose.animation.core/AnimationVector1D.hashCode|hashCode(){}[0]
+    final fun toString(): kotlin/String // androidx.compose.animation.core/AnimationVector1D.toString|toString(){}[0]
+    final var value // androidx.compose.animation.core/AnimationVector1D.value|{}value[0]
+        final fun <get-value>(): kotlin/Float // androidx.compose.animation.core/AnimationVector1D.value.<get-value>|<get-value>(){}[0]
+}
+final class androidx.compose.animation.core/AnimationVector2D : androidx.compose.animation.core/AnimationVector { // androidx.compose.animation.core/AnimationVector2D|null[0]
+    constructor <init>(kotlin/Float, kotlin/Float) // androidx.compose.animation.core/AnimationVector2D.<init>|<init>(kotlin.Float;kotlin.Float){}[0]
+    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.animation.core/AnimationVector2D.equals|equals(kotlin.Any?){}[0]
+    final fun hashCode(): kotlin/Int // androidx.compose.animation.core/AnimationVector2D.hashCode|hashCode(){}[0]
+    final fun toString(): kotlin/String // androidx.compose.animation.core/AnimationVector2D.toString|toString(){}[0]
+    final var v1 // androidx.compose.animation.core/AnimationVector2D.v1|{}v1[0]
+        final fun <get-v1>(): kotlin/Float // androidx.compose.animation.core/AnimationVector2D.v1.<get-v1>|<get-v1>(){}[0]
+    final var v2 // androidx.compose.animation.core/AnimationVector2D.v2|{}v2[0]
+        final fun <get-v2>(): kotlin/Float // androidx.compose.animation.core/AnimationVector2D.v2.<get-v2>|<get-v2>(){}[0]
+}
+final class androidx.compose.animation.core/AnimationVector3D : androidx.compose.animation.core/AnimationVector { // androidx.compose.animation.core/AnimationVector3D|null[0]
+    constructor <init>(kotlin/Float, kotlin/Float, kotlin/Float) // androidx.compose.animation.core/AnimationVector3D.<init>|<init>(kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.animation.core/AnimationVector3D.equals|equals(kotlin.Any?){}[0]
+    final fun hashCode(): kotlin/Int // androidx.compose.animation.core/AnimationVector3D.hashCode|hashCode(){}[0]
+    final fun toString(): kotlin/String // androidx.compose.animation.core/AnimationVector3D.toString|toString(){}[0]
+    final var v1 // androidx.compose.animation.core/AnimationVector3D.v1|{}v1[0]
+        final fun <get-v1>(): kotlin/Float // androidx.compose.animation.core/AnimationVector3D.v1.<get-v1>|<get-v1>(){}[0]
+    final var v2 // androidx.compose.animation.core/AnimationVector3D.v2|{}v2[0]
+        final fun <get-v2>(): kotlin/Float // androidx.compose.animation.core/AnimationVector3D.v2.<get-v2>|<get-v2>(){}[0]
+    final var v3 // androidx.compose.animation.core/AnimationVector3D.v3|{}v3[0]
+        final fun <get-v3>(): kotlin/Float // androidx.compose.animation.core/AnimationVector3D.v3.<get-v3>|<get-v3>(){}[0]
+}
+final class androidx.compose.animation.core/AnimationVector4D : androidx.compose.animation.core/AnimationVector { // androidx.compose.animation.core/AnimationVector4D|null[0]
+    constructor <init>(kotlin/Float, kotlin/Float, kotlin/Float, kotlin/Float) // androidx.compose.animation.core/AnimationVector4D.<init>|<init>(kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.animation.core/AnimationVector4D.equals|equals(kotlin.Any?){}[0]
+    final fun hashCode(): kotlin/Int // androidx.compose.animation.core/AnimationVector4D.hashCode|hashCode(){}[0]
+    final fun toString(): kotlin/String // androidx.compose.animation.core/AnimationVector4D.toString|toString(){}[0]
+    final var v1 // androidx.compose.animation.core/AnimationVector4D.v1|{}v1[0]
+        final fun <get-v1>(): kotlin/Float // androidx.compose.animation.core/AnimationVector4D.v1.<get-v1>|<get-v1>(){}[0]
+    final var v2 // androidx.compose.animation.core/AnimationVector4D.v2|{}v2[0]
+        final fun <get-v2>(): kotlin/Float // androidx.compose.animation.core/AnimationVector4D.v2.<get-v2>|<get-v2>(){}[0]
+    final var v3 // androidx.compose.animation.core/AnimationVector4D.v3|{}v3[0]
+        final fun <get-v3>(): kotlin/Float // androidx.compose.animation.core/AnimationVector4D.v3.<get-v3>|<get-v3>(){}[0]
+    final var v4 // androidx.compose.animation.core/AnimationVector4D.v4|{}v4[0]
+        final fun <get-v4>(): kotlin/Float // androidx.compose.animation.core/AnimationVector4D.v4.<get-v4>|<get-v4>(){}[0]
+}
+final class androidx.compose.animation.core/CubicBezierEasing : androidx.compose.animation.core/Easing { // androidx.compose.animation.core/CubicBezierEasing|null[0]
+    constructor <init>(kotlin/Float, kotlin/Float, kotlin/Float, kotlin/Float) // androidx.compose.animation.core/CubicBezierEasing.<init>|<init>(kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.animation.core/CubicBezierEasing.equals|equals(kotlin.Any?){}[0]
+    final fun hashCode(): kotlin/Int // androidx.compose.animation.core/CubicBezierEasing.hashCode|hashCode(){}[0]
+    final fun toString(): kotlin/String // androidx.compose.animation.core/CubicBezierEasing.toString|toString(){}[0]
+    final fun transform(kotlin/Float): kotlin/Float // androidx.compose.animation.core/CubicBezierEasing.transform|transform(kotlin.Float){}[0]
+}
+final class androidx.compose.animation.core/FloatExponentialDecaySpec : androidx.compose.animation.core/FloatDecayAnimationSpec { // androidx.compose.animation.core/FloatExponentialDecaySpec|null[0]
+    constructor <init>(kotlin/Float =..., kotlin/Float =...) // androidx.compose.animation.core/FloatExponentialDecaySpec.<init>|<init>(kotlin.Float;kotlin.Float){}[0]
+    final fun getDurationNanos(kotlin/Float, kotlin/Float): kotlin/Long // androidx.compose.animation.core/FloatExponentialDecaySpec.getDurationNanos|getDurationNanos(kotlin.Float;kotlin.Float){}[0]
+    final fun getTargetValue(kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatExponentialDecaySpec.getTargetValue|getTargetValue(kotlin.Float;kotlin.Float){}[0]
+    final fun getValueFromNanos(kotlin/Long, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatExponentialDecaySpec.getValueFromNanos|getValueFromNanos(kotlin.Long;kotlin.Float;kotlin.Float){}[0]
+    final fun getVelocityFromNanos(kotlin/Long, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatExponentialDecaySpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;kotlin.Float;kotlin.Float){}[0]
+    final val absVelocityThreshold // androidx.compose.animation.core/FloatExponentialDecaySpec.absVelocityThreshold|{}absVelocityThreshold[0]
+        final fun <get-absVelocityThreshold>(): kotlin/Float // androidx.compose.animation.core/FloatExponentialDecaySpec.absVelocityThreshold.<get-absVelocityThreshold>|<get-absVelocityThreshold>(){}[0]
+}
+final class androidx.compose.animation.core/FloatSpringSpec : androidx.compose.animation.core/FloatAnimationSpec { // androidx.compose.animation.core/FloatSpringSpec|null[0]
+    constructor <init>(kotlin/Float =..., kotlin/Float =..., kotlin/Float =...) // androidx.compose.animation.core/FloatSpringSpec.<init>|<init>(kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    final fun getDurationNanos(kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Long // androidx.compose.animation.core/FloatSpringSpec.getDurationNanos|getDurationNanos(kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    final fun getEndVelocity(kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatSpringSpec.getEndVelocity|getEndVelocity(kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    final fun getValueFromNanos(kotlin/Long, kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatSpringSpec.getValueFromNanos|getValueFromNanos(kotlin.Long;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    final fun getVelocityFromNanos(kotlin/Long, kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatSpringSpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    final val dampingRatio // androidx.compose.animation.core/FloatSpringSpec.dampingRatio|{}dampingRatio[0]
+        final fun <get-dampingRatio>(): kotlin/Float // androidx.compose.animation.core/FloatSpringSpec.dampingRatio.<get-dampingRatio>|<get-dampingRatio>(){}[0]
+    final val stiffness // androidx.compose.animation.core/FloatSpringSpec.stiffness|{}stiffness[0]
+        final fun <get-stiffness>(): kotlin/Float // androidx.compose.animation.core/FloatSpringSpec.stiffness.<get-stiffness>|<get-stiffness>(){}[0]
+}
+final class androidx.compose.animation.core/FloatTweenSpec : androidx.compose.animation.core/FloatAnimationSpec { // androidx.compose.animation.core/FloatTweenSpec|null[0]
+    constructor <init>(kotlin/Int =..., kotlin/Int =..., androidx.compose.animation.core/Easing =...) // androidx.compose.animation.core/FloatTweenSpec.<init>|<init>(kotlin.Int;kotlin.Int;androidx.compose.animation.core.Easing){}[0]
+    final fun getDurationNanos(kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Long // androidx.compose.animation.core/FloatTweenSpec.getDurationNanos|getDurationNanos(kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    final fun getValueFromNanos(kotlin/Long, kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatTweenSpec.getValueFromNanos|getValueFromNanos(kotlin.Long;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    final fun getVelocityFromNanos(kotlin/Long, kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/FloatTweenSpec.getVelocityFromNanos|getVelocityFromNanos(kotlin.Long;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+    final val delay // androidx.compose.animation.core/FloatTweenSpec.delay|{}delay[0]
+        final fun <get-delay>(): kotlin/Int // androidx.compose.animation.core/FloatTweenSpec.delay.<get-delay>|<get-delay>(){}[0]
+    final val duration // androidx.compose.animation.core/FloatTweenSpec.duration|{}duration[0]
+        final fun <get-duration>(): kotlin/Int // androidx.compose.animation.core/FloatTweenSpec.duration.<get-duration>|<get-duration>(){}[0]
+}
+final class androidx.compose.animation.core/InfiniteTransition { // androidx.compose.animation.core/InfiniteTransition|null[0]
+    final inner class <#A1: kotlin/Any?, #B1: androidx.compose.animation.core/AnimationVector> TransitionAnimationState : androidx.compose.runtime/State<#A1> { // androidx.compose.animation.core/InfiniteTransition.TransitionAnimationState|null[0]
+        final val label // androidx.compose.animation.core/InfiniteTransition.TransitionAnimationState.label|{}label[0]
+            final fun <get-label>(): kotlin/String // androidx.compose.animation.core/InfiniteTransition.TransitionAnimationState.label.<get-label>|<get-label>(){}[0]
+        final val typeConverter // androidx.compose.animation.core/InfiniteTransition.TransitionAnimationState.typeConverter|{}typeConverter[0]
+            final fun <get-typeConverter>(): androidx.compose.animation.core/TwoWayConverter<#A1, #B1> // androidx.compose.animation.core/InfiniteTransition.TransitionAnimationState.typeConverter.<get-typeConverter>|<get-typeConverter>(){}[0]
+        final var animation // androidx.compose.animation.core/InfiniteTransition.TransitionAnimationState.animation|{}animation[0]
+            final fun <get-animation>(): androidx.compose.animation.core/TargetBasedAnimation<#A1, #B1> // androidx.compose.animation.core/InfiniteTransition.TransitionAnimationState.animation.<get-animation>|<get-animation>(){}[0]
+        final var animationSpec // androidx.compose.animation.core/InfiniteTransition.TransitionAnimationState.animationSpec|{}animationSpec[0]
+            final fun <get-animationSpec>(): androidx.compose.animation.core/AnimationSpec<#A1> // androidx.compose.animation.core/InfiniteTransition.TransitionAnimationState.animationSpec.<get-animationSpec>|<get-animationSpec>(){}[0]
+        final var value // androidx.compose.animation.core/InfiniteTransition.TransitionAnimationState.value|{}value[0]
+            final fun <get-value>(): #A1 // androidx.compose.animation.core/InfiniteTransition.TransitionAnimationState.value.<get-value>|<get-value>(){}[0]
+    }
+    final val animations // androidx.compose.animation.core/InfiniteTransition.animations|{}animations[0]
+        final fun <get-animations>(): kotlin.collections/List<androidx.compose.animation.core/InfiniteTransition.TransitionAnimationState<*, *>> // androidx.compose.animation.core/InfiniteTransition.animations.<get-animations>|<get-animations>(){}[0]
+    final val label // androidx.compose.animation.core/InfiniteTransition.label|{}label[0]
+        final fun <get-label>(): kotlin/String // androidx.compose.animation.core/InfiniteTransition.label.<get-label>|<get-label>(){}[0]
+}
+final class androidx.compose.animation.core/PathEasing : androidx.compose.animation.core/Easing { // androidx.compose.animation.core/PathEasing|null[0]
+    constructor <init>(androidx.compose.ui.graphics/Path) // androidx.compose.animation.core/PathEasing.<init>|<init>(androidx.compose.ui.graphics.Path){}[0]
+    final fun transform(kotlin/Float): kotlin/Float // androidx.compose.animation.core/PathEasing.transform|transform(kotlin.Float){}[0]
+}
+final enum class androidx.compose.animation.core/AnimationEndReason : kotlin/Enum<androidx.compose.animation.core/AnimationEndReason> { // androidx.compose.animation.core/AnimationEndReason|null[0]
+    enum entry BoundReached // androidx.compose.animation.core/AnimationEndReason.BoundReached|null[0]
+    enum entry Finished // androidx.compose.animation.core/AnimationEndReason.Finished|null[0]
+    final fun valueOf(kotlin/String): androidx.compose.animation.core/AnimationEndReason // androidx.compose.animation.core/AnimationEndReason.valueOf|valueOf#static(kotlin.String){}[0]
+    final fun values(): kotlin/Array<androidx.compose.animation.core/AnimationEndReason> // androidx.compose.animation.core/AnimationEndReason.values|values#static(){}[0]
+}
+final enum class androidx.compose.animation.core/RepeatMode : kotlin/Enum<androidx.compose.animation.core/RepeatMode> { // androidx.compose.animation.core/RepeatMode|null[0]
+    enum entry Restart // androidx.compose.animation.core/RepeatMode.Restart|null[0]
+    enum entry Reverse // androidx.compose.animation.core/RepeatMode.Reverse|null[0]
+    final fun valueOf(kotlin/String): androidx.compose.animation.core/RepeatMode // androidx.compose.animation.core/RepeatMode.valueOf|valueOf#static(kotlin.String){}[0]
+    final fun values(): kotlin/Array<androidx.compose.animation.core/RepeatMode> // androidx.compose.animation.core/RepeatMode.values|values#static(){}[0]
+}
+final fun (androidx.compose.animation.core/AnimationState<kotlin/Float, androidx.compose.animation.core/AnimationVector1D>).androidx.compose.animation.core/copy(kotlin/Float =..., kotlin/Float =..., kotlin/Long =..., kotlin/Long =..., kotlin/Boolean =...): androidx.compose.animation.core/AnimationState<kotlin/Float, androidx.compose.animation.core/AnimationVector1D> // androidx.compose.animation.core/copy|[email protected]<kotlin.Float,androidx.compose.animation.core.AnimationVector1D>(kotlin.Float;kotlin.Float;kotlin.Long;kotlin.Long;kotlin.Boolean){}[0]
+final fun (androidx.compose.animation.core/DecayAnimationSpec<kotlin/Float>).androidx.compose.animation.core/calculateTargetValue(kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.animation.core/calculateTargetValue|calculateTargetValue@androidx.compose.animation.core.DecayAnimationSpec<kotlin.Float>(kotlin.Float;kotlin.Float){}[0]
+final fun (androidx.compose.animation.core/InfiniteTransition).androidx.compose.animation.core/animateFloat(kotlin/Float, kotlin/Float, androidx.compose.animation.core/InfiniteRepeatableSpec<kotlin/Float>): androidx.compose.runtime/State<kotlin/Float> // androidx.compose.animation.core/animateFloat|[email protected](kotlin.Float;kotlin.Float;androidx.compose.animation.core.InfiniteRepeatableSpec<kotlin.Float>){}[0]
+final fun (androidx.compose.animation.core/InfiniteTransition).androidx.compose.animation.core/animateFloat(kotlin/Float, kotlin/Float, androidx.compose.animation.core/InfiniteRepeatableSpec<kotlin/Float>, kotlin/String =...): androidx.compose.runtime/State<kotlin/Float> // androidx.compose.animation.core/animateFloat|[email protected](kotlin.Float;kotlin.Float;androidx.compose.animation.core.InfiniteRepeatableSpec<kotlin.Float>;kotlin.String){}[0]
+final fun <#A: androidx.compose.animation.core/AnimationVector> (androidx.compose.animation.core/VectorizedAnimationSpec<#A>).androidx.compose.animation.core/createAnimation(#A, #A, #A): androidx.compose.animation.core/TargetBasedAnimation<#A, #A> // androidx.compose.animation.core/createAnimation|createAnimation@androidx.compose.animation.core.VectorizedAnimationSpec<0:0>(0:0;0:0;0:0){0§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> (androidx.compose.animation.core/Animation<#A, #B>).androidx.compose.animation.core/getVelocityFromNanos(kotlin/Long): #A // androidx.compose.animation.core/getVelocityFromNanos|[email protected]<0:0,0:1>(kotlin.Long){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> (androidx.compose.animation.core/AnimationState<#A, #B>).androidx.compose.animation.core/copy(#A =..., #B? =..., kotlin/Long =..., kotlin/Long =..., kotlin/Boolean =...): androidx.compose.animation.core/AnimationState<#A, #B> // androidx.compose.animation.core/copy|[email protected]<0:0,0:1>(0:0;0:1?;kotlin.Long;kotlin.Long;kotlin.Boolean){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> (androidx.compose.animation.core/DecayAnimationSpec<#A>).androidx.compose.animation.core/calculateTargetValue(androidx.compose.animation.core/TwoWayConverter<#A, #B>, #A, #A): #A // androidx.compose.animation.core/calculateTargetValue|calculateTargetValue@androidx.compose.animation.core.DecayAnimationSpec<0:0>(androidx.compose.animation.core.TwoWayConverter<0:0,0:1>;0:0;0:0){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> (androidx.compose.animation.core/InfiniteTransition).androidx.compose.animation.core/animateValue(#A, #A, androidx.compose.animation.core/TwoWayConverter<#A, #B>, androidx.compose.animation.core/InfiniteRepeatableSpec<#A>): androidx.compose.runtime/State<#A> // androidx.compose.animation.core/animateValue|[email protected](0:0;0:0;androidx.compose.animation.core.TwoWayConverter<0:0,0:1>;androidx.compose.animation.core.InfiniteRepeatableSpec<0:0>){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> (androidx.compose.animation.core/InfiniteTransition).androidx.compose.animation.core/animateValue(#A, #A, androidx.compose.animation.core/TwoWayConverter<#A, #B>, androidx.compose.animation.core/InfiniteRepeatableSpec<#A>, kotlin/String =...): androidx.compose.runtime/State<#A> // androidx.compose.animation.core/animateValue|[email protected](0:0;0:0;androidx.compose.animation.core.TwoWayConverter<0:0,0:1>;androidx.compose.animation.core.InfiniteRepeatableSpec<0:0>;kotlin.String){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> (androidx.compose.animation.core/TwoWayConverter<#A, #B>).androidx.compose.animation.core/createZeroVectorFrom(#A): #B // androidx.compose.animation.core/createZeroVectorFrom|createZeroVectorFrom@androidx.compose.animation.core.TwoWayConverter<0:0,0:1>(0:0){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/AnimationState(androidx.compose.animation.core/TwoWayConverter<#A, #B>, #A, #A, kotlin/Long =..., kotlin/Long =..., kotlin/Boolean =...): androidx.compose.animation.core/AnimationState<#A, #B> // androidx.compose.animation.core/AnimationState|AnimationState(androidx.compose.animation.core.TwoWayConverter<0:0,0:1>;0:0;0:0;kotlin.Long;kotlin.Long;kotlin.Boolean){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/TargetBasedAnimation(androidx.compose.animation.core/AnimationSpec<#A>, androidx.compose.animation.core/TwoWayConverter<#A, #B>, #A, #A, #A): androidx.compose.animation.core/TargetBasedAnimation<#A, #B> // androidx.compose.animation.core/TargetBasedAnimation|TargetBasedAnimation(androidx.compose.animation.core.AnimationSpec<0:0>;androidx.compose.animation.core.TwoWayConverter<0:0,0:1>;0:0;0:0;0:0){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/TwoWayConverter(kotlin/Function1<#A, #B>, kotlin/Function1<#B, #A>): androidx.compose.animation.core/TwoWayConverter<#A, #B> // androidx.compose.animation.core/TwoWayConverter|TwoWayConverter(kotlin.Function1<0:0,0:1>;kotlin.Function1<0:1,0:0>){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/animateValueAsState(#A, androidx.compose.animation.core/TwoWayConverter<#A, #B>, androidx.compose.animation.core/AnimationSpec<#A> =..., #A? =..., kotlin/Function1<#A, kotlin/Unit>? =...): androidx.compose.runtime/State<#A> // androidx.compose.animation.core/animateValueAsState|animateValueAsState(0:0;androidx.compose.animation.core.TwoWayConverter<0:0,0:1>;androidx.compose.animation.core.AnimationSpec<0:0>;0:0?;kotlin.Function1<0:0,kotlin.Unit>?){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/animateValueAsState(#A, androidx.compose.animation.core/TwoWayConverter<#A, #B>, androidx.compose.animation.core/AnimationSpec<#A> =..., #A? =..., kotlin/String =..., kotlin/Function1<#A, kotlin/Unit>? =...): androidx.compose.runtime/State<#A> // androidx.compose.animation.core/animateValueAsState|animateValueAsState(0:0;androidx.compose.animation.core.TwoWayConverter<0:0,0:1>;androidx.compose.animation.core.AnimationSpec<0:0>;0:0?;kotlin.String;kotlin.Function1<0:0,kotlin.Unit>?){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: androidx.compose.animation.core/AnimationVector> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation.core/createDeferredAnimation(androidx.compose.animation.core/TwoWayConverter<#B, #C>, kotlin/String =...): androidx.compose.animation.core/Transition.DeferredAnimation<#B, #C, #A> // androidx.compose.animation.core/createDeferredAnimation|createDeferredAnimation@androidx.compose.animation.core.Transition<0:0>(androidx.compose.animation.core.TwoWayConverter<0:1,0:2>;kotlin.String){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: androidx.compose.animation.core/AnimationVector> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation.core/createTransitionAnimation(#B, #B, androidx.compose.animation.core/FiniteAnimationSpec<#B>, androidx.compose.animation.core/TwoWayConverter<#B, #C>, kotlin/String): androidx.compose.runtime/State<#B> // androidx.compose.animation.core/createTransitionAnimation|createTransitionAnimation@androidx.compose.animation.core.Transition<0:0>(0:1;0:1;androidx.compose.animation.core.FiniteAnimationSpec<0:1>;androidx.compose.animation.core.TwoWayConverter<0:1,0:2>;kotlin.String){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<androidx.compose.animation.core.AnimationVector>}[0]
+final fun <#A: kotlin/Any?, #B: kotlin/Any?> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation.core/createChildTransitionInternal(#B, #B, kotlin/String): androidx.compose.animation.core/Transition<#B> // androidx.compose.animation.core/createChildTransitionInternal|createChildTransitionInternal@androidx.compose.animation.core.Transition<0:0>(0:1;0:1;kotlin.String){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
+final fun <#A: kotlin/Any?> (androidx.compose.animation.core/FloatDecayAnimationSpec).androidx.compose.animation.core/generateDecayAnimationSpec(): androidx.compose.animation.core/DecayAnimationSpec<#A> // androidx.compose.animation.core/generateDecayAnimationSpec|generateDecayAnimationSpec@androidx.compose.animation.core.FloatDecayAnimationSpec(){0§<kotlin.Any?>}[0]
+final fun <#A: kotlin/Any?> androidx.compose.animation.core/exponentialDecay(kotlin/Float =..., kotlin/Float =...): androidx.compose.animation.core/DecayAnimationSpec<#A> // androidx.compose.animation.core/exponentialDecay|exponentialDecay(kotlin.Float;kotlin.Float){0§<kotlin.Any?>}[0]
+final fun <#A: kotlin/Any?> androidx.compose.animation.core/infiniteRepeatable(androidx.compose.animation.core/DurationBasedAnimationSpec<#A>, androidx.compose.animation.core/RepeatMode =...): androidx.compose.animation.core/InfiniteRepeatableSpec<#A> // androidx.compose.animation.core/infiniteRepeatable|infiniteRepeatable(androidx.compose.animation.core.DurationBasedAnimationSpec<0:0>;androidx.compose.animation.core.RepeatMode){0§<kotlin.Any?>}[0]
+final fun <#A: kotlin/Any?> androidx.compose.animation.core/infiniteRepeatable(androidx.compose.animation.core/DurationBasedAnimationSpec<#A>, androidx.compose.animation.core/RepeatMode =..., androidx.compose.animation.core/StartOffset =...): androidx.compose.animation.core/InfiniteRepeatableSpec<#A> // androidx.compose.animation.core/infiniteRepeatable|infiniteRepeatable(androidx.compose.animation.core.DurationBasedAnimationSpec<0:0>;androidx.compose.animation.core.RepeatMode;androidx.compose.animation.core.StartOffset){0§<kotlin.Any?>}[0]
+final fun <#A: kotlin/Any?> androidx.compose.animation.core/keyframes(kotlin/Function1<androidx.compose.animation.core/KeyframesSpec.KeyframesSpecConfig<#A>, kotlin/Unit>): androidx.compose.animation.core/KeyframesSpec<#A> // androidx.compose.animation.core/keyframes|keyframes(kotlin.Function1<androidx.compose.animation.core.KeyframesSpec.KeyframesSpecConfig<0:0>,kotlin.Unit>){0§<kotlin.Any?>}[0]
+final fun <#A: kotlin/Any?> androidx.compose.animation.core/rememberTransition(androidx.compose.animation.core/TransitionState<#A>, kotlin/String? =...): androidx.compose.animation.core/Transition<#A> // androidx.compose.animation.core/rememberTransition|rememberTransition(androidx.compose.animation.core.TransitionState<0:0>;kotlin.String?){0§<kotlin.Any?>}[0]
+final fun <#A: kotlin/Any?> androidx.compose.animation.core/repeatable(kotlin/Int, androidx.compose.animation.core/DurationBasedAnimationSpec<#A>, androidx.compose.animation.core/RepeatMode =...): androidx.compose.animation.core/RepeatableSpec<#A> // androidx.compose.animation.core/repeatable|repeatable(kotlin.Int;androidx.compose.animation.core.DurationBasedAnimationSpec<0:0>;androidx.compose.animation.core.RepeatMode){0§<kotlin.Any?>}[0]
+final fun <#A: kotlin/Any?> androidx.compose.animation.core/repeatable(kotlin/Int, androidx.compose.animation.core/DurationBasedAnimationSpec<#A>, androidx.compose.animation.core/RepeatMode =..., androidx.compose.animation.core/StartOffset =...): androidx.compose.animation.core/RepeatableSpec<#A> // androidx.compose.animation.core/repeatable|repeatable(kotlin.Int;androidx.compose.animation.core.DurationBasedAnimationSpec<0:0>;androidx.compose.animation.core.RepeatMode;androidx.compose.animation.core.StartOffset){0§<kotlin.Any?>}[0]
+final fun <#A: kotlin/Any?> androidx.compose.animation.core/snap(kotlin/Int =...): androidx.compose.animation.core/SnapSpec<#A> // androidx.compose.animation.core/snap|snap(kotlin.Int){0§<kotlin.Any?>}[0]
+final fun <#A: kotlin/Any?> androidx.compose.animation.core/spring(kotlin/Float =..., kotlin/Float =..., #A? =...): androidx.compose.animation.core/SpringSpec<#A> // androidx.compose.animation.core/spring|spring(kotlin.Float;kotlin.Float;0:0?){0§<kotlin.Any?>}[0]
+final fun <#A: kotlin/Any?> androidx.compose.animation.core/tween(kotlin/Int =..., kotlin/Int =..., androidx.compose.animation.core/Easing =...): androidx.compose.animation.core/TweenSpec<#A> // androidx.compose.animation.core/tween|tween(kotlin.Int;kotlin.Int;androidx.compose.animation.core.Easing){0§<kotlin.Any?>}[0]
+final fun <#A: kotlin/Any?> androidx.compose.animation.core/updateTransition(#A, kotlin/String? =...): androidx.compose.animation.core/Transition<#A> // androidx.compose.animation.core/updateTransition|updateTransition(0:0;kotlin.String?){0§<kotlin.Any?>}[0]
+final fun <#A: kotlin/Any?> androidx.compose.animation.core/updateTransition(androidx.compose.animation.core/MutableTransitionState<#A>, kotlin/String? =...): androidx.compose.animation.core/Transition<#A> // androidx.compose.animation.core/updateTransition|updateTransition(androidx.compose.animation.core.MutableTransitionState<0:0>;kotlin.String?){0§<kotlin.Any?>}[0]
+final fun androidx.compose.animation.core/Animatable(kotlin/Float, kotlin/Float =...): androidx.compose.animation.core/Animatable<kotlin/Float, androidx.compose.animation.core/AnimationVector1D> // androidx.compose.animation.core/Animatable|Animatable(kotlin.Float;kotlin.Float){}[0]
+final fun androidx.compose.animation.core/AnimationState(kotlin/Float, kotlin/Float =..., kotlin/Long =..., kotlin/Long =..., kotlin/Boolean =...): androidx.compose.animation.core/AnimationState<kotlin/Float, androidx.compose.animation.core/AnimationVector1D> // androidx.compose.animation.core/AnimationState|AnimationState(kotlin.Float;kotlin.Float;kotlin.Long;kotlin.Long;kotlin.Boolean){}[0]
+final fun androidx.compose.animation.core/AnimationVector(kotlin/Float): androidx.compose.animation.core/AnimationVector1D // androidx.compose.animation.core/AnimationVector|AnimationVector(kotlin.Float){}[0]
+final fun androidx.compose.animation.core/AnimationVector(kotlin/Float, kotlin/Float): androidx.compose.animation.core/AnimationVector2D // androidx.compose.animation.core/AnimationVector|AnimationVector(kotlin.Float;kotlin.Float){}[0]
+final fun androidx.compose.animation.core/AnimationVector(kotlin/Float, kotlin/Float, kotlin/Float): androidx.compose.animation.core/AnimationVector3D // androidx.compose.animation.core/AnimationVector|AnimationVector(kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+final fun androidx.compose.animation.core/AnimationVector(kotlin/Float, kotlin/Float, kotlin/Float, kotlin/Float): androidx.compose.animation.core/AnimationVector4D // androidx.compose.animation.core/AnimationVector|AnimationVector(kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+final fun androidx.compose.animation.core/DecayAnimation(androidx.compose.animation.core/FloatDecayAnimationSpec, kotlin/Float, kotlin/Float =...): androidx.compose.animation.core/DecayAnimation<kotlin/Float, androidx.compose.animation.core/AnimationVector1D> // androidx.compose.animation.core/DecayAnimation|DecayAnimation(androidx.compose.animation.core.FloatDecayAnimationSpec;kotlin.Float;kotlin.Float){}[0]
+final fun androidx.compose.animation.core/animateDpAsState(androidx.compose.ui.unit/Dp, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.unit/Dp> =..., kotlin/Function1<androidx.compose.ui.unit/Dp, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.unit/Dp> // androidx.compose.animation.core/animateDpAsState|animateDpAsState(androidx.compose.ui.unit.Dp;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp>;kotlin.Function1<androidx.compose.ui.unit.Dp,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateDpAsState(androidx.compose.ui.unit/Dp, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.unit/Dp> =..., kotlin/String =..., kotlin/Function1<androidx.compose.ui.unit/Dp, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.unit/Dp> // androidx.compose.animation.core/animateDpAsState|animateDpAsState(androidx.compose.ui.unit.Dp;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.Dp>;kotlin.String;kotlin.Function1<androidx.compose.ui.unit.Dp,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateFloatAsState(kotlin/Float, androidx.compose.animation.core/AnimationSpec<kotlin/Float> =..., kotlin/Float =..., kotlin/Function1<kotlin/Float, kotlin/Unit>? =...): androidx.compose.runtime/State<kotlin/Float> // androidx.compose.animation.core/animateFloatAsState|animateFloatAsState(kotlin.Float;androidx.compose.animation.core.AnimationSpec<kotlin.Float>;kotlin.Float;kotlin.Function1<kotlin.Float,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateFloatAsState(kotlin/Float, androidx.compose.animation.core/AnimationSpec<kotlin/Float> =..., kotlin/Float =..., kotlin/String =..., kotlin/Function1<kotlin/Float, kotlin/Unit>? =...): androidx.compose.runtime/State<kotlin/Float> // androidx.compose.animation.core/animateFloatAsState|animateFloatAsState(kotlin.Float;androidx.compose.animation.core.AnimationSpec<kotlin.Float>;kotlin.Float;kotlin.String;kotlin.Function1<kotlin.Float,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateIntAsState(kotlin/Int, androidx.compose.animation.core/AnimationSpec<kotlin/Int> =..., kotlin/Function1<kotlin/Int, kotlin/Unit>? =...): androidx.compose.runtime/State<kotlin/Int> // androidx.compose.animation.core/animateIntAsState|animateIntAsState(kotlin.Int;androidx.compose.animation.core.AnimationSpec<kotlin.Int>;kotlin.Function1<kotlin.Int,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateIntAsState(kotlin/Int, androidx.compose.animation.core/AnimationSpec<kotlin/Int> =..., kotlin/String =..., kotlin/Function1<kotlin/Int, kotlin/Unit>? =...): androidx.compose.runtime/State<kotlin/Int> // androidx.compose.animation.core/animateIntAsState|animateIntAsState(kotlin.Int;androidx.compose.animation.core.AnimationSpec<kotlin.Int>;kotlin.String;kotlin.Function1<kotlin.Int,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateIntOffsetAsState(androidx.compose.ui.unit/IntOffset, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.unit/IntOffset> =..., kotlin/Function1<androidx.compose.ui.unit/IntOffset, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.unit/IntOffset> // androidx.compose.animation.core/animateIntOffsetAsState|animateIntOffsetAsState(androidx.compose.ui.unit.IntOffset;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset>;kotlin.Function1<androidx.compose.ui.unit.IntOffset,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateIntOffsetAsState(androidx.compose.ui.unit/IntOffset, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.unit/IntOffset> =..., kotlin/String =..., kotlin/Function1<androidx.compose.ui.unit/IntOffset, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.unit/IntOffset> // androidx.compose.animation.core/animateIntOffsetAsState|animateIntOffsetAsState(androidx.compose.ui.unit.IntOffset;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntOffset>;kotlin.String;kotlin.Function1<androidx.compose.ui.unit.IntOffset,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateIntSizeAsState(androidx.compose.ui.unit/IntSize, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.unit/IntSize> =..., kotlin/Function1<androidx.compose.ui.unit/IntSize, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.unit/IntSize> // androidx.compose.animation.core/animateIntSizeAsState|animateIntSizeAsState(androidx.compose.ui.unit.IntSize;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize>;kotlin.Function1<androidx.compose.ui.unit.IntSize,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateIntSizeAsState(androidx.compose.ui.unit/IntSize, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.unit/IntSize> =..., kotlin/String =..., kotlin/Function1<androidx.compose.ui.unit/IntSize, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.unit/IntSize> // androidx.compose.animation.core/animateIntSizeAsState|animateIntSizeAsState(androidx.compose.ui.unit.IntSize;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.unit.IntSize>;kotlin.String;kotlin.Function1<androidx.compose.ui.unit.IntSize,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateOffsetAsState(androidx.compose.ui.geometry/Offset, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.geometry/Offset> =..., kotlin/Function1<androidx.compose.ui.geometry/Offset, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.geometry/Offset> // androidx.compose.animation.core/animateOffsetAsState|animateOffsetAsState(androidx.compose.ui.geometry.Offset;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset>;kotlin.Function1<androidx.compose.ui.geometry.Offset,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateOffsetAsState(androidx.compose.ui.geometry/Offset, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.geometry/Offset> =..., kotlin/String =..., kotlin/Function1<androidx.compose.ui.geometry/Offset, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.geometry/Offset> // androidx.compose.animation.core/animateOffsetAsState|animateOffsetAsState(androidx.compose.ui.geometry.Offset;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Offset>;kotlin.String;kotlin.Function1<androidx.compose.ui.geometry.Offset,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateRectAsState(androidx.compose.ui.geometry/Rect, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.geometry/Rect> =..., kotlin/Function1<androidx.compose.ui.geometry/Rect, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.geometry/Rect> // androidx.compose.animation.core/animateRectAsState|animateRectAsState(androidx.compose.ui.geometry.Rect;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect>;kotlin.Function1<androidx.compose.ui.geometry.Rect,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateRectAsState(androidx.compose.ui.geometry/Rect, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.geometry/Rect> =..., kotlin/String =..., kotlin/Function1<androidx.compose.ui.geometry/Rect, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.geometry/Rect> // androidx.compose.animation.core/animateRectAsState|animateRectAsState(androidx.compose.ui.geometry.Rect;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Rect>;kotlin.String;kotlin.Function1<androidx.compose.ui.geometry.Rect,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateSizeAsState(androidx.compose.ui.geometry/Size, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.geometry/Size> =..., kotlin/Function1<androidx.compose.ui.geometry/Size, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.geometry/Size> // androidx.compose.animation.core/animateSizeAsState|animateSizeAsState(androidx.compose.ui.geometry.Size;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size>;kotlin.Function1<androidx.compose.ui.geometry.Size,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/animateSizeAsState(androidx.compose.ui.geometry/Size, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.geometry/Size> =..., kotlin/String =..., kotlin/Function1<androidx.compose.ui.geometry/Size, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.geometry/Size> // androidx.compose.animation.core/animateSizeAsState|animateSizeAsState(androidx.compose.ui.geometry.Size;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.geometry.Size>;kotlin.String;kotlin.Function1<androidx.compose.ui.geometry.Size,kotlin.Unit>?){}[0]
+final fun androidx.compose.animation.core/estimateAnimationDurationMillis(kotlin/Double, kotlin/Double, kotlin/Double, kotlin/Double, kotlin/Double): kotlin/Long // androidx.compose.animation.core/estimateAnimationDurationMillis|estimateAnimationDurationMillis(kotlin.Double;kotlin.Double;kotlin.Double;kotlin.Double;kotlin.Double){}[0]
+final fun androidx.compose.animation.core/estimateAnimationDurationMillis(kotlin/Double, kotlin/Double, kotlin/Double, kotlin/Double, kotlin/Double, kotlin/Double): kotlin/Long // androidx.compose.animation.core/estimateAnimationDurationMillis|estimateAnimationDurationMillis(kotlin.Double;kotlin.Double;kotlin.Double;kotlin.Double;kotlin.Double;kotlin.Double){}[0]
+final fun androidx.compose.animation.core/estimateAnimationDurationMillis(kotlin/Float, kotlin/Float, kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Long // androidx.compose.animation.core/estimateAnimationDurationMillis|estimateAnimationDurationMillis(kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+final fun androidx.compose.animation.core/rememberInfiniteTransition(): androidx.compose.animation.core/InfiniteTransition // androidx.compose.animation.core/rememberInfiniteTransition|rememberInfiniteTransition(){}[0]
+final fun androidx.compose.animation.core/rememberInfiniteTransition(kotlin/String =...): androidx.compose.animation.core/InfiniteTransition // androidx.compose.animation.core/rememberInfiniteTransition|rememberInfiniteTransition(kotlin.String){}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: androidx.compose.animation.core/AnimationVector> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation.core/animateValue(androidx.compose.animation.core/TwoWayConverter<#B, #C>, noinline kotlin/Function1<androidx.compose.animation.core/Transition.Segment<#A>, androidx.compose.animation.core/FiniteAnimationSpec<#B>> =..., kotlin/String =..., kotlin/Function1<#A, #B>): androidx.compose.runtime/State<#B> // androidx.compose.animation.core/animateValue|[email protected]<0:0>(androidx.compose.animation.core.TwoWayConverter<0:1,0:2>;kotlin.Function1<androidx.compose.animation.core.Transition.Segment<0:0>,androidx.compose.animation.core.FiniteAnimationSpec<0:1>>;kotlin.String;kotlin.Function1<0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<androidx.compose.animation.core.AnimationVector>}[0]
+final inline fun <#A: kotlin/Any?> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation.core/animateDp(noinline kotlin/Function1<androidx.compose.animation.core/Transition.Segment<#A>, androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/Dp>> =..., kotlin/String =..., kotlin/Function1<#A, androidx.compose.ui.unit/Dp>): androidx.compose.runtime/State<androidx.compose.ui.unit/Dp> // androidx.compose.animation.core/animateDp|[email protected]<0:0>(kotlin.Function1<androidx.compose.animation.core.Transition.Segment<0:0>,androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.Dp>>;kotlin.String;kotlin.Function1<0:0,androidx.compose.ui.unit.Dp>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation.core/animateFloat(noinline kotlin/Function1<androidx.compose.animation.core/Transition.Segment<#A>, androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float>> =..., kotlin/String =..., kotlin/Function1<#A, kotlin/Float>): androidx.compose.runtime/State<kotlin/Float> // androidx.compose.animation.core/animateFloat|[email protected]<0:0>(kotlin.Function1<androidx.compose.animation.core.Transition.Segment<0:0>,androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>>;kotlin.String;kotlin.Function1<0:0,kotlin.Float>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation.core/animateInt(noinline kotlin/Function1<androidx.compose.animation.core/Transition.Segment<#A>, androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Int>> =..., kotlin/String =..., kotlin/Function1<#A, kotlin/Int>): androidx.compose.runtime/State<kotlin/Int> // androidx.compose.animation.core/animateInt|[email protected]<0:0>(kotlin.Function1<androidx.compose.animation.core.Transition.Segment<0:0>,androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Int>>;kotlin.String;kotlin.Function1<0:0,kotlin.Int>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation.core/animateIntOffset(noinline kotlin/Function1<androidx.compose.animation.core/Transition.Segment<#A>, androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntOffset>> =..., kotlin/String =..., kotlin/Function1<#A, androidx.compose.ui.unit/IntOffset>): androidx.compose.runtime/State<androidx.compose.ui.unit/IntOffset> // androidx.compose.animation.core/animateIntOffset|[email protected]<0:0>(kotlin.Function1<androidx.compose.animation.core.Transition.Segment<0:0>,androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>>;kotlin.String;kotlin.Function1<0:0,androidx.compose.ui.unit.IntOffset>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation.core/animateIntSize(noinline kotlin/Function1<androidx.compose.animation.core/Transition.Segment<#A>, androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntSize>> =..., kotlin/String =..., kotlin/Function1<#A, androidx.compose.ui.unit/IntSize>): androidx.compose.runtime/State<androidx.compose.ui.unit/IntSize> // androidx.compose.animation.core/animateIntSize|[email protected]<0:0>(kotlin.Function1<androidx.compose.animation.core.Transition.Segment<0:0>,androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize>>;kotlin.String;kotlin.Function1<0:0,androidx.compose.ui.unit.IntSize>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation.core/animateOffset(noinline kotlin/Function1<androidx.compose.animation.core/Transition.Segment<#A>, androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.geometry/Offset>> =..., kotlin/String =..., kotlin/Function1<#A, androidx.compose.ui.geometry/Offset>): androidx.compose.runtime/State<androidx.compose.ui.geometry/Offset> // androidx.compose.animation.core/animateOffset|[email protected]<0:0>(kotlin.Function1<androidx.compose.animation.core.Transition.Segment<0:0>,androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.geometry.Offset>>;kotlin.String;kotlin.Function1<0:0,androidx.compose.ui.geometry.Offset>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation.core/animateRect(noinline kotlin/Function1<androidx.compose.animation.core/Transition.Segment<#A>, androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.geometry/Rect>> =..., kotlin/String =..., kotlin/Function1<#A, androidx.compose.ui.geometry/Rect>): androidx.compose.runtime/State<androidx.compose.ui.geometry/Rect> // androidx.compose.animation.core/animateRect|[email protected]<0:0>(kotlin.Function1<androidx.compose.animation.core.Transition.Segment<0:0>,androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.geometry.Rect>>;kotlin.String;kotlin.Function1<0:0,androidx.compose.ui.geometry.Rect>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation.core/animateSize(noinline kotlin/Function1<androidx.compose.animation.core/Transition.Segment<#A>, androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.geometry/Size>> =..., kotlin/String =..., kotlin/Function1<#A, androidx.compose.ui.geometry/Size>): androidx.compose.runtime/State<androidx.compose.ui.geometry/Size> // androidx.compose.animation.core/animateSize|[email protected]<0:0>(kotlin.Function1<androidx.compose.animation.core.Transition.Segment<0:0>,androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.geometry.Size>>;kotlin.String;kotlin.Function1<0:0,androidx.compose.ui.geometry.Size>){0§<kotlin.Any?>}[0]
+final object androidx.compose.animation.core/AnimationConstants { // androidx.compose.animation.core/AnimationConstants|null[0]
+    final const val DefaultDurationMillis // androidx.compose.animation.core/AnimationConstants.DefaultDurationMillis|{}DefaultDurationMillis[0]
+        final fun <get-DefaultDurationMillis>(): kotlin/Int // androidx.compose.animation.core/AnimationConstants.DefaultDurationMillis.<get-DefaultDurationMillis>|<get-DefaultDurationMillis>(){}[0]
+    final const val UnspecifiedTime // androidx.compose.animation.core/AnimationConstants.UnspecifiedTime|{}UnspecifiedTime[0]
+        final fun <get-UnspecifiedTime>(): kotlin/Long // androidx.compose.animation.core/AnimationConstants.UnspecifiedTime.<get-UnspecifiedTime>|<get-UnspecifiedTime>(){}[0]
+}
+final object androidx.compose.animation.core/Spring { // androidx.compose.animation.core/Spring|null[0]
+    final const val DampingRatioHighBouncy // androidx.compose.animation.core/Spring.DampingRatioHighBouncy|{}DampingRatioHighBouncy[0]
+        final fun <get-DampingRatioHighBouncy>(): kotlin/Float // androidx.compose.animation.core/Spring.DampingRatioHighBouncy.<get-DampingRatioHighBouncy>|<get-DampingRatioHighBouncy>(){}[0]
+    final const val DampingRatioLowBouncy // androidx.compose.animation.core/Spring.DampingRatioLowBouncy|{}DampingRatioLowBouncy[0]
+        final fun <get-DampingRatioLowBouncy>(): kotlin/Float // androidx.compose.animation.core/Spring.DampingRatioLowBouncy.<get-DampingRatioLowBouncy>|<get-DampingRatioLowBouncy>(){}[0]
+    final const val DampingRatioMediumBouncy // androidx.compose.animation.core/Spring.DampingRatioMediumBouncy|{}DampingRatioMediumBouncy[0]
+        final fun <get-DampingRatioMediumBouncy>(): kotlin/Float // androidx.compose.animation.core/Spring.DampingRatioMediumBouncy.<get-DampingRatioMediumBouncy>|<get-DampingRatioMediumBouncy>(){}[0]
+    final const val DampingRatioNoBouncy // androidx.compose.animation.core/Spring.DampingRatioNoBouncy|{}DampingRatioNoBouncy[0]
+        final fun <get-DampingRatioNoBouncy>(): kotlin/Float // androidx.compose.animation.core/Spring.DampingRatioNoBouncy.<get-DampingRatioNoBouncy>|<get-DampingRatioNoBouncy>(){}[0]
+    final const val DefaultDisplacementThreshold // androidx.compose.animation.core/Spring.DefaultDisplacementThreshold|{}DefaultDisplacementThreshold[0]
+        final fun <get-DefaultDisplacementThreshold>(): kotlin/Float // androidx.compose.animation.core/Spring.DefaultDisplacementThreshold.<get-DefaultDisplacementThreshold>|<get-DefaultDisplacementThreshold>(){}[0]
+    final const val StiffnessHigh // androidx.compose.animation.core/Spring.StiffnessHigh|{}StiffnessHigh[0]
+        final fun <get-StiffnessHigh>(): kotlin/Float // androidx.compose.animation.core/Spring.StiffnessHigh.<get-StiffnessHigh>|<get-StiffnessHigh>(){}[0]
+    final const val StiffnessLow // androidx.compose.animation.core/Spring.StiffnessLow|{}StiffnessLow[0]
+        final fun <get-StiffnessLow>(): kotlin/Float // androidx.compose.animation.core/Spring.StiffnessLow.<get-StiffnessLow>|<get-StiffnessLow>(){}[0]
+    final const val StiffnessMedium // androidx.compose.animation.core/Spring.StiffnessMedium|{}StiffnessMedium[0]
+        final fun <get-StiffnessMedium>(): kotlin/Float // androidx.compose.animation.core/Spring.StiffnessMedium.<get-StiffnessMedium>|<get-StiffnessMedium>(){}[0]
+    final const val StiffnessMediumLow // androidx.compose.animation.core/Spring.StiffnessMediumLow|{}StiffnessMediumLow[0]
+        final fun <get-StiffnessMediumLow>(): kotlin/Float // androidx.compose.animation.core/Spring.StiffnessMediumLow.<get-StiffnessMediumLow>|<get-StiffnessMediumLow>(){}[0]
+    final const val StiffnessVeryLow // androidx.compose.animation.core/Spring.StiffnessVeryLow|{}StiffnessVeryLow[0]
+        final fun <get-StiffnessVeryLow>(): kotlin/Float // androidx.compose.animation.core/Spring.StiffnessVeryLow.<get-StiffnessVeryLow>|<get-StiffnessVeryLow>(){}[0]
+}
+final suspend fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> (androidx.compose.animation.core/AnimationState<#A, #B>).androidx.compose.animation.core/animateDecay(androidx.compose.animation.core/DecayAnimationSpec<#A>, kotlin/Boolean =..., kotlin/Function1<androidx.compose.animation.core/AnimationScope<#A, #B>, kotlin/Unit> =...) // androidx.compose.animation.core/animateDecay|[email protected]<0:0,0:1>(androidx.compose.animation.core.DecayAnimationSpec<0:0>;kotlin.Boolean;kotlin.Function1<androidx.compose.animation.core.AnimationScope<0:0,0:1>,kotlin.Unit>){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final suspend fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> (androidx.compose.animation.core/AnimationState<#A, #B>).androidx.compose.animation.core/animateTo(#A, androidx.compose.animation.core/AnimationSpec<#A> =..., kotlin/Boolean =..., kotlin/Function1<androidx.compose.animation.core/AnimationScope<#A, #B>, kotlin/Unit> =...) // androidx.compose.animation.core/animateTo|[email protected]<0:0,0:1>(0:0;androidx.compose.animation.core.AnimationSpec<0:0>;kotlin.Boolean;kotlin.Function1<androidx.compose.animation.core.AnimationScope<0:0,0:1>,kotlin.Unit>){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final suspend fun <#A: kotlin/Any?, #B: androidx.compose.animation.core/AnimationVector> androidx.compose.animation.core/animate(androidx.compose.animation.core/TwoWayConverter<#A, #B>, #A, #A, #A? =..., androidx.compose.animation.core/AnimationSpec<#A> =..., kotlin/Function2<#A, #A, kotlin/Unit>) // androidx.compose.animation.core/animate|animate(androidx.compose.animation.core.TwoWayConverter<0:0,0:1>;0:0;0:0;0:0?;androidx.compose.animation.core.AnimationSpec<0:0>;kotlin.Function2<0:0,0:0,kotlin.Unit>){0§<kotlin.Any?>;1§<androidx.compose.animation.core.AnimationVector>}[0]
+final suspend fun <#A: kotlin/Any?> androidx.compose.animation.core/withInfiniteAnimationFrameNanos(kotlin/Function1<kotlin/Long, #A>): #A // androidx.compose.animation.core/withInfiniteAnimationFrameNanos|withInfiniteAnimationFrameNanos(kotlin.Function1<kotlin.Long,0:0>){0§<kotlin.Any?>}[0]
+final suspend fun androidx.compose.animation.core/animate(kotlin/Float, kotlin/Float, kotlin/Float =..., androidx.compose.animation.core/AnimationSpec<kotlin/Float> =..., kotlin/Function2<kotlin/Float, kotlin/Float, kotlin/Unit>) // androidx.compose.animation.core/animate|animate(kotlin.Float;kotlin.Float;kotlin.Float;androidx.compose.animation.core.AnimationSpec<kotlin.Float>;kotlin.Function2<kotlin.Float,kotlin.Float,kotlin.Unit>){}[0]
+final suspend fun androidx.compose.animation.core/animateDecay(kotlin/Float, kotlin/Float, androidx.compose.animation.core/FloatDecayAnimationSpec, kotlin/Function2<kotlin/Float, kotlin/Float, kotlin/Unit>) // androidx.compose.animation.core/animateDecay|animateDecay(kotlin.Float;kotlin.Float;androidx.compose.animation.core.FloatDecayAnimationSpec;kotlin.Function2<kotlin.Float,kotlin.Float,kotlin.Unit>){}[0]
+final suspend inline fun <#A: kotlin/Any?> androidx.compose.animation.core/withInfiniteAnimationFrameMillis(crossinline kotlin/Function1<kotlin/Long, #A>): #A // androidx.compose.animation.core/withInfiniteAnimationFrameMillis|withInfiniteAnimationFrameMillis(kotlin.Function1<kotlin.Long,0:0>){0§<kotlin.Any?>}[0]
+final val androidx.compose.animation.core/Ease // androidx.compose.animation.core/Ease|{}Ease[0]
+    final fun <get-Ease>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/Ease.<get-Ease>|<get-Ease>(){}[0]
+final val androidx.compose.animation.core/EaseIn // androidx.compose.animation.core/EaseIn|{}EaseIn[0]
+    final fun <get-EaseIn>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseIn.<get-EaseIn>|<get-EaseIn>(){}[0]
+final val androidx.compose.animation.core/EaseInBack // androidx.compose.animation.core/EaseInBack|{}EaseInBack[0]
+    final fun <get-EaseInBack>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInBack.<get-EaseInBack>|<get-EaseInBack>(){}[0]
+final val androidx.compose.animation.core/EaseInBounce // androidx.compose.animation.core/EaseInBounce|{}EaseInBounce[0]
+    final fun <get-EaseInBounce>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInBounce.<get-EaseInBounce>|<get-EaseInBounce>(){}[0]
+final val androidx.compose.animation.core/EaseInCirc // androidx.compose.animation.core/EaseInCirc|{}EaseInCirc[0]
+    final fun <get-EaseInCirc>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInCirc.<get-EaseInCirc>|<get-EaseInCirc>(){}[0]
+final val androidx.compose.animation.core/EaseInCubic // androidx.compose.animation.core/EaseInCubic|{}EaseInCubic[0]
+    final fun <get-EaseInCubic>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInCubic.<get-EaseInCubic>|<get-EaseInCubic>(){}[0]
+final val androidx.compose.animation.core/EaseInElastic // androidx.compose.animation.core/EaseInElastic|{}EaseInElastic[0]
+    final fun <get-EaseInElastic>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInElastic.<get-EaseInElastic>|<get-EaseInElastic>(){}[0]
+final val androidx.compose.animation.core/EaseInExpo // androidx.compose.animation.core/EaseInExpo|{}EaseInExpo[0]
+    final fun <get-EaseInExpo>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInExpo.<get-EaseInExpo>|<get-EaseInExpo>(){}[0]
+final val androidx.compose.animation.core/EaseInOut // androidx.compose.animation.core/EaseInOut|{}EaseInOut[0]
+    final fun <get-EaseInOut>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInOut.<get-EaseInOut>|<get-EaseInOut>(){}[0]
+final val androidx.compose.animation.core/EaseInOutBack // androidx.compose.animation.core/EaseInOutBack|{}EaseInOutBack[0]
+    final fun <get-EaseInOutBack>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInOutBack.<get-EaseInOutBack>|<get-EaseInOutBack>(){}[0]
+final val androidx.compose.animation.core/EaseInOutBounce // androidx.compose.animation.core/EaseInOutBounce|{}EaseInOutBounce[0]
+    final fun <get-EaseInOutBounce>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInOutBounce.<get-EaseInOutBounce>|<get-EaseInOutBounce>(){}[0]
+final val androidx.compose.animation.core/EaseInOutCirc // androidx.compose.animation.core/EaseInOutCirc|{}EaseInOutCirc[0]
+    final fun <get-EaseInOutCirc>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInOutCirc.<get-EaseInOutCirc>|<get-EaseInOutCirc>(){}[0]
+final val androidx.compose.animation.core/EaseInOutCubic // androidx.compose.animation.core/EaseInOutCubic|{}EaseInOutCubic[0]
+    final fun <get-EaseInOutCubic>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInOutCubic.<get-EaseInOutCubic>|<get-EaseInOutCubic>(){}[0]
+final val androidx.compose.animation.core/EaseInOutElastic // androidx.compose.animation.core/EaseInOutElastic|{}EaseInOutElastic[0]
+    final fun <get-EaseInOutElastic>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInOutElastic.<get-EaseInOutElastic>|<get-EaseInOutElastic>(){}[0]
+final val androidx.compose.animation.core/EaseInOutExpo // androidx.compose.animation.core/EaseInOutExpo|{}EaseInOutExpo[0]
+    final fun <get-EaseInOutExpo>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInOutExpo.<get-EaseInOutExpo>|<get-EaseInOutExpo>(){}[0]
+final val androidx.compose.animation.core/EaseInOutQuad // androidx.compose.animation.core/EaseInOutQuad|{}EaseInOutQuad[0]
+    final fun <get-EaseInOutQuad>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInOutQuad.<get-EaseInOutQuad>|<get-EaseInOutQuad>(){}[0]
+final val androidx.compose.animation.core/EaseInOutQuart // androidx.compose.animation.core/EaseInOutQuart|{}EaseInOutQuart[0]
+    final fun <get-EaseInOutQuart>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInOutQuart.<get-EaseInOutQuart>|<get-EaseInOutQuart>(){}[0]
+final val androidx.compose.animation.core/EaseInOutQuint // androidx.compose.animation.core/EaseInOutQuint|{}EaseInOutQuint[0]
+    final fun <get-EaseInOutQuint>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInOutQuint.<get-EaseInOutQuint>|<get-EaseInOutQuint>(){}[0]
+final val androidx.compose.animation.core/EaseInOutSine // androidx.compose.animation.core/EaseInOutSine|{}EaseInOutSine[0]
+    final fun <get-EaseInOutSine>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInOutSine.<get-EaseInOutSine>|<get-EaseInOutSine>(){}[0]
+final val androidx.compose.animation.core/EaseInQuad // androidx.compose.animation.core/EaseInQuad|{}EaseInQuad[0]
+    final fun <get-EaseInQuad>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInQuad.<get-EaseInQuad>|<get-EaseInQuad>(){}[0]
+final val androidx.compose.animation.core/EaseInQuart // androidx.compose.animation.core/EaseInQuart|{}EaseInQuart[0]
+    final fun <get-EaseInQuart>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInQuart.<get-EaseInQuart>|<get-EaseInQuart>(){}[0]
+final val androidx.compose.animation.core/EaseInQuint // androidx.compose.animation.core/EaseInQuint|{}EaseInQuint[0]
+    final fun <get-EaseInQuint>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInQuint.<get-EaseInQuint>|<get-EaseInQuint>(){}[0]
+final val androidx.compose.animation.core/EaseInSine // androidx.compose.animation.core/EaseInSine|{}EaseInSine[0]
+    final fun <get-EaseInSine>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseInSine.<get-EaseInSine>|<get-EaseInSine>(){}[0]
+final val androidx.compose.animation.core/EaseOut // androidx.compose.animation.core/EaseOut|{}EaseOut[0]
+    final fun <get-EaseOut>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseOut.<get-EaseOut>|<get-EaseOut>(){}[0]
+final val androidx.compose.animation.core/EaseOutBack // androidx.compose.animation.core/EaseOutBack|{}EaseOutBack[0]
+    final fun <get-EaseOutBack>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseOutBack.<get-EaseOutBack>|<get-EaseOutBack>(){}[0]
+final val androidx.compose.animation.core/EaseOutBounce // androidx.compose.animation.core/EaseOutBounce|{}EaseOutBounce[0]
+    final fun <get-EaseOutBounce>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseOutBounce.<get-EaseOutBounce>|<get-EaseOutBounce>(){}[0]
+final val androidx.compose.animation.core/EaseOutCirc // androidx.compose.animation.core/EaseOutCirc|{}EaseOutCirc[0]
+    final fun <get-EaseOutCirc>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseOutCirc.<get-EaseOutCirc>|<get-EaseOutCirc>(){}[0]
+final val androidx.compose.animation.core/EaseOutCubic // androidx.compose.animation.core/EaseOutCubic|{}EaseOutCubic[0]
+    final fun <get-EaseOutCubic>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseOutCubic.<get-EaseOutCubic>|<get-EaseOutCubic>(){}[0]
+final val androidx.compose.animation.core/EaseOutElastic // androidx.compose.animation.core/EaseOutElastic|{}EaseOutElastic[0]
+    final fun <get-EaseOutElastic>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseOutElastic.<get-EaseOutElastic>|<get-EaseOutElastic>(){}[0]
+final val androidx.compose.animation.core/EaseOutExpo // androidx.compose.animation.core/EaseOutExpo|{}EaseOutExpo[0]
+    final fun <get-EaseOutExpo>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseOutExpo.<get-EaseOutExpo>|<get-EaseOutExpo>(){}[0]
+final val androidx.compose.animation.core/EaseOutQuad // androidx.compose.animation.core/EaseOutQuad|{}EaseOutQuad[0]
+    final fun <get-EaseOutQuad>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseOutQuad.<get-EaseOutQuad>|<get-EaseOutQuad>(){}[0]
+final val androidx.compose.animation.core/EaseOutQuart // androidx.compose.animation.core/EaseOutQuart|{}EaseOutQuart[0]
+    final fun <get-EaseOutQuart>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseOutQuart.<get-EaseOutQuart>|<get-EaseOutQuart>(){}[0]
+final val androidx.compose.animation.core/EaseOutQuint // androidx.compose.animation.core/EaseOutQuint|{}EaseOutQuint[0]
+    final fun <get-EaseOutQuint>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseOutQuint.<get-EaseOutQuint>|<get-EaseOutQuint>(){}[0]
+final val androidx.compose.animation.core/EaseOutSine // androidx.compose.animation.core/EaseOutSine|{}EaseOutSine[0]
+    final fun <get-EaseOutSine>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/EaseOutSine.<get-EaseOutSine>|<get-EaseOutSine>(){}[0]
+final val androidx.compose.animation.core/FastOutLinearInEasing // androidx.compose.animation.core/FastOutLinearInEasing|{}FastOutLinearInEasing[0]
+    final fun <get-FastOutLinearInEasing>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/FastOutLinearInEasing.<get-FastOutLinearInEasing>|<get-FastOutLinearInEasing>(){}[0]
+final val androidx.compose.animation.core/FastOutSlowInEasing // androidx.compose.animation.core/FastOutSlowInEasing|{}FastOutSlowInEasing[0]
+    final fun <get-FastOutSlowInEasing>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/FastOutSlowInEasing.<get-FastOutSlowInEasing>|<get-FastOutSlowInEasing>(){}[0]
+final val androidx.compose.animation.core/LinearEasing // androidx.compose.animation.core/LinearEasing|{}LinearEasing[0]
+    final fun <get-LinearEasing>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/LinearEasing.<get-LinearEasing>|<get-LinearEasing>(){}[0]
+final val androidx.compose.animation.core/LinearOutSlowInEasing // androidx.compose.animation.core/LinearOutSlowInEasing|{}LinearOutSlowInEasing[0]
+    final fun <get-LinearOutSlowInEasing>(): androidx.compose.animation.core/Easing // androidx.compose.animation.core/LinearOutSlowInEasing.<get-LinearOutSlowInEasing>|<get-LinearOutSlowInEasing>(){}[0]
+final val androidx.compose.animation.core/VectorConverter // androidx.compose.animation.core/VectorConverter|@androidx.compose.ui.geometry.Offset.Companion{}VectorConverter[0]
+    final fun (androidx.compose.ui.geometry/Offset.Companion).<get-VectorConverter>(): androidx.compose.animation.core/TwoWayConverter<androidx.compose.ui.geometry/Offset, androidx.compose.animation.core/AnimationVector2D> // androidx.compose.animation.core/VectorConverter.<get-VectorConverter>|<get-VectorConverter>@androidx.compose.ui.geometry.Offset.Companion(){}[0]
+final val androidx.compose.animation.core/VectorConverter // androidx.compose.animation.core/VectorConverter|@androidx.compose.ui.geometry.Rect.Companion{}VectorConverter[0]
+    final fun (androidx.compose.ui.geometry/Rect.Companion).<get-VectorConverter>(): androidx.compose.animation.core/TwoWayConverter<androidx.compose.ui.geometry/Rect, androidx.compose.animation.core/AnimationVector4D> // androidx.compose.animation.core/VectorConverter.<get-VectorConverter>|<get-VectorConverter>@androidx.compose.ui.geometry.Rect.Companion(){}[0]
+final val androidx.compose.animation.core/VectorConverter // androidx.compose.animation.core/VectorConverter|@androidx.compose.ui.geometry.Size.Companion{}VectorConverter[0]
+    final fun (androidx.compose.ui.geometry/Size.Companion).<get-VectorConverter>(): androidx.compose.animation.core/TwoWayConverter<androidx.compose.ui.geometry/Size, androidx.compose.animation.core/AnimationVector2D> // androidx.compose.animation.core/VectorConverter.<get-VectorConverter>|<get-VectorConverter>@androidx.compose.ui.geometry.Size.Companion(){}[0]
+final val androidx.compose.animation.core/VectorConverter // androidx.compose.animation.core/VectorConverter|@androidx.compose.ui.unit.Dp.Companion{}VectorConverter[0]
+    final fun (androidx.compose.ui.unit/Dp.Companion).<get-VectorConverter>(): androidx.compose.animation.core/TwoWayConverter<androidx.compose.ui.unit/Dp, androidx.compose.animation.core/AnimationVector1D> // androidx.compose.animation.core/VectorConverter.<get-VectorConverter>|<get-VectorConverter>@androidx.compose.ui.unit.Dp.Companion(){}[0]
+final val androidx.compose.animation.core/VectorConverter // androidx.compose.animation.core/VectorConverter|@androidx.compose.ui.unit.DpOffset.Companion{}VectorConverter[0]
+    final fun (androidx.compose.ui.unit/DpOffset.Companion).<get-VectorConverter>(): androidx.compose.animation.core/TwoWayConverter<androidx.compose.ui.unit/DpOffset, androidx.compose.animation.core/AnimationVector2D> // androidx.compose.animation.core/VectorConverter.<get-VectorConverter>|<get-VectorConverter>@androidx.compose.ui.unit.DpOffset.Companion(){}[0]
+final val androidx.compose.animation.core/VectorConverter // androidx.compose.animation.core/VectorConverter|@androidx.compose.ui.unit.IntOffset.Companion{}VectorConverter[0]
+    final fun (androidx.compose.ui.unit/IntOffset.Companion).<get-VectorConverter>(): androidx.compose.animation.core/TwoWayConverter<androidx.compose.ui.unit/IntOffset, androidx.compose.animation.core/AnimationVector2D> // androidx.compose.animation.core/VectorConverter.<get-VectorConverter>|<get-VectorConverter>@androidx.compose.ui.unit.IntOffset.Companion(){}[0]
+final val androidx.compose.animation.core/VectorConverter // androidx.compose.animation.core/VectorConverter|@androidx.compose.ui.unit.IntSize.Companion{}VectorConverter[0]
+    final fun (androidx.compose.ui.unit/IntSize.Companion).<get-VectorConverter>(): androidx.compose.animation.core/TwoWayConverter<androidx.compose.ui.unit/IntSize, androidx.compose.animation.core/AnimationVector2D> // androidx.compose.animation.core/VectorConverter.<get-VectorConverter>|<get-VectorConverter>@androidx.compose.ui.unit.IntSize.Companion(){}[0]
+final val androidx.compose.animation.core/VectorConverter // androidx.compose.animation.core/VectorConverter|@kotlin.Float.Companion{}VectorConverter[0]
+    final fun (kotlin/Float.Companion).<get-VectorConverter>(): androidx.compose.animation.core/TwoWayConverter<kotlin/Float, androidx.compose.animation.core/AnimationVector1D> // androidx.compose.animation.core/VectorConverter.<get-VectorConverter>|<get-VectorConverter>@kotlin.Float.Companion(){}[0]
+final val androidx.compose.animation.core/VectorConverter // androidx.compose.animation.core/VectorConverter|@kotlin.Int.Companion{}VectorConverter[0]
+    final fun (kotlin/Int.Companion).<get-VectorConverter>(): androidx.compose.animation.core/TwoWayConverter<kotlin/Int, androidx.compose.animation.core/AnimationVector1D> // androidx.compose.animation.core/VectorConverter.<get-VectorConverter>|<get-VectorConverter>@kotlin.Int.Companion(){}[0]
+final val androidx.compose.animation.core/VisibilityThreshold // androidx.compose.animation.core/VisibilityThreshold|@androidx.compose.ui.geometry.Offset.Companion{}VisibilityThreshold[0]
+    final fun (androidx.compose.ui.geometry/Offset.Companion).<get-VisibilityThreshold>(): androidx.compose.ui.geometry/Offset // androidx.compose.animation.core/VisibilityThreshold.<get-VisibilityThreshold>|<get-VisibilityThreshold>@androidx.compose.ui.geometry.Offset.Companion(){}[0]
+final val androidx.compose.animation.core/VisibilityThreshold // androidx.compose.animation.core/VisibilityThreshold|@androidx.compose.ui.geometry.Rect.Companion{}VisibilityThreshold[0]
+    final fun (androidx.compose.ui.geometry/Rect.Companion).<get-VisibilityThreshold>(): androidx.compose.ui.geometry/Rect // androidx.compose.animation.core/VisibilityThreshold.<get-VisibilityThreshold>|<get-VisibilityThreshold>@androidx.compose.ui.geometry.Rect.Companion(){}[0]
+final val androidx.compose.animation.core/VisibilityThreshold // androidx.compose.animation.core/VisibilityThreshold|@androidx.compose.ui.geometry.Size.Companion{}VisibilityThreshold[0]
+    final fun (androidx.compose.ui.geometry/Size.Companion).<get-VisibilityThreshold>(): androidx.compose.ui.geometry/Size // androidx.compose.animation.core/VisibilityThreshold.<get-VisibilityThreshold>|<get-VisibilityThreshold>@androidx.compose.ui.geometry.Size.Companion(){}[0]
+final val androidx.compose.animation.core/VisibilityThreshold // androidx.compose.animation.core/VisibilityThreshold|@androidx.compose.ui.unit.Dp.Companion{}VisibilityThreshold[0]
+    final fun (androidx.compose.ui.unit/Dp.Companion).<get-VisibilityThreshold>(): androidx.compose.ui.unit/Dp // androidx.compose.animation.core/VisibilityThreshold.<get-VisibilityThreshold>|<get-VisibilityThreshold>@androidx.compose.ui.unit.Dp.Companion(){}[0]
+final val androidx.compose.animation.core/VisibilityThreshold // androidx.compose.animation.core/VisibilityThreshold|@androidx.compose.ui.unit.DpOffset.Companion{}VisibilityThreshold[0]
+    final fun (androidx.compose.ui.unit/DpOffset.Companion).<get-VisibilityThreshold>(): androidx.compose.ui.unit/DpOffset // androidx.compose.animation.core/VisibilityThreshold.<get-VisibilityThreshold>|<get-VisibilityThreshold>@androidx.compose.ui.unit.DpOffset.Companion(){}[0]
+final val androidx.compose.animation.core/VisibilityThreshold // androidx.compose.animation.core/VisibilityThreshold|@androidx.compose.ui.unit.IntOffset.Companion{}VisibilityThreshold[0]
+    final fun (androidx.compose.ui.unit/IntOffset.Companion).<get-VisibilityThreshold>(): androidx.compose.ui.unit/IntOffset // androidx.compose.animation.core/VisibilityThreshold.<get-VisibilityThreshold>|<get-VisibilityThreshold>@androidx.compose.ui.unit.IntOffset.Companion(){}[0]
+final val androidx.compose.animation.core/VisibilityThreshold // androidx.compose.animation.core/VisibilityThreshold|@androidx.compose.ui.unit.IntSize.Companion{}VisibilityThreshold[0]
+    final fun (androidx.compose.ui.unit/IntSize.Companion).<get-VisibilityThreshold>(): androidx.compose.ui.unit/IntSize // androidx.compose.animation.core/VisibilityThreshold.<get-VisibilityThreshold>|<get-VisibilityThreshold>@androidx.compose.ui.unit.IntSize.Companion(){}[0]
+final val androidx.compose.animation.core/VisibilityThreshold // androidx.compose.animation.core/VisibilityThreshold|@kotlin.Int.Companion{}VisibilityThreshold[0]
+    final fun (kotlin/Int.Companion).<get-VisibilityThreshold>(): kotlin/Int // androidx.compose.animation.core/VisibilityThreshold.<get-VisibilityThreshold>|<get-VisibilityThreshold>@kotlin.Int.Companion(){}[0]
+final val androidx.compose.animation.core/isFinished // androidx.compose.animation.core/isFinished|@androidx.compose.animation.core.AnimationState<*,*>{}isFinished[0]
+    final fun (androidx.compose.animation.core/AnimationState<*, *>).<get-isFinished>(): kotlin/Boolean // androidx.compose.animation.core/isFinished.<get-isFinished>|<get-isFinished>@androidx.compose.animation.core.AnimationState<*,*>(){}[0]
+final value class androidx.compose.animation.core/StartOffset { // androidx.compose.animation.core/StartOffset|null[0]
+    constructor <init>(kotlin/Int, androidx.compose.animation.core/StartOffsetType =...) // androidx.compose.animation.core/StartOffset.<init>|<init>(kotlin.Int;androidx.compose.animation.core.StartOffsetType){}[0]
+    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.animation.core/StartOffset.equals|equals(kotlin.Any?){}[0]
+    final fun hashCode(): kotlin/Int // androidx.compose.animation.core/StartOffset.hashCode|hashCode(){}[0]
+    final fun toString(): kotlin/String // androidx.compose.animation.core/StartOffset.toString|toString(){}[0]
+    final val offsetMillis // androidx.compose.animation.core/StartOffset.offsetMillis|{}offsetMillis[0]
+        final fun <get-offsetMillis>(): kotlin/Int // androidx.compose.animation.core/StartOffset.offsetMillis.<get-offsetMillis>|<get-offsetMillis>(){}[0]
+    final val offsetType // androidx.compose.animation.core/StartOffset.offsetType|{}offsetType[0]
+        final fun <get-offsetType>(): androidx.compose.animation.core/StartOffsetType // androidx.compose.animation.core/StartOffset.offsetType.<get-offsetType>|<get-offsetType>(){}[0]
+}
+final value class androidx.compose.animation.core/StartOffsetType { // androidx.compose.animation.core/StartOffsetType|null[0]
+    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.animation.core/StartOffsetType.equals|equals(kotlin.Any?){}[0]
+    final fun hashCode(): kotlin/Int // androidx.compose.animation.core/StartOffsetType.hashCode|hashCode(){}[0]
+    final fun toString(): kotlin/String // androidx.compose.animation.core/StartOffsetType.toString|toString(){}[0]
+    final object Companion { // androidx.compose.animation.core/StartOffsetType.Companion|null[0]
+        final val Delay // androidx.compose.animation.core/StartOffsetType.Companion.Delay|{}Delay[0]
+            final fun <get-Delay>(): androidx.compose.animation.core/StartOffsetType // androidx.compose.animation.core/StartOffsetType.Companion.Delay.<get-Delay>|<get-Delay>(){}[0]
+        final val FastForward // androidx.compose.animation.core/StartOffsetType.Companion.FastForward|{}FastForward[0]
+            final fun <get-FastForward>(): androidx.compose.animation.core/StartOffsetType // androidx.compose.animation.core/StartOffsetType.Companion.FastForward.<get-FastForward>|<get-FastForward>(){}[0]
+    }
+}
+open annotation class androidx.compose.animation.core/ExperimentalAnimatableApi : kotlin/Annotation { // androidx.compose.animation.core/ExperimentalAnimatableApi|null[0]
+    constructor <init>() // androidx.compose.animation.core/ExperimentalAnimatableApi.<init>|<init>(){}[0]
+}
+open annotation class androidx.compose.animation.core/ExperimentalAnimationSpecApi : kotlin/Annotation { // androidx.compose.animation.core/ExperimentalAnimationSpecApi|null[0]
+    constructor <init>() // androidx.compose.animation.core/ExperimentalAnimationSpecApi.<init>|<init>(){}[0]
+}
+open annotation class androidx.compose.animation.core/ExperimentalTransitionApi : kotlin/Annotation { // androidx.compose.animation.core/ExperimentalTransitionApi|null[0]
+    constructor <init>() // androidx.compose.animation.core/ExperimentalTransitionApi.<init>|<init>(){}[0]
+}
+open annotation class androidx.compose.animation.core/InternalAnimationApi : kotlin/Annotation { // androidx.compose.animation.core/InternalAnimationApi|null[0]
+    constructor <init>() // androidx.compose.animation.core/InternalAnimationApi.<init>|<init>(){}[0]
+}
+sealed class <#A: kotlin/Any?, #B: androidx.compose.animation.core/KeyframeBaseEntity<#A>> androidx.compose.animation.core/KeyframesSpecBaseConfig { // androidx.compose.animation.core/KeyframesSpecBaseConfig|null[0]
+    constructor <init>() // androidx.compose.animation.core/KeyframesSpecBaseConfig.<init>|<init>(){}[0]
+    final fun (#B).using(androidx.compose.animation.core/Easing): #B // androidx.compose.animation.core/KeyframesSpecBaseConfig.using|using@1:1(androidx.compose.animation.core.Easing){}[0]
+    final var delayMillis // androidx.compose.animation.core/KeyframesSpecBaseConfig.delayMillis|{}delayMillis[0]
+        final fun <get-delayMillis>(): kotlin/Int // androidx.compose.animation.core/KeyframesSpecBaseConfig.delayMillis.<get-delayMillis>|<get-delayMillis>(){}[0]
+        final fun <set-delayMillis>(kotlin/Int) // androidx.compose.animation.core/KeyframesSpecBaseConfig.delayMillis.<set-delayMillis>|<set-delayMillis>(kotlin.Int){}[0]
+    final var durationMillis // androidx.compose.animation.core/KeyframesSpecBaseConfig.durationMillis|{}durationMillis[0]
+        final fun <get-durationMillis>(): kotlin/Int // androidx.compose.animation.core/KeyframesSpecBaseConfig.durationMillis.<get-durationMillis>|<get-durationMillis>(){}[0]
+        final fun <set-durationMillis>(kotlin/Int) // androidx.compose.animation.core/KeyframesSpecBaseConfig.durationMillis.<set-durationMillis>|<set-durationMillis>(kotlin.Int){}[0]
+    open fun (#A).at(kotlin/Int): #B // androidx.compose.animation.core/KeyframesSpecBaseConfig.at|at@1:0(kotlin.Int){}[0]
+    open fun (#A).atFraction(kotlin/Float): #B // androidx.compose.animation.core/KeyframesSpecBaseConfig.atFraction|atFraction@1:0(kotlin.Float){}[0]
+}
+sealed class <#A: kotlin/Any?> androidx.compose.animation.core/KeyframeBaseEntity { // androidx.compose.animation.core/KeyframeBaseEntity|null[0]
+    constructor <init>(#A, androidx.compose.animation.core/Easing) // androidx.compose.animation.core/KeyframeBaseEntity.<init>|<init>(1:0;androidx.compose.animation.core.Easing){}[0]
+}
+sealed class <#A: kotlin/Any?> androidx.compose.animation.core/TransitionState { // androidx.compose.animation.core/TransitionState|null[0]
+    abstract var currentState // androidx.compose.animation.core/TransitionState.currentState|{}currentState[0]
+        abstract fun <get-currentState>(): #A // androidx.compose.animation.core/TransitionState.currentState.<get-currentState>|<get-currentState>(){}[0]
+    abstract var targetState // androidx.compose.animation.core/TransitionState.targetState|{}targetState[0]
+        abstract fun <get-targetState>(): #A // androidx.compose.animation.core/TransitionState.targetState.<get-targetState>|<get-targetState>(){}[0]
+    constructor <init>() // androidx.compose.animation.core/TransitionState.<init>|<init>(){}[0]
+}
+sealed class androidx.compose.animation.core/AnimationVector { // androidx.compose.animation.core/AnimationVector|null[0]
+    constructor <init>() // androidx.compose.animation.core/AnimationVector.<init>|<init>(){}[0]
+}
diff --git a/compose/animation/animation-core/build.gradle b/compose/animation/animation-core/build.gradle
index ad24266..adeda14 100644
--- a/compose/animation/animation-core/build.gradle
+++ b/compose/animation/animation-core/build.gradle
@@ -29,30 +29,12 @@
 
 plugins {
     id("AndroidXPlugin")
+    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    androidLibrary {
-        namespace = "androidx.compose.animation.core"
-        withAndroidTestOnDeviceBuilder {
-            it.compilationName = "instrumentedTest"
-            it.defaultSourceSetName = "androidInstrumentedTest"
-            it.sourceSetTreeName = "test"
-        }
-        withAndroidTestOnJvmBuilder {
-            it.defaultSourceSetName = "androidUnitTest"
-        }
-        optimization {
-            it.consumerKeepRules.publish = true
-            it.consumerKeepRules.files.add(
-                    new File(project.projectDir, "proguard-rules.pro")
-            )
-        }
-
-        compileSdk = 35
-        aarMetadata.minCompileSdk = 35
-    }
+    android()
     jvmStubs()
     linuxX64Stubs()
 
@@ -150,3 +132,10 @@
     kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
+android {
+    compileSdk 35
+    namespace "androidx.compose.animation.core"
+    buildTypes.configureEach {
+        consumerProguardFiles("proguard-rules.pro")
+    }
+}
diff --git a/compose/animation/animation-core/src/androidInstrumentedTest/kotlin/androidx/compose/animation/core/TransitionTest.kt b/compose/animation/animation-core/src/androidInstrumentedTest/kotlin/androidx/compose/animation/core/TransitionTest.kt
index 618516f..a81e8a6 100644
--- a/compose/animation/animation-core/src/androidInstrumentedTest/kotlin/androidx/compose/animation/core/TransitionTest.kt
+++ b/compose/animation/animation-core/src/androidInstrumentedTest/kotlin/androidx/compose/animation/core/TransitionTest.kt
@@ -20,6 +20,7 @@
 import androidx.compose.animation.AnimatedContent
 import androidx.compose.animation.VectorConverter
 import androidx.compose.animation.animateColor
+import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.State
 import androidx.compose.runtime.getValue
@@ -566,4 +567,32 @@
         rule.mainClock.advanceTimeBy(200)
         rule.runOnIdle { assertThat(durations.size).isGreaterThan(0) }
     }
+
+    @Test
+    fun animateFloatCallerRecompositionCount() {
+        var recompositionCount = 0
+        val transitionState = MutableTransitionState(false)
+        rule.setContent {
+            if (transitionState.targetState) {
+                TestAnimatedContent(transitionState, { recompositionCount++ })
+            }
+        }
+
+        rule.runOnIdle { transitionState.targetState = true }
+
+        rule.runOnIdle {
+            // TODO(b/381537138): Once the bug is fixed, there should only be a single recomposition
+            assertEquals(2, recompositionCount)
+        }
+    }
+
+    @Composable
+    fun TestAnimatedContent(
+        transitionState: MutableTransitionState<Boolean>,
+        onRecomposition: () -> Unit
+    ) {
+        onRecomposition()
+        val transition = rememberTransition(transitionState)
+        transition.animateFloat { state -> if (state) 1f else 0f }
+    }
 }
diff --git a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt
index 9ceaf13..600a004 100644
--- a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt
+++ b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt
@@ -1861,12 +1861,7 @@
                 label
             )
         }
-    if (isSeeking) {
-        // In the case of seeking, we also need to update initial value as needed
-        transitionAnimation.updateInitialAndTargetValue(initialValue, targetValue, animationSpec)
-    } else {
-        transitionAnimation.updateTargetValue(targetValue, animationSpec)
-    }
+    UpdateInitialAndTargetValues(transitionAnimation, initialValue, targetValue, animationSpec)
 
     DisposableEffect(transitionAnimation) {
         addAnimation(transitionAnimation)
@@ -1875,6 +1870,24 @@
     return transitionAnimation
 }
 
+// This composable function is needed to contain recompositions caused by reads of the internal
+// animation states to an internal recomposition scope. Without this function, the caller of
+// animateValue gets recomposed when an animation starts.
+@Composable
+private fun <S, T, V : AnimationVector> Transition<S>.UpdateInitialAndTargetValues(
+    transitionAnimation: Transition<S>.TransitionAnimationState<T, V>,
+    initialValue: T,
+    targetValue: T,
+    animationSpec: FiniteAnimationSpec<T>
+) {
+    if (isSeeking) {
+        // In the case of seeking, we also need to update initial value as needed
+        transitionAnimation.updateInitialAndTargetValue(initialValue, targetValue, animationSpec)
+    } else {
+        transitionAnimation.updateTargetValue(targetValue, animationSpec)
+    }
+}
+
 // TODO: Remove noinline when b/174814083 is fixed.
 /**
  * Creates a Float animation as a part of the given [Transition]. This means the states of this
diff --git a/compose/animation/animation-graphics/bcv/native/1.7.0.txt b/compose/animation/animation-graphics/bcv/native/1.7.0.txt
index 3bc788e..d87ad3d 100644
--- a/compose/animation/animation-graphics/bcv/native/1.7.0.txt
+++ b/compose/animation/animation-graphics/bcv/native/1.7.0.txt
@@ -6,13 +6,6 @@
 // - Show declarations: true
 
 // Library unique name: <androidx.compose.animation:animation-graphics>
-final class androidx.compose.animation.graphics.vector/AnimatedImageVector { // androidx.compose.animation.graphics.vector/AnimatedImageVector|null[0]
-    final object Companion // androidx.compose.animation.graphics.vector/AnimatedImageVector.Companion|null[0]
-    final val imageVector // androidx.compose.animation.graphics.vector/AnimatedImageVector.imageVector|{}imageVector[0]
-        final fun <get-imageVector>(): androidx.compose.ui.graphics.vector/ImageVector // androidx.compose.animation.graphics.vector/AnimatedImageVector.imageVector.<get-imageVector>|<get-imageVector>(){}[0]
-    final val totalDuration // androidx.compose.animation.graphics.vector/AnimatedImageVector.totalDuration|{}totalDuration[0]
-        final fun <get-totalDuration>(): kotlin/Int // androidx.compose.animation.graphics.vector/AnimatedImageVector.totalDuration.<get-totalDuration>|<get-totalDuration>(){}[0]
-}
 open annotation class androidx.compose.animation.graphics/ExperimentalAnimationGraphicsApi : kotlin/Annotation { // androidx.compose.animation.graphics/ExperimentalAnimationGraphicsApi|null[0]
     constructor <init>() // androidx.compose.animation.graphics/ExperimentalAnimationGraphicsApi.<init>|<init>(){}[0]
 }
diff --git a/compose/animation/animation/bcv/native/1.7.0.txt b/compose/animation/animation/bcv/native/1.7.0.txt
index ef65c7b..9cd5f2b 100644
--- a/compose/animation/animation/bcv/native/1.7.0.txt
+++ b/compose/animation/animation/bcv/native/1.7.0.txt
@@ -6,56 +6,11 @@
 // - Show declarations: true
 
 // Library unique name: <androidx.compose.animation:animation>
-abstract fun interface androidx.compose.animation/BoundsTransform { // androidx.compose.animation/BoundsTransform|null[0]
-    abstract fun transform(androidx.compose.ui.geometry/Rect, androidx.compose.ui.geometry/Rect): androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.geometry/Rect> // androidx.compose.animation/BoundsTransform.transform|transform(androidx.compose.ui.geometry.Rect;androidx.compose.ui.geometry.Rect){}[0]
-}
 abstract interface androidx.compose.animation/AnimatedVisibilityScope { // androidx.compose.animation/AnimatedVisibilityScope|null[0]
     abstract val transition // androidx.compose.animation/AnimatedVisibilityScope.transition|{}transition[0]
         abstract fun <get-transition>(): androidx.compose.animation.core/Transition<androidx.compose.animation/EnterExitState> // androidx.compose.animation/AnimatedVisibilityScope.transition.<get-transition>|<get-transition>(){}[0]
     open fun (androidx.compose.ui/Modifier).animateEnterExit(androidx.compose.animation/EnterTransition =..., androidx.compose.animation/ExitTransition =..., kotlin/String =...): androidx.compose.ui/Modifier // androidx.compose.animation/AnimatedVisibilityScope.animateEnterExit|[email protected](androidx.compose.animation.EnterTransition;androidx.compose.animation.ExitTransition;kotlin.String){}[0]
 }
-abstract interface androidx.compose.animation/SharedTransitionScope : androidx.compose.ui.layout/LookaheadScope { // androidx.compose.animation/SharedTransitionScope|null[0]
-    abstract fun (androidx.compose.ui/Modifier).renderInSharedTransitionScopeOverlay(kotlin/Function0<kotlin/Boolean> =..., kotlin/Float =..., kotlin/Function2<androidx.compose.ui.unit/LayoutDirection, androidx.compose.ui.unit/Density, androidx.compose.ui.graphics/Path?> =...): androidx.compose.ui/Modifier // androidx.compose.animation/SharedTransitionScope.renderInSharedTransitionScopeOverlay|renderInSharedTransitionScopeOverlay@androidx.compose.ui.Modifier(kotlin.Function0<kotlin.Boolean>;kotlin.Float;kotlin.Function2<androidx.compose.ui.unit.LayoutDirection,androidx.compose.ui.unit.Density,androidx.compose.ui.graphics.Path?>){}[0]
-    abstract fun (androidx.compose.ui/Modifier).sharedBounds(androidx.compose.animation/SharedTransitionScope.SharedContentState, androidx.compose.animation/AnimatedVisibilityScope, androidx.compose.animation/EnterTransition =..., androidx.compose.animation/ExitTransition =..., androidx.compose.animation/BoundsTransform =..., androidx.compose.animation/SharedTransitionScope.ResizeMode =..., androidx.compose.animation/SharedTransitionScope.PlaceHolderSize =..., kotlin/Boolean =..., kotlin/Float =..., androidx.compose.animation/SharedTransitionScope.OverlayClip =...): androidx.compose.ui/Modifier // androidx.compose.animation/SharedTransitionScope.sharedBounds|[email protected](androidx.compose.animation.SharedTransitionScope.SharedContentState;androidx.compose.animation.AnimatedVisibilityScope;androidx.compose.animation.EnterTransition;androidx.compose.animation.ExitTransition;androidx.compose.animation.BoundsTransform;androidx.compose.animation.SharedTransitionScope.ResizeMode;androidx.compose.animation.SharedTransitionScope.PlaceHolderSize;kotlin.Boolean;kotlin.Float;androidx.compose.animation.SharedTransitionScope.OverlayClip){}[0]
-    abstract fun (androidx.compose.ui/Modifier).sharedElement(androidx.compose.animation/SharedTransitionScope.SharedContentState, androidx.compose.animation/AnimatedVisibilityScope, androidx.compose.animation/BoundsTransform =..., androidx.compose.animation/SharedTransitionScope.PlaceHolderSize =..., kotlin/Boolean =..., kotlin/Float =..., androidx.compose.animation/SharedTransitionScope.OverlayClip =...): androidx.compose.ui/Modifier // androidx.compose.animation/SharedTransitionScope.sharedElement|[email protected](androidx.compose.animation.SharedTransitionScope.SharedContentState;androidx.compose.animation.AnimatedVisibilityScope;androidx.compose.animation.BoundsTransform;androidx.compose.animation.SharedTransitionScope.PlaceHolderSize;kotlin.Boolean;kotlin.Float;androidx.compose.animation.SharedTransitionScope.OverlayClip){}[0]
-    abstract fun (androidx.compose.ui/Modifier).sharedElementWithCallerManagedVisibility(androidx.compose.animation/SharedTransitionScope.SharedContentState, kotlin/Boolean, androidx.compose.animation/BoundsTransform =..., androidx.compose.animation/SharedTransitionScope.PlaceHolderSize =..., kotlin/Boolean =..., kotlin/Float =..., androidx.compose.animation/SharedTransitionScope.OverlayClip =...): androidx.compose.ui/Modifier // androidx.compose.animation/SharedTransitionScope.sharedElementWithCallerManagedVisibility|sharedElementWithCallerManagedVisibility@androidx.compose.ui.Modifier(androidx.compose.animation.SharedTransitionScope.SharedContentState;kotlin.Boolean;androidx.compose.animation.BoundsTransform;androidx.compose.animation.SharedTransitionScope.PlaceHolderSize;kotlin.Boolean;kotlin.Float;androidx.compose.animation.SharedTransitionScope.OverlayClip){}[0]
-    abstract fun (androidx.compose.ui/Modifier).skipToLookaheadSize(): androidx.compose.ui/Modifier // androidx.compose.animation/SharedTransitionScope.skipToLookaheadSize|[email protected](){}[0]
-    abstract fun OverlayClip(androidx.compose.ui.graphics/Shape): androidx.compose.animation/SharedTransitionScope.OverlayClip // androidx.compose.animation/SharedTransitionScope.OverlayClip|OverlayClip(androidx.compose.ui.graphics.Shape){}[0]
-    abstract fun interface PlaceHolderSize { // androidx.compose.animation/SharedTransitionScope.PlaceHolderSize|null[0]
-        abstract fun calculateSize(androidx.compose.ui.unit/IntSize, androidx.compose.ui.unit/IntSize): androidx.compose.ui.unit/IntSize // androidx.compose.animation/SharedTransitionScope.PlaceHolderSize.calculateSize|calculateSize(androidx.compose.ui.unit.IntSize;androidx.compose.ui.unit.IntSize){}[0]
-        final object Companion { // androidx.compose.animation/SharedTransitionScope.PlaceHolderSize.Companion|null[0]
-            final val animatedSize // androidx.compose.animation/SharedTransitionScope.PlaceHolderSize.Companion.animatedSize|{}animatedSize[0]
-                final fun <get-animatedSize>(): androidx.compose.animation/SharedTransitionScope.PlaceHolderSize // androidx.compose.animation/SharedTransitionScope.PlaceHolderSize.Companion.animatedSize.<get-animatedSize>|<get-animatedSize>(){}[0]
-            final val contentSize // androidx.compose.animation/SharedTransitionScope.PlaceHolderSize.Companion.contentSize|{}contentSize[0]
-                final fun <get-contentSize>(): androidx.compose.animation/SharedTransitionScope.PlaceHolderSize // androidx.compose.animation/SharedTransitionScope.PlaceHolderSize.Companion.contentSize.<get-contentSize>|<get-contentSize>(){}[0]
-        }
-    }
-    abstract fun rememberSharedContentState(kotlin/Any): androidx.compose.animation/SharedTransitionScope.SharedContentState // androidx.compose.animation/SharedTransitionScope.rememberSharedContentState|rememberSharedContentState(kotlin.Any){}[0]
-    abstract interface OverlayClip { // androidx.compose.animation/SharedTransitionScope.OverlayClip|null[0]
-        abstract fun getClipPath(androidx.compose.animation/SharedTransitionScope.SharedContentState, androidx.compose.ui.geometry/Rect, androidx.compose.ui.unit/LayoutDirection, androidx.compose.ui.unit/Density): androidx.compose.ui.graphics/Path? // androidx.compose.animation/SharedTransitionScope.OverlayClip.getClipPath|getClipPath(androidx.compose.animation.SharedTransitionScope.SharedContentState;androidx.compose.ui.geometry.Rect;androidx.compose.ui.unit.LayoutDirection;androidx.compose.ui.unit.Density){}[0]
-    }
-    abstract val isTransitionActive // androidx.compose.animation/SharedTransitionScope.isTransitionActive|{}isTransitionActive[0]
-        abstract fun <get-isTransitionActive>(): kotlin/Boolean // androidx.compose.animation/SharedTransitionScope.isTransitionActive.<get-isTransitionActive>|<get-isTransitionActive>(){}[0]
-    final class SharedContentState { // androidx.compose.animation/SharedTransitionScope.SharedContentState|null[0]
-        final val clipPathInOverlay // androidx.compose.animation/SharedTransitionScope.SharedContentState.clipPathInOverlay|{}clipPathInOverlay[0]
-            final fun <get-clipPathInOverlay>(): androidx.compose.ui.graphics/Path? // androidx.compose.animation/SharedTransitionScope.SharedContentState.clipPathInOverlay.<get-clipPathInOverlay>|<get-clipPathInOverlay>(){}[0]
-        final val isMatchFound // androidx.compose.animation/SharedTransitionScope.SharedContentState.isMatchFound|{}isMatchFound[0]
-            final fun <get-isMatchFound>(): kotlin/Boolean // androidx.compose.animation/SharedTransitionScope.SharedContentState.isMatchFound.<get-isMatchFound>|<get-isMatchFound>(){}[0]
-        final val key // androidx.compose.animation/SharedTransitionScope.SharedContentState.key|{}key[0]
-            final fun <get-key>(): kotlin/Any // androidx.compose.animation/SharedTransitionScope.SharedContentState.key.<get-key>|<get-key>(){}[0]
-        final val parentSharedContentState // androidx.compose.animation/SharedTransitionScope.SharedContentState.parentSharedContentState|{}parentSharedContentState[0]
-            final fun <get-parentSharedContentState>(): androidx.compose.animation/SharedTransitionScope.SharedContentState? // androidx.compose.animation/SharedTransitionScope.SharedContentState.parentSharedContentState.<get-parentSharedContentState>|<get-parentSharedContentState>(){}[0]
-    }
-    open fun scaleInSharedContentToBounds(androidx.compose.ui.layout/ContentScale =..., androidx.compose.ui/Alignment =...): androidx.compose.animation/EnterTransition // androidx.compose.animation/SharedTransitionScope.scaleInSharedContentToBounds|scaleInSharedContentToBounds(androidx.compose.ui.layout.ContentScale;androidx.compose.ui.Alignment){}[0]
-    open fun scaleOutSharedContentToBounds(androidx.compose.ui.layout/ContentScale =..., androidx.compose.ui/Alignment =...): androidx.compose.animation/ExitTransition // androidx.compose.animation/SharedTransitionScope.scaleOutSharedContentToBounds|scaleOutSharedContentToBounds(androidx.compose.ui.layout.ContentScale;androidx.compose.ui.Alignment){}[0]
-    sealed interface ResizeMode { // androidx.compose.animation/SharedTransitionScope.ResizeMode|null[0]
-        final object Companion { // androidx.compose.animation/SharedTransitionScope.ResizeMode.Companion|null[0]
-            final fun ScaleToBounds(androidx.compose.ui.layout/ContentScale =..., androidx.compose.ui/Alignment =...): androidx.compose.animation/SharedTransitionScope.ResizeMode // androidx.compose.animation/SharedTransitionScope.ResizeMode.Companion.ScaleToBounds|ScaleToBounds(androidx.compose.ui.layout.ContentScale;androidx.compose.ui.Alignment){}[0]
-            final val RemeasureToBounds // androidx.compose.animation/SharedTransitionScope.ResizeMode.Companion.RemeasureToBounds|{}RemeasureToBounds[0]
-                final fun <get-RemeasureToBounds>(): androidx.compose.animation/SharedTransitionScope.ResizeMode // androidx.compose.animation/SharedTransitionScope.ResizeMode.Companion.RemeasureToBounds.<get-RemeasureToBounds>|<get-RemeasureToBounds>(){}[0]
-        }
-    }
-}
 abstract interface androidx.compose.animation/SizeTransform { // androidx.compose.animation/SizeTransform|null[0]
     abstract fun createAnimationSpec(androidx.compose.ui.unit/IntSize, androidx.compose.ui.unit/IntSize): androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntSize> // androidx.compose.animation/SizeTransform.createAnimationSpec|createAnimationSpec(androidx.compose.ui.unit.IntSize;androidx.compose.ui.unit.IntSize){}[0]
     abstract val clip // androidx.compose.animation/SizeTransform.clip|{}clip[0]
@@ -92,7 +47,6 @@
 final fun (androidx.compose.animation.core/InfiniteTransition).androidx.compose.animation/animateColor(androidx.compose.ui.graphics/Color, androidx.compose.ui.graphics/Color, androidx.compose.animation.core/InfiniteRepeatableSpec<androidx.compose.ui.graphics/Color>): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.animation/animateColor|[email protected](androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.animation.core.InfiniteRepeatableSpec<androidx.compose.ui.graphics.Color>){}[0]
 final fun (androidx.compose.animation.core/InfiniteTransition).androidx.compose.animation/animateColor(androidx.compose.ui.graphics/Color, androidx.compose.ui.graphics/Color, androidx.compose.animation.core/InfiniteRepeatableSpec<androidx.compose.ui.graphics/Color>, kotlin/String =...): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.animation/animateColor|[email protected](androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.animation.core.InfiniteRepeatableSpec<androidx.compose.ui.graphics.Color>;kotlin.String){}[0]
 final fun (androidx.compose.animation/EnterTransition).androidx.compose.animation/togetherWith(androidx.compose.animation/ExitTransition): androidx.compose.animation/ContentTransform // androidx.compose.animation/togetherWith|[email protected](androidx.compose.animation.ExitTransition){}[0]
-final fun (androidx.compose.animation/EnterTransition).androidx.compose.animation/with(androidx.compose.animation/ExitTransition): androidx.compose.animation/ContentTransform // androidx.compose.animation/with|[email protected](androidx.compose.animation.ExitTransition){}[0]
 final fun (androidx.compose.foundation.layout/ColumnScope).androidx.compose.animation/AnimatedVisibility(androidx.compose.animation.core/MutableTransitionState<kotlin/Boolean>, androidx.compose.ui/Modifier =..., androidx.compose.animation/EnterTransition =..., androidx.compose.animation/ExitTransition =..., kotlin/String =..., kotlin/Function1<androidx.compose.animation/AnimatedVisibilityScope, kotlin/Unit>) // androidx.compose.animation/AnimatedVisibility|AnimatedVisibility@androidx.compose.foundation.layout.ColumnScope(androidx.compose.animation.core.MutableTransitionState<kotlin.Boolean>;androidx.compose.ui.Modifier;androidx.compose.animation.EnterTransition;androidx.compose.animation.ExitTransition;kotlin.String;kotlin.Function1<androidx.compose.animation.AnimatedVisibilityScope,kotlin.Unit>){}[0]
 final fun (androidx.compose.foundation.layout/ColumnScope).androidx.compose.animation/AnimatedVisibility(kotlin/Boolean, androidx.compose.ui/Modifier =..., androidx.compose.animation/EnterTransition =..., androidx.compose.animation/ExitTransition =..., kotlin/String =..., kotlin/Function1<androidx.compose.animation/AnimatedVisibilityScope, kotlin/Unit>) // androidx.compose.animation/AnimatedVisibility|AnimatedVisibility@androidx.compose.foundation.layout.ColumnScope(kotlin.Boolean;androidx.compose.ui.Modifier;androidx.compose.animation.EnterTransition;androidx.compose.animation.ExitTransition;kotlin.String;kotlin.Function1<androidx.compose.animation.AnimatedVisibilityScope,kotlin.Unit>){}[0]
 final fun (androidx.compose.foundation.layout/RowScope).androidx.compose.animation/AnimatedVisibility(androidx.compose.animation.core/MutableTransitionState<kotlin/Boolean>, androidx.compose.ui/Modifier =..., androidx.compose.animation/EnterTransition =..., androidx.compose.animation/ExitTransition =..., kotlin/String =..., kotlin/Function1<androidx.compose.animation/AnimatedVisibilityScope, kotlin/Unit>) // androidx.compose.animation/AnimatedVisibility|[email protected](androidx.compose.animation.core.MutableTransitionState<kotlin.Boolean>;androidx.compose.ui.Modifier;androidx.compose.animation.EnterTransition;androidx.compose.animation.ExitTransition;kotlin.String;kotlin.Function1<androidx.compose.animation.AnimatedVisibilityScope,kotlin.Unit>){}[0]
@@ -101,7 +55,6 @@
 final fun (androidx.compose.ui/Modifier).androidx.compose.animation/animateContentSize(androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntSize> =..., kotlin/Function2<androidx.compose.ui.unit/IntSize, androidx.compose.ui.unit/IntSize, kotlin/Unit>? =...): androidx.compose.ui/Modifier // androidx.compose.animation/animateContentSize|[email protected](androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize>;kotlin.Function2<androidx.compose.ui.unit.IntSize,androidx.compose.ui.unit.IntSize,kotlin.Unit>?){}[0]
 final fun <#A: kotlin/Any?> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation/AnimatedContent(androidx.compose.ui/Modifier =..., kotlin/Function1<androidx.compose.animation/AnimatedContentTransitionScope<#A>, androidx.compose.animation/ContentTransform> =..., androidx.compose.ui/Alignment =..., kotlin/Function1<#A, kotlin/Any?> =..., kotlin/Function2<androidx.compose.animation/AnimatedContentScope, #A, kotlin/Unit>) // androidx.compose.animation/AnimatedContent|[email protected]<0:0>(androidx.compose.ui.Modifier;kotlin.Function1<androidx.compose.animation.AnimatedContentTransitionScope<0:0>,androidx.compose.animation.ContentTransform>;androidx.compose.ui.Alignment;kotlin.Function1<0:0,kotlin.Any?>;kotlin.Function2<androidx.compose.animation.AnimatedContentScope,0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
 final fun <#A: kotlin/Any?> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation/AnimatedVisibility(kotlin/Function1<#A, kotlin/Boolean>, androidx.compose.ui/Modifier =..., androidx.compose.animation/EnterTransition =..., androidx.compose.animation/ExitTransition =..., kotlin/Function1<androidx.compose.animation/AnimatedVisibilityScope, kotlin/Unit>) // androidx.compose.animation/AnimatedVisibility|[email protected]<0:0>(kotlin.Function1<0:0,kotlin.Boolean>;androidx.compose.ui.Modifier;androidx.compose.animation.EnterTransition;androidx.compose.animation.ExitTransition;kotlin.Function1<androidx.compose.animation.AnimatedVisibilityScope,kotlin.Unit>){0§<kotlin.Any?>}[0]
-final fun <#A: kotlin/Any?> (androidx.compose.animation.core/Transition<#A>).androidx.compose.animation/Crossfade(androidx.compose.ui/Modifier =..., androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float> =..., kotlin/Function1<#A, kotlin/Any?> =..., kotlin/Function1<#A, kotlin/Unit>) // androidx.compose.animation/Crossfade|[email protected]<0:0>(androidx.compose.ui.Modifier;androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>;kotlin.Function1<0:0,kotlin.Any?>;kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
 final fun <#A: kotlin/Any?> androidx.compose.animation/AnimatedContent(#A, androidx.compose.ui/Modifier =..., kotlin/Function1<androidx.compose.animation/AnimatedContentTransitionScope<#A>, androidx.compose.animation/ContentTransform> =..., androidx.compose.ui/Alignment =..., kotlin/String =..., kotlin/Function1<#A, kotlin/Any?> =..., kotlin/Function2<androidx.compose.animation/AnimatedContentScope, #A, kotlin/Unit>) // androidx.compose.animation/AnimatedContent|AnimatedContent(0:0;androidx.compose.ui.Modifier;kotlin.Function1<androidx.compose.animation.AnimatedContentTransitionScope<0:0>,androidx.compose.animation.ContentTransform>;androidx.compose.ui.Alignment;kotlin.String;kotlin.Function1<0:0,kotlin.Any?>;kotlin.Function2<androidx.compose.animation.AnimatedContentScope,0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
 final fun <#A: kotlin/Any?> androidx.compose.animation/Crossfade(#A, androidx.compose.ui/Modifier =..., androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float> =..., kotlin/Function1<#A, kotlin/Unit>) // androidx.compose.animation/Crossfade|Crossfade(0:0;androidx.compose.ui.Modifier;androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>;kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
 final fun <#A: kotlin/Any?> androidx.compose.animation/Crossfade(#A, androidx.compose.ui/Modifier =..., androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float> =..., kotlin/String =..., kotlin/Function1<#A, kotlin/Unit>) // androidx.compose.animation/Crossfade|Crossfade(0:0;androidx.compose.ui.Modifier;androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>;kotlin.String;kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
@@ -110,8 +63,6 @@
 final fun androidx.compose.animation/Animatable(androidx.compose.ui.graphics/Color): androidx.compose.animation.core/Animatable<androidx.compose.ui.graphics/Color, androidx.compose.animation.core/AnimationVector4D> // androidx.compose.animation/Animatable|Animatable(androidx.compose.ui.graphics.Color){}[0]
 final fun androidx.compose.animation/AnimatedVisibility(androidx.compose.animation.core/MutableTransitionState<kotlin/Boolean>, androidx.compose.ui/Modifier =..., androidx.compose.animation/EnterTransition =..., androidx.compose.animation/ExitTransition =..., kotlin/String =..., kotlin/Function1<androidx.compose.animation/AnimatedVisibilityScope, kotlin/Unit>) // androidx.compose.animation/AnimatedVisibility|AnimatedVisibility(androidx.compose.animation.core.MutableTransitionState<kotlin.Boolean>;androidx.compose.ui.Modifier;androidx.compose.animation.EnterTransition;androidx.compose.animation.ExitTransition;kotlin.String;kotlin.Function1<androidx.compose.animation.AnimatedVisibilityScope,kotlin.Unit>){}[0]
 final fun androidx.compose.animation/AnimatedVisibility(kotlin/Boolean, androidx.compose.ui/Modifier =..., androidx.compose.animation/EnterTransition =..., androidx.compose.animation/ExitTransition =..., kotlin/String =..., kotlin/Function1<androidx.compose.animation/AnimatedVisibilityScope, kotlin/Unit>) // androidx.compose.animation/AnimatedVisibility|AnimatedVisibility(kotlin.Boolean;androidx.compose.ui.Modifier;androidx.compose.animation.EnterTransition;androidx.compose.animation.ExitTransition;kotlin.String;kotlin.Function1<androidx.compose.animation.AnimatedVisibilityScope,kotlin.Unit>){}[0]
-final fun androidx.compose.animation/SharedTransitionLayout(androidx.compose.ui/Modifier =..., kotlin/Function1<androidx.compose.animation/SharedTransitionScope, kotlin/Unit>) // androidx.compose.animation/SharedTransitionLayout|SharedTransitionLayout(androidx.compose.ui.Modifier;kotlin.Function1<androidx.compose.animation.SharedTransitionScope,kotlin.Unit>){}[0]
-final fun androidx.compose.animation/SharedTransitionScope(kotlin/Function2<androidx.compose.animation/SharedTransitionScope, androidx.compose.ui/Modifier, kotlin/Unit>) // androidx.compose.animation/SharedTransitionScope|SharedTransitionScope(kotlin.Function2<androidx.compose.animation.SharedTransitionScope,androidx.compose.ui.Modifier,kotlin.Unit>){}[0]
 final fun androidx.compose.animation/SizeTransform(kotlin/Boolean =..., kotlin/Function2<androidx.compose.ui.unit/IntSize, androidx.compose.ui.unit/IntSize, androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntSize>> =...): androidx.compose.animation/SizeTransform // androidx.compose.animation/SizeTransform|SizeTransform(kotlin.Boolean;kotlin.Function2<androidx.compose.ui.unit.IntSize,androidx.compose.ui.unit.IntSize,androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntSize>>){}[0]
 final fun androidx.compose.animation/animateColorAsState(androidx.compose.ui.graphics/Color, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.graphics/Color> =..., kotlin/Function1<androidx.compose.ui.graphics/Color, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.animation/animateColorAsState|animateColorAsState(androidx.compose.ui.graphics.Color;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color>;kotlin.Function1<androidx.compose.ui.graphics.Color,kotlin.Unit>?){}[0]
 final fun androidx.compose.animation/animateColorAsState(androidx.compose.ui.graphics/Color, androidx.compose.animation.core/AnimationSpec<androidx.compose.ui.graphics/Color> =..., kotlin/String =..., kotlin/Function1<androidx.compose.ui.graphics/Color, kotlin/Unit>? =...): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.animation/animateColorAsState|animateColorAsState(androidx.compose.ui.graphics.Color;androidx.compose.animation.core.AnimationSpec<androidx.compose.ui.graphics.Color>;kotlin.String;kotlin.Function1<androidx.compose.ui.graphics.Color,kotlin.Unit>?){}[0]
diff --git a/compose/benchmark-utils/src/main/java/androidx/compose/testutils/benchmark/BenchmarksExtensions.kt b/compose/benchmark-utils/src/main/java/androidx/compose/testutils/benchmark/BenchmarksExtensions.kt
index 46a3dd5..95f5c4f 100644
--- a/compose/benchmark-utils/src/main/java/androidx/compose/testutils/benchmark/BenchmarksExtensions.kt
+++ b/compose/benchmark-utils/src/main/java/androidx/compose/testutils/benchmark/BenchmarksExtensions.kt
@@ -361,6 +361,43 @@
 }
 
 /**
+ * Measures recompose time after changing a state.
+ *
+ * @param assertOneRecomposition whether the benchmark will fail if there are pending recompositions
+ *   after the first recomposition. By default this is true to enforce correctness in the benchmark,
+ *   but for components that have animations after being recomposed this can be turned off to
+ *   benchmark just the first recompose, remeasure and relayout without any pending animations.
+ */
+fun <T> ComposeBenchmarkRule.toggleStateBenchmarkCompose(
+    caseFactory: () -> T,
+    assertOneRecomposition: Boolean = true,
+    requireRecomposition: Boolean = true
+) where T : ComposeTestCase, T : ToggleableTestCase {
+    runBenchmarkFor(caseFactory) {
+        runOnUiThread { doFramesUntilNoChangesPending() }
+        measureRepeatedOnUiThread {
+            getTestCase().toggleState()
+            if (requireRecomposition) {
+                recomposeAssertHadChanges()
+            } else {
+                recompose()
+            }
+            if (assertOneRecomposition) {
+                assertNoPendingChanges()
+            }
+
+            runWithTimingDisabled {
+                measure()
+                layout()
+                drawPrepare()
+                draw()
+                drawFinish()
+            }
+        }
+    }
+}
+
+/**
  * Measures measure and layout time after changing a state.
  *
  * @param assertOneRecomposition whether the benchmark will fail if there are pending recompositions
diff --git a/compose/docs/compose-component-api-guidelines.md b/compose/docs/compose-component-api-guidelines.md
index 978d7ff..76c2a5c 100644
--- a/compose/docs/compose-component-api-guidelines.md
+++ b/compose/docs/compose-component-api-guidelines.md
@@ -534,7 +534,7 @@
 *   Has a no-op default value `Modifier`.
     *   No-op default value ensures that no functionality will be lost when users provide their own modifiers for the component.
 *   Is the only parameter of type Modifier in the parameter list.
-    *   Since modifiers intend to modify the external behaviors and appearance of the component, one modifier parameter should be sufficient. Consider asking for specific parameters or reconsidering the layering of the component (e.g. braking component into two) instead.
+    *   Since modifiers intend to modify the external behaviors and appearance of the component, one modifier parameter should be sufficient. Consider asking for specific parameters or reconsidering the layering of the component (e.g. breaking component into two) instead.
 *   Is applied once as a first modifier in the chain to the root-most layout in the component implementation.
     *   Since modifiers intend to modify the external behaviors and appearance of the component, they must be applied to the outer-most layout and be the first modifiers in the chain. It is ok to chain other modifiers to the modifier that is passed as a parameter.
 
diff --git a/compose/foundation/foundation-layout/bcv/native/1.7.0.txt b/compose/foundation/foundation-layout/bcv/native/1.7.0.txt
index c7bbdbd..fc94796 100644
--- a/compose/foundation/foundation-layout/bcv/native/1.7.0.txt
+++ b/compose/foundation/foundation-layout/bcv/native/1.7.0.txt
@@ -28,46 +28,6 @@
     abstract fun (androidx.compose.ui/Modifier).alignBy(kotlin/Function1<androidx.compose.ui.layout/Measured, kotlin/Int>): androidx.compose.ui/Modifier // androidx.compose.foundation.layout/ColumnScope.alignBy|[email protected](kotlin.Function1<androidx.compose.ui.layout.Measured,kotlin.Int>){}[0]
     abstract fun (androidx.compose.ui/Modifier).weight(kotlin/Float, kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.foundation.layout/ColumnScope.weight|[email protected](kotlin.Float;kotlin.Boolean){}[0]
 }
-abstract interface androidx.compose.foundation.layout/ContextualFlowColumnOverflowScope : androidx.compose.foundation.layout/FlowColumnOverflowScope // androidx.compose.foundation.layout/ContextualFlowColumnOverflowScope|null[0]
-abstract interface androidx.compose.foundation.layout/ContextualFlowColumnScope : androidx.compose.foundation.layout/FlowColumnScope { // androidx.compose.foundation.layout/ContextualFlowColumnScope|null[0]
-    abstract val indexInLine // androidx.compose.foundation.layout/ContextualFlowColumnScope.indexInLine|{}indexInLine[0]
-        abstract fun <get-indexInLine>(): kotlin/Int // androidx.compose.foundation.layout/ContextualFlowColumnScope.indexInLine.<get-indexInLine>|<get-indexInLine>(){}[0]
-    abstract val lineIndex // androidx.compose.foundation.layout/ContextualFlowColumnScope.lineIndex|{}lineIndex[0]
-        abstract fun <get-lineIndex>(): kotlin/Int // androidx.compose.foundation.layout/ContextualFlowColumnScope.lineIndex.<get-lineIndex>|<get-lineIndex>(){}[0]
-    abstract val maxHeightInLine // androidx.compose.foundation.layout/ContextualFlowColumnScope.maxHeightInLine|{}maxHeightInLine[0]
-        abstract fun <get-maxHeightInLine>(): androidx.compose.ui.unit/Dp // androidx.compose.foundation.layout/ContextualFlowColumnScope.maxHeightInLine.<get-maxHeightInLine>|<get-maxHeightInLine>(){}[0]
-    abstract val maxWidth // androidx.compose.foundation.layout/ContextualFlowColumnScope.maxWidth|{}maxWidth[0]
-        abstract fun <get-maxWidth>(): androidx.compose.ui.unit/Dp // androidx.compose.foundation.layout/ContextualFlowColumnScope.maxWidth.<get-maxWidth>|<get-maxWidth>(){}[0]
-}
-abstract interface androidx.compose.foundation.layout/ContextualFlowRowOverflowScope : androidx.compose.foundation.layout/FlowRowOverflowScope // androidx.compose.foundation.layout/ContextualFlowRowOverflowScope|null[0]
-abstract interface androidx.compose.foundation.layout/ContextualFlowRowScope : androidx.compose.foundation.layout/FlowRowScope { // androidx.compose.foundation.layout/ContextualFlowRowScope|null[0]
-    abstract val indexInLine // androidx.compose.foundation.layout/ContextualFlowRowScope.indexInLine|{}indexInLine[0]
-        abstract fun <get-indexInLine>(): kotlin/Int // androidx.compose.foundation.layout/ContextualFlowRowScope.indexInLine.<get-indexInLine>|<get-indexInLine>(){}[0]
-    abstract val lineIndex // androidx.compose.foundation.layout/ContextualFlowRowScope.lineIndex|{}lineIndex[0]
-        abstract fun <get-lineIndex>(): kotlin/Int // androidx.compose.foundation.layout/ContextualFlowRowScope.lineIndex.<get-lineIndex>|<get-lineIndex>(){}[0]
-    abstract val maxHeight // androidx.compose.foundation.layout/ContextualFlowRowScope.maxHeight|{}maxHeight[0]
-        abstract fun <get-maxHeight>(): androidx.compose.ui.unit/Dp // androidx.compose.foundation.layout/ContextualFlowRowScope.maxHeight.<get-maxHeight>|<get-maxHeight>(){}[0]
-    abstract val maxWidthInLine // androidx.compose.foundation.layout/ContextualFlowRowScope.maxWidthInLine|{}maxWidthInLine[0]
-        abstract fun <get-maxWidthInLine>(): androidx.compose.ui.unit/Dp // androidx.compose.foundation.layout/ContextualFlowRowScope.maxWidthInLine.<get-maxWidthInLine>|<get-maxWidthInLine>(){}[0]
-}
-abstract interface androidx.compose.foundation.layout/FlowColumnOverflowScope : androidx.compose.foundation.layout/FlowColumnScope { // androidx.compose.foundation.layout/FlowColumnOverflowScope|null[0]
-    abstract val shownItemCount // androidx.compose.foundation.layout/FlowColumnOverflowScope.shownItemCount|{}shownItemCount[0]
-        abstract fun <get-shownItemCount>(): kotlin/Int // androidx.compose.foundation.layout/FlowColumnOverflowScope.shownItemCount.<get-shownItemCount>|<get-shownItemCount>(){}[0]
-    abstract val totalItemCount // androidx.compose.foundation.layout/FlowColumnOverflowScope.totalItemCount|{}totalItemCount[0]
-        abstract fun <get-totalItemCount>(): kotlin/Int // androidx.compose.foundation.layout/FlowColumnOverflowScope.totalItemCount.<get-totalItemCount>|<get-totalItemCount>(){}[0]
-}
-abstract interface androidx.compose.foundation.layout/FlowColumnScope : androidx.compose.foundation.layout/ColumnScope { // androidx.compose.foundation.layout/FlowColumnScope|null[0]
-    abstract fun (androidx.compose.ui/Modifier).fillMaxColumnWidth(kotlin/Float =...): androidx.compose.ui/Modifier // androidx.compose.foundation.layout/FlowColumnScope.fillMaxColumnWidth|[email protected](kotlin.Float){}[0]
-}
-abstract interface androidx.compose.foundation.layout/FlowRowOverflowScope : androidx.compose.foundation.layout/FlowRowScope { // androidx.compose.foundation.layout/FlowRowOverflowScope|null[0]
-    abstract val shownItemCount // androidx.compose.foundation.layout/FlowRowOverflowScope.shownItemCount|{}shownItemCount[0]
-        abstract fun <get-shownItemCount>(): kotlin/Int // androidx.compose.foundation.layout/FlowRowOverflowScope.shownItemCount.<get-shownItemCount>|<get-shownItemCount>(){}[0]
-    abstract val totalItemCount // androidx.compose.foundation.layout/FlowRowOverflowScope.totalItemCount|{}totalItemCount[0]
-        abstract fun <get-totalItemCount>(): kotlin/Int // androidx.compose.foundation.layout/FlowRowOverflowScope.totalItemCount.<get-totalItemCount>|<get-totalItemCount>(){}[0]
-}
-abstract interface androidx.compose.foundation.layout/FlowRowScope : androidx.compose.foundation.layout/RowScope { // androidx.compose.foundation.layout/FlowRowScope|null[0]
-    abstract fun (androidx.compose.ui/Modifier).fillMaxRowHeight(kotlin/Float =...): androidx.compose.ui/Modifier // androidx.compose.foundation.layout/FlowRowScope.fillMaxRowHeight|[email protected](kotlin.Float){}[0]
-}
 abstract interface androidx.compose.foundation.layout/PaddingValues { // androidx.compose.foundation.layout/PaddingValues|null[0]
     abstract fun calculateBottomPadding(): androidx.compose.ui.unit/Dp // androidx.compose.foundation.layout/PaddingValues.calculateBottomPadding|calculateBottomPadding(){}[0]
     abstract fun calculateLeftPadding(androidx.compose.ui.unit/LayoutDirection): androidx.compose.ui.unit/Dp // androidx.compose.foundation.layout/PaddingValues.calculateLeftPadding|calculateLeftPadding(androidx.compose.ui.unit.LayoutDirection){}[0]
@@ -98,56 +58,6 @@
     abstract fun getTop(androidx.compose.ui.unit/Density): kotlin/Int // androidx.compose.foundation.layout/WindowInsets.getTop|getTop(androidx.compose.ui.unit.Density){}[0]
     final object Companion // androidx.compose.foundation.layout/WindowInsets.Companion|null[0]
 }
-final class androidx.compose.foundation.layout/ContextualFlowColumnOverflow : androidx.compose.foundation.layout/FlowLayoutOverflow { // androidx.compose.foundation.layout/ContextualFlowColumnOverflow|null[0]
-    final object Companion { // androidx.compose.foundation.layout/ContextualFlowColumnOverflow.Companion|null[0]
-        final fun expandIndicator(kotlin/Function1<androidx.compose.foundation.layout/ContextualFlowColumnOverflowScope, kotlin/Unit>): androidx.compose.foundation.layout/ContextualFlowColumnOverflow // androidx.compose.foundation.layout/ContextualFlowColumnOverflow.Companion.expandIndicator|expandIndicator(kotlin.Function1<androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit>){}[0]
-        final fun expandOrCollapseIndicator(kotlin/Function1<androidx.compose.foundation.layout/ContextualFlowColumnOverflowScope, kotlin/Unit>, kotlin/Function1<androidx.compose.foundation.layout/ContextualFlowColumnOverflowScope, kotlin/Unit>, kotlin/Int =..., androidx.compose.ui.unit/Dp =...): androidx.compose.foundation.layout/ContextualFlowColumnOverflow // androidx.compose.foundation.layout/ContextualFlowColumnOverflow.Companion.expandOrCollapseIndicator|expandOrCollapseIndicator(kotlin.Function1<androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit>;kotlin.Function1<androidx.compose.foundation.layout.ContextualFlowColumnOverflowScope,kotlin.Unit>;kotlin.Int;androidx.compose.ui.unit.Dp){}[0]
-        final val Clip // androidx.compose.foundation.layout/ContextualFlowColumnOverflow.Companion.Clip|{}Clip[0]
-            final fun <get-Clip>(): androidx.compose.foundation.layout/ContextualFlowColumnOverflow // androidx.compose.foundation.layout/ContextualFlowColumnOverflow.Companion.Clip.<get-Clip>|<get-Clip>(){}[0]
-        final val Visible // androidx.compose.foundation.layout/ContextualFlowColumnOverflow.Companion.Visible|{}Visible[0]
-            final fun <get-Visible>(): androidx.compose.foundation.layout/ContextualFlowColumnOverflow // androidx.compose.foundation.layout/ContextualFlowColumnOverflow.Companion.Visible.<get-Visible>|<get-Visible>(){}[0]
-    }
-}
-final class androidx.compose.foundation.layout/ContextualFlowRowOverflow : androidx.compose.foundation.layout/FlowLayoutOverflow { // androidx.compose.foundation.layout/ContextualFlowRowOverflow|null[0]
-    final object Companion { // androidx.compose.foundation.layout/ContextualFlowRowOverflow.Companion|null[0]
-        final fun expandIndicator(kotlin/Function1<androidx.compose.foundation.layout/ContextualFlowRowOverflowScope, kotlin/Unit>): androidx.compose.foundation.layout/ContextualFlowRowOverflow // androidx.compose.foundation.layout/ContextualFlowRowOverflow.Companion.expandIndicator|expandIndicator(kotlin.Function1<androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit>){}[0]
-        final fun expandOrCollapseIndicator(kotlin/Function1<androidx.compose.foundation.layout/ContextualFlowRowOverflowScope, kotlin/Unit>, kotlin/Function1<androidx.compose.foundation.layout/ContextualFlowRowOverflowScope, kotlin/Unit>, kotlin/Int =..., androidx.compose.ui.unit/Dp =...): androidx.compose.foundation.layout/ContextualFlowRowOverflow // androidx.compose.foundation.layout/ContextualFlowRowOverflow.Companion.expandOrCollapseIndicator|expandOrCollapseIndicator(kotlin.Function1<androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit>;kotlin.Function1<androidx.compose.foundation.layout.ContextualFlowRowOverflowScope,kotlin.Unit>;kotlin.Int;androidx.compose.ui.unit.Dp){}[0]
-        final val Clip // androidx.compose.foundation.layout/ContextualFlowRowOverflow.Companion.Clip|{}Clip[0]
-            final fun <get-Clip>(): androidx.compose.foundation.layout/ContextualFlowRowOverflow // androidx.compose.foundation.layout/ContextualFlowRowOverflow.Companion.Clip.<get-Clip>|<get-Clip>(){}[0]
-        final val Visible // androidx.compose.foundation.layout/ContextualFlowRowOverflow.Companion.Visible|{}Visible[0]
-            final fun <get-Visible>(): androidx.compose.foundation.layout/ContextualFlowRowOverflow // androidx.compose.foundation.layout/ContextualFlowRowOverflow.Companion.Visible.<get-Visible>|<get-Visible>(){}[0]
-    }
-}
-final class androidx.compose.foundation.layout/FlowColumnOverflow : androidx.compose.foundation.layout/FlowLayoutOverflow { // androidx.compose.foundation.layout/FlowColumnOverflow|null[0]
-    final object Companion { // androidx.compose.foundation.layout/FlowColumnOverflow.Companion|null[0]
-        final fun expandIndicator(kotlin/Function1<androidx.compose.foundation.layout/FlowColumnOverflowScope, kotlin/Unit>): androidx.compose.foundation.layout/FlowColumnOverflow // androidx.compose.foundation.layout/FlowColumnOverflow.Companion.expandIndicator|expandIndicator(kotlin.Function1<androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit>){}[0]
-        final fun expandOrCollapseIndicator(kotlin/Function1<androidx.compose.foundation.layout/FlowColumnOverflowScope, kotlin/Unit>, kotlin/Function1<androidx.compose.foundation.layout/FlowColumnOverflowScope, kotlin/Unit>, kotlin/Int =..., androidx.compose.ui.unit/Dp =...): androidx.compose.foundation.layout/FlowColumnOverflow // androidx.compose.foundation.layout/FlowColumnOverflow.Companion.expandOrCollapseIndicator|expandOrCollapseIndicator(kotlin.Function1<androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit>;kotlin.Function1<androidx.compose.foundation.layout.FlowColumnOverflowScope,kotlin.Unit>;kotlin.Int;androidx.compose.ui.unit.Dp){}[0]
-        final val Clip // androidx.compose.foundation.layout/FlowColumnOverflow.Companion.Clip|{}Clip[0]
-            final fun <get-Clip>(): androidx.compose.foundation.layout/FlowColumnOverflow // androidx.compose.foundation.layout/FlowColumnOverflow.Companion.Clip.<get-Clip>|<get-Clip>(){}[0]
-        final val Visible // androidx.compose.foundation.layout/FlowColumnOverflow.Companion.Visible|{}Visible[0]
-            final fun <get-Visible>(): androidx.compose.foundation.layout/FlowColumnOverflow // androidx.compose.foundation.layout/FlowColumnOverflow.Companion.Visible.<get-Visible>|<get-Visible>(){}[0]
-    }
-}
-final class androidx.compose.foundation.layout/FlowRowOverflow : androidx.compose.foundation.layout/FlowLayoutOverflow { // androidx.compose.foundation.layout/FlowRowOverflow|null[0]
-    final object Companion { // androidx.compose.foundation.layout/FlowRowOverflow.Companion|null[0]
-        final fun expandIndicator(kotlin/Function1<androidx.compose.foundation.layout/FlowRowOverflowScope, kotlin/Unit>): androidx.compose.foundation.layout/FlowRowOverflow // androidx.compose.foundation.layout/FlowRowOverflow.Companion.expandIndicator|expandIndicator(kotlin.Function1<androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit>){}[0]
-        final fun expandOrCollapseIndicator(kotlin/Function1<androidx.compose.foundation.layout/FlowRowOverflowScope, kotlin/Unit>, kotlin/Function1<androidx.compose.foundation.layout/FlowRowOverflowScope, kotlin/Unit>, kotlin/Int =..., androidx.compose.ui.unit/Dp =...): androidx.compose.foundation.layout/FlowRowOverflow // androidx.compose.foundation.layout/FlowRowOverflow.Companion.expandOrCollapseIndicator|expandOrCollapseIndicator(kotlin.Function1<androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit>;kotlin.Function1<androidx.compose.foundation.layout.FlowRowOverflowScope,kotlin.Unit>;kotlin.Int;androidx.compose.ui.unit.Dp){}[0]
-        final val Clip // androidx.compose.foundation.layout/FlowRowOverflow.Companion.Clip|{}Clip[0]
-            final fun <get-Clip>(): androidx.compose.foundation.layout/FlowRowOverflow // androidx.compose.foundation.layout/FlowRowOverflow.Companion.Clip.<get-Clip>|<get-Clip>(){}[0]
-        final val Visible // androidx.compose.foundation.layout/FlowRowOverflow.Companion.Visible|{}Visible[0]
-            final fun <get-Visible>(): androidx.compose.foundation.layout/FlowRowOverflow // androidx.compose.foundation.layout/FlowRowOverflow.Companion.Visible.<get-Visible>|<get-Visible>(){}[0]
-    }
-}
-final class androidx.compose.foundation.layout/MutableWindowInsets : androidx.compose.foundation.layout/WindowInsets { // androidx.compose.foundation.layout/MutableWindowInsets|null[0]
-    constructor <init>(androidx.compose.foundation.layout/WindowInsets =...) // androidx.compose.foundation.layout/MutableWindowInsets.<init>|<init>(androidx.compose.foundation.layout.WindowInsets){}[0]
-    final fun getBottom(androidx.compose.ui.unit/Density): kotlin/Int // androidx.compose.foundation.layout/MutableWindowInsets.getBottom|getBottom(androidx.compose.ui.unit.Density){}[0]
-    final fun getLeft(androidx.compose.ui.unit/Density, androidx.compose.ui.unit/LayoutDirection): kotlin/Int // androidx.compose.foundation.layout/MutableWindowInsets.getLeft|getLeft(androidx.compose.ui.unit.Density;androidx.compose.ui.unit.LayoutDirection){}[0]
-    final fun getRight(androidx.compose.ui.unit/Density, androidx.compose.ui.unit/LayoutDirection): kotlin/Int // androidx.compose.foundation.layout/MutableWindowInsets.getRight|getRight(androidx.compose.ui.unit.Density;androidx.compose.ui.unit.LayoutDirection){}[0]
-    final fun getTop(androidx.compose.ui.unit/Density): kotlin/Int // androidx.compose.foundation.layout/MutableWindowInsets.getTop|getTop(androidx.compose.ui.unit.Density){}[0]
-    final var insets // androidx.compose.foundation.layout/MutableWindowInsets.insets|{}insets[0]
-        final fun <get-insets>(): androidx.compose.foundation.layout/WindowInsets // androidx.compose.foundation.layout/MutableWindowInsets.insets.<get-insets>|<get-insets>(){}[0]
-        final fun <set-insets>(androidx.compose.foundation.layout/WindowInsets) // androidx.compose.foundation.layout/MutableWindowInsets.insets.<set-insets>|<set-insets>(androidx.compose.foundation.layout.WindowInsets){}[0]
-}
 final enum class androidx.compose.foundation.layout/IntrinsicSize : kotlin/Enum<androidx.compose.foundation.layout/IntrinsicSize> { // androidx.compose.foundation.layout/IntrinsicSize|null[0]
     enum entry Max // androidx.compose.foundation.layout/IntrinsicSize.Max|null[0]
     enum entry Min // androidx.compose.foundation.layout/IntrinsicSize.Min|null[0]
@@ -225,10 +135,6 @@
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.layout/wrapContentWidth(androidx.compose.ui/Alignment.Horizontal =..., kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.foundation.layout/wrapContentWidth|[email protected](androidx.compose.ui.Alignment.Horizontal;kotlin.Boolean){}[0]
 final fun androidx.compose.foundation.layout/Box(androidx.compose.ui/Modifier) // androidx.compose.foundation.layout/Box|Box(androidx.compose.ui.Modifier){}[0]
 final fun androidx.compose.foundation.layout/BoxWithConstraints(androidx.compose.ui/Modifier =..., androidx.compose.ui/Alignment =..., kotlin/Boolean =..., kotlin/Function1<androidx.compose.foundation.layout/BoxWithConstraintsScope, kotlin/Unit>) // androidx.compose.foundation.layout/BoxWithConstraints|BoxWithConstraints(androidx.compose.ui.Modifier;androidx.compose.ui.Alignment;kotlin.Boolean;kotlin.Function1<androidx.compose.foundation.layout.BoxWithConstraintsScope,kotlin.Unit>){}[0]
-final fun androidx.compose.foundation.layout/ContextualFlowColumn(kotlin/Int, androidx.compose.ui/Modifier =..., androidx.compose.foundation.layout/Arrangement.Vertical =..., androidx.compose.foundation.layout/Arrangement.Horizontal =..., kotlin/Int =..., kotlin/Int =..., androidx.compose.foundation.layout/ContextualFlowColumnOverflow =..., kotlin/Function2<androidx.compose.foundation.layout/ContextualFlowColumnScope, kotlin/Int, kotlin/Unit>) // androidx.compose.foundation.layout/ContextualFlowColumn|ContextualFlowColumn(kotlin.Int;androidx.compose.ui.Modifier;androidx.compose.foundation.layout.Arrangement.Vertical;androidx.compose.foundation.layout.Arrangement.Horizontal;kotlin.Int;kotlin.Int;androidx.compose.foundation.layout.ContextualFlowColumnOverflow;kotlin.Function2<androidx.compose.foundation.layout.ContextualFlowColumnScope,kotlin.Int,kotlin.Unit>){}[0]
-final fun androidx.compose.foundation.layout/ContextualFlowRow(kotlin/Int, androidx.compose.ui/Modifier =..., androidx.compose.foundation.layout/Arrangement.Horizontal =..., androidx.compose.foundation.layout/Arrangement.Vertical =..., kotlin/Int =..., kotlin/Int =..., androidx.compose.foundation.layout/ContextualFlowRowOverflow =..., kotlin/Function2<androidx.compose.foundation.layout/ContextualFlowRowScope, kotlin/Int, kotlin/Unit>) // androidx.compose.foundation.layout/ContextualFlowRow|ContextualFlowRow(kotlin.Int;androidx.compose.ui.Modifier;androidx.compose.foundation.layout.Arrangement.Horizontal;androidx.compose.foundation.layout.Arrangement.Vertical;kotlin.Int;kotlin.Int;androidx.compose.foundation.layout.ContextualFlowRowOverflow;kotlin.Function2<androidx.compose.foundation.layout.ContextualFlowRowScope,kotlin.Int,kotlin.Unit>){}[0]
-final fun androidx.compose.foundation.layout/FlowColumn(androidx.compose.ui/Modifier =..., androidx.compose.foundation.layout/Arrangement.Vertical =..., androidx.compose.foundation.layout/Arrangement.Horizontal =..., kotlin/Int =..., kotlin/Int =..., androidx.compose.foundation.layout/FlowColumnOverflow =..., kotlin/Function1<androidx.compose.foundation.layout/FlowColumnScope, kotlin/Unit>) // androidx.compose.foundation.layout/FlowColumn|FlowColumn(androidx.compose.ui.Modifier;androidx.compose.foundation.layout.Arrangement.Vertical;androidx.compose.foundation.layout.Arrangement.Horizontal;kotlin.Int;kotlin.Int;androidx.compose.foundation.layout.FlowColumnOverflow;kotlin.Function1<androidx.compose.foundation.layout.FlowColumnScope,kotlin.Unit>){}[0]
-final fun androidx.compose.foundation.layout/FlowRow(androidx.compose.ui/Modifier =..., androidx.compose.foundation.layout/Arrangement.Horizontal =..., androidx.compose.foundation.layout/Arrangement.Vertical =..., kotlin/Int =..., kotlin/Int =..., androidx.compose.foundation.layout/FlowRowOverflow =..., kotlin/Function1<androidx.compose.foundation.layout/FlowRowScope, kotlin/Unit>) // androidx.compose.foundation.layout/FlowRow|FlowRow(androidx.compose.ui.Modifier;androidx.compose.foundation.layout.Arrangement.Horizontal;androidx.compose.foundation.layout.Arrangement.Vertical;kotlin.Int;kotlin.Int;androidx.compose.foundation.layout.FlowRowOverflow;kotlin.Function1<androidx.compose.foundation.layout.FlowRowScope,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.layout/PaddingValues(androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =...): androidx.compose.foundation.layout/PaddingValues // androidx.compose.foundation.layout/PaddingValues|PaddingValues(androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp){}[0]
 final fun androidx.compose.foundation.layout/PaddingValues(androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =...): androidx.compose.foundation.layout/PaddingValues // androidx.compose.foundation.layout/PaddingValues|PaddingValues(androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp){}[0]
 final fun androidx.compose.foundation.layout/PaddingValues(androidx.compose.ui.unit/Dp): androidx.compose.foundation.layout/PaddingValues // androidx.compose.foundation.layout/PaddingValues|PaddingValues(androidx.compose.ui.unit.Dp){}[0]
@@ -359,6 +265,3 @@
 open annotation class androidx.compose.foundation.layout/LayoutScopeMarker : kotlin/Annotation { // androidx.compose.foundation.layout/LayoutScopeMarker|null[0]
     constructor <init>() // androidx.compose.foundation.layout/LayoutScopeMarker.<init>|<init>(){}[0]
 }
-sealed class androidx.compose.foundation.layout/FlowLayoutOverflow { // androidx.compose.foundation.layout/FlowLayoutOverflow|null[0]
-    constructor <init>(androidx.compose.foundation.layout/FlowLayoutOverflow.OverflowType, kotlin/Int =..., kotlin/Int =..., kotlin/Function1<androidx.compose.foundation.layout/FlowLayoutOverflowState, kotlin/Function0<kotlin/Unit>>? =..., kotlin/Function1<androidx.compose.foundation.layout/FlowLayoutOverflowState, kotlin/Function0<kotlin/Unit>>? =...) // androidx.compose.foundation.layout/FlowLayoutOverflow.<init>|<init>(androidx.compose.foundation.layout.FlowLayoutOverflow.OverflowType;kotlin.Int;kotlin.Int;kotlin.Function1<androidx.compose.foundation.layout.FlowLayoutOverflowState,kotlin.Function0<kotlin.Unit>>?;kotlin.Function1<androidx.compose.foundation.layout.FlowLayoutOverflowState,kotlin.Function0<kotlin.Unit>>?){}[0]
-}
diff --git a/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/RectsInFlowColumnTestCase.kt b/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/RectsInFlowColumnTestCase.kt
index cf87c54..0a91b17 100644
--- a/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/RectsInFlowColumnTestCase.kt
+++ b/compose/foundation/foundation-layout/benchmark/src/androidTest/java/androidx/compose/foundation/layout/benchmark/RectsInFlowColumnTestCase.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 20 The Android Open Source Project
+ * Copyright 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/compose/foundation/foundation-layout/build.gradle b/compose/foundation/foundation-layout/build.gradle
index 54dd48b..a90bb95 100644
--- a/compose/foundation/foundation-layout/build.gradle
+++ b/compose/foundation/foundation-layout/build.gradle
@@ -28,31 +28,12 @@
 
 plugins {
     id("AndroidXPlugin")
+    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    androidLibrary {
-        namespace = "androidx.compose.foundation.layout"
-        withAndroidTestOnDeviceBuilder {
-            it.compilationName = "instrumentedTest"
-            it.defaultSourceSetName = "androidInstrumentedTest"
-            it.sourceSetTreeName = "test"
-        }
-        withAndroidTestOnJvmBuilder {
-            it.defaultSourceSetName = "androidUnitTest"
-        }
-
-        compileSdk = 35
-        aarMetadata.minCompileSdk = 35
-
-        optimization {
-            it.consumerKeepRules.publish = true
-            it.consumerKeepRules.files.add(
-                new File(project.projectDir, "proguard-rules.pro")
-            )
-        }
-    }
+    android()
     jvmStubs()
     linuxX64Stubs()
 
@@ -141,3 +122,10 @@
     kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
+android {
+    compileSdk 35
+    namespace "androidx.compose.foundation.layout"
+    buildTypes.configureEach {
+        consumerProguardFiles("proguard-rules.pro")
+    }
+}
diff --git a/compose/foundation/foundation/bcv/native/1.7.0.txt b/compose/foundation/foundation/bcv/native/1.7.0.txt
index fe430df..bea6859 100644
--- a/compose/foundation/foundation/bcv/native/1.7.0.txt
+++ b/compose/foundation/foundation/bcv/native/1.7.0.txt
@@ -6,28 +6,10 @@
 // - Show declarations: true
 
 // Library unique name: <androidx.compose.foundation:foundation>
-abstract class <#A: androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.Interval> androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent { // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent|null[0]
-    abstract interface Interval { // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.Interval|null[0]
-        open val key // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.Interval.key|<get-key>(){}[0]
-            open fun <get-key>(): kotlin/Function1<kotlin/Int, kotlin/Any>? // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.Interval.key.<get-key>|<get-key>(){}[0]
-        open val type // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.Interval.type|<get-type>(){}[0]
-            open fun <get-type>(): kotlin/Function1<kotlin/Int, kotlin/Any?> // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.Interval.type.<get-type>|<get-type>(){}[0]
-    }
-    abstract val intervals // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.intervals|{}intervals[0]
-        abstract fun <get-intervals>(): androidx.compose.foundation.lazy.layout/IntervalList<#A> // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.intervals.<get-intervals>|<get-intervals>(){}[0]
-    constructor <init>() // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.<init>|<init>(){}[0]
-    final fun getContentType(kotlin/Int): kotlin/Any? // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.getContentType|getContentType(kotlin.Int){}[0]
-    final fun getKey(kotlin/Int): kotlin/Any // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.getKey|getKey(kotlin.Int){}[0]
-    final inline fun <#A1: kotlin/Any?> withInterval(kotlin/Int, kotlin/Function2<kotlin/Int, #A, #A1>): #A1 // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.withInterval|withInterval(kotlin.Int;kotlin.Function2<kotlin.Int,1:0,0:0>){0§<kotlin.Any?>}[0]
-    final val itemCount // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.itemCount|{}itemCount[0]
-        final fun <get-itemCount>(): kotlin/Int // androidx.compose.foundation.lazy.layout/LazyLayoutIntervalContent.itemCount.<get-itemCount>|<get-itemCount>(){}[0]
-}
 abstract class androidx.compose.foundation.pager/PagerState : androidx.compose.foundation.gestures/ScrollableState { // androidx.compose.foundation.pager/PagerState|null[0]
     abstract val pageCount // androidx.compose.foundation.pager/PagerState.pageCount|<get-pageCount>(){}[0]
         abstract fun <get-pageCount>(): kotlin/Int // androidx.compose.foundation.pager/PagerState.pageCount.<get-pageCount>|<get-pageCount>(){}[0]
     constructor <init>(kotlin/Int =..., kotlin/Float =...) // androidx.compose.foundation.pager/PagerState.<init>|<init>(kotlin.Int;kotlin.Float){}[0]
-    final fun (androidx.compose.foundation.gestures/ScrollScope).updateCurrentPage(kotlin/Int, kotlin/Float =...) // androidx.compose.foundation.pager/PagerState.updateCurrentPage|updateCurrentPage@androidx.compose.foundation.gestures.ScrollScope(kotlin.Int;kotlin.Float){}[0]
-    final fun (androidx.compose.foundation.gestures/ScrollScope).updateTargetPage(kotlin/Int) // androidx.compose.foundation.pager/PagerState.updateTargetPage|updateTargetPage@androidx.compose.foundation.gestures.ScrollScope(kotlin.Int){}[0]
     final fun getOffsetDistanceInPages(kotlin/Int): kotlin/Float // androidx.compose.foundation.pager/PagerState.getOffsetDistanceInPages|getOffsetDistanceInPages(kotlin.Int){}[0]
     final fun requestScrollToPage(kotlin/Int, kotlin/Float =...) // androidx.compose.foundation.pager/PagerState.requestScrollToPage|requestScrollToPage(kotlin.Int;kotlin.Float){}[0]
     final suspend fun animateScrollToPage(kotlin/Int, kotlin/Float =..., androidx.compose.animation.core/AnimationSpec<kotlin/Float> =...) // androidx.compose.foundation.pager/PagerState.animateScrollToPage|animateScrollToPage(kotlin.Int;kotlin.Float;androidx.compose.animation.core.AnimationSpec<kotlin.Float>){}[0]
@@ -72,13 +54,6 @@
     final val topStart // androidx.compose.foundation.shape/CornerBasedShape.topStart|{}topStart[0]
         final fun <get-topStart>(): androidx.compose.foundation.shape/CornerSize // androidx.compose.foundation.shape/CornerBasedShape.topStart.<get-topStart>|<get-topStart>(){}[0]
 }
-abstract fun interface androidx.compose.foundation.content/ReceiveContentListener { // androidx.compose.foundation.content/ReceiveContentListener|null[0]
-    abstract fun onReceive(androidx.compose.foundation.content/TransferableContent): androidx.compose.foundation.content/TransferableContent? // androidx.compose.foundation.content/ReceiveContentListener.onReceive|onReceive(androidx.compose.foundation.content.TransferableContent){}[0]
-    open fun onDragEnd() // androidx.compose.foundation.content/ReceiveContentListener.onDragEnd|onDragEnd(){}[0]
-    open fun onDragEnter() // androidx.compose.foundation.content/ReceiveContentListener.onDragEnter|onDragEnter(){}[0]
-    open fun onDragExit() // androidx.compose.foundation.content/ReceiveContentListener.onDragExit|onDragExit(){}[0]
-    open fun onDragStart() // androidx.compose.foundation.content/ReceiveContentListener.onDragStart|onDragStart(){}[0]
-}
 abstract fun interface androidx.compose.foundation.text.input/InputTransformation { // androidx.compose.foundation.text.input/InputTransformation|null[0]
     abstract fun (androidx.compose.foundation.text.input/TextFieldBuffer).transformInput() // androidx.compose.foundation.text.input/InputTransformation.transformInput|transformInput@androidx.compose.foundation.text.input.TextFieldBuffer(){}[0]
     final object Companion : androidx.compose.foundation.text.input/InputTransformation { // androidx.compose.foundation.text.input/InputTransformation.Companion|null[0]
@@ -103,20 +78,6 @@
         final fun fractionOfContainer(kotlin/Float): androidx.compose.foundation/MarqueeSpacing // androidx.compose.foundation/MarqueeSpacing.Companion.fractionOfContainer|fractionOfContainer(kotlin.Float){}[0]
     }
 }
-abstract interface <#A: kotlin/Any?> androidx.compose.foundation.gestures/DraggableAnchors { // androidx.compose.foundation.gestures/DraggableAnchors|null[0]
-    abstract fun closestAnchor(kotlin/Float): #A? // androidx.compose.foundation.gestures/DraggableAnchors.closestAnchor|closestAnchor(kotlin.Float){}[0]
-    abstract fun closestAnchor(kotlin/Float, kotlin/Boolean): #A? // androidx.compose.foundation.gestures/DraggableAnchors.closestAnchor|closestAnchor(kotlin.Float;kotlin.Boolean){}[0]
-    abstract fun forEach(kotlin/Function2<#A, kotlin/Float, kotlin/Unit>) // androidx.compose.foundation.gestures/DraggableAnchors.forEach|forEach(kotlin.Function2<1:0,kotlin.Float,kotlin.Unit>){}[0]
-    abstract fun hasAnchorFor(#A): kotlin/Boolean // androidx.compose.foundation.gestures/DraggableAnchors.hasAnchorFor|hasAnchorFor(1:0){}[0]
-    abstract fun maxAnchor(): kotlin/Float // androidx.compose.foundation.gestures/DraggableAnchors.maxAnchor|maxAnchor(){}[0]
-    abstract fun minAnchor(): kotlin/Float // androidx.compose.foundation.gestures/DraggableAnchors.minAnchor|minAnchor(){}[0]
-    abstract fun positionOf(#A): kotlin/Float // androidx.compose.foundation.gestures/DraggableAnchors.positionOf|positionOf(1:0){}[0]
-    abstract val size // androidx.compose.foundation.gestures/DraggableAnchors.size|{}size[0]
-        abstract fun <get-size>(): kotlin/Int // androidx.compose.foundation.gestures/DraggableAnchors.size.<get-size>|<get-size>(){}[0]
-}
-abstract interface androidx.compose.foundation.draganddrop/DragAndDropSourceScope : androidx.compose.ui.input.pointer/PointerInputScope { // androidx.compose.foundation.draganddrop/DragAndDropSourceScope|null[0]
-    abstract fun startTransfer(androidx.compose.ui.draganddrop/DragAndDropTransferData) // androidx.compose.foundation.draganddrop/DragAndDropSourceScope.startTransfer|startTransfer(androidx.compose.ui.draganddrop.DragAndDropTransferData){}[0]
-}
 abstract interface androidx.compose.foundation.gestures.snapping/SnapLayoutInfoProvider { // androidx.compose.foundation.gestures.snapping/SnapLayoutInfoProvider|null[0]
     abstract fun calculateSnapOffset(kotlin/Float): kotlin/Float // androidx.compose.foundation.gestures.snapping/SnapLayoutInfoProvider.calculateSnapOffset|calculateSnapOffset(kotlin.Float){}[0]
     open fun calculateApproachOffset(kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.foundation.gestures.snapping/SnapLayoutInfoProvider.calculateApproachOffset|calculateApproachOffset(kotlin.Float;kotlin.Float){}[0]
@@ -136,28 +97,9 @@
         final fun toString(): kotlin/String // androidx.compose.foundation.gestures.snapping/SnapPosition.Start.toString|toString(){}[0]
     }
 }
-abstract interface androidx.compose.foundation.gestures/AnchoredDragScope { // androidx.compose.foundation.gestures/AnchoredDragScope|null[0]
-    abstract fun dragTo(kotlin/Float, kotlin/Float =...) // androidx.compose.foundation.gestures/AnchoredDragScope.dragTo|dragTo(kotlin.Float;kotlin.Float){}[0]
-}
-abstract interface androidx.compose.foundation.gestures/BringIntoViewSpec { // androidx.compose.foundation.gestures/BringIntoViewSpec|null[0]
-    final object Companion { // androidx.compose.foundation.gestures/BringIntoViewSpec.Companion|null[0]
-        final val DefaultScrollAnimationSpec // androidx.compose.foundation.gestures/BringIntoViewSpec.Companion.DefaultScrollAnimationSpec|<get-DefaultScrollAnimationSpec>(){}[0]
-            final fun <get-DefaultScrollAnimationSpec>(): androidx.compose.animation.core/AnimationSpec<kotlin/Float> // androidx.compose.foundation.gestures/BringIntoViewSpec.Companion.DefaultScrollAnimationSpec.<get-DefaultScrollAnimationSpec>|<get-DefaultScrollAnimationSpec>(){}[0]
-    }
-    open fun calculateScrollDistance(kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.foundation.gestures/BringIntoViewSpec.calculateScrollDistance|calculateScrollDistance(kotlin.Float;kotlin.Float;kotlin.Float){}[0]
-    open val scrollAnimationSpec // androidx.compose.foundation.gestures/BringIntoViewSpec.scrollAnimationSpec|{}scrollAnimationSpec[0]
-        open fun <get-scrollAnimationSpec>(): androidx.compose.animation.core/AnimationSpec<kotlin/Float> // androidx.compose.foundation.gestures/BringIntoViewSpec.scrollAnimationSpec.<get-scrollAnimationSpec>|<get-scrollAnimationSpec>(){}[0]
-}
-abstract interface androidx.compose.foundation.gestures/Drag2DScope { // androidx.compose.foundation.gestures/Drag2DScope|null[0]
-    abstract fun dragBy(androidx.compose.ui.geometry/Offset) // androidx.compose.foundation.gestures/Drag2DScope.dragBy|dragBy(androidx.compose.ui.geometry.Offset){}[0]
-}
 abstract interface androidx.compose.foundation.gestures/DragScope { // androidx.compose.foundation.gestures/DragScope|null[0]
     abstract fun dragBy(kotlin/Float) // androidx.compose.foundation.gestures/DragScope.dragBy|dragBy(kotlin.Float){}[0]
 }
-abstract interface androidx.compose.foundation.gestures/Draggable2DState { // androidx.compose.foundation.gestures/Draggable2DState|null[0]
-    abstract fun dispatchRawDelta(androidx.compose.ui.geometry/Offset) // androidx.compose.foundation.gestures/Draggable2DState.dispatchRawDelta|dispatchRawDelta(androidx.compose.ui.geometry.Offset){}[0]
-    abstract suspend fun drag(androidx.compose.foundation/MutatePriority =..., kotlin.coroutines/SuspendFunction1<androidx.compose.foundation.gestures/Drag2DScope, kotlin/Unit>) // androidx.compose.foundation.gestures/Draggable2DState.drag|drag(androidx.compose.foundation.MutatePriority;kotlin.coroutines.SuspendFunction1<androidx.compose.foundation.gestures.Drag2DScope,kotlin.Unit>){}[0]
-}
 abstract interface androidx.compose.foundation.gestures/DraggableState { // androidx.compose.foundation.gestures/DraggableState|null[0]
     abstract fun dispatchRawDelta(kotlin/Float) // androidx.compose.foundation.gestures/DraggableState.dispatchRawDelta|dispatchRawDelta(kotlin.Float){}[0]
     abstract suspend fun drag(androidx.compose.foundation/MutatePriority =..., kotlin.coroutines/SuspendFunction1<androidx.compose.foundation.gestures/DragScope, kotlin/Unit>) // androidx.compose.foundation.gestures/DraggableState.drag|drag(androidx.compose.foundation.MutatePriority;kotlin.coroutines.SuspendFunction1<androidx.compose.foundation.gestures.DragScope,kotlin.Unit>){}[0]
@@ -280,30 +222,6 @@
         final fun hashCode(): kotlin/Int // androidx.compose.foundation.lazy.grid/GridCells.FixedSize.hashCode|hashCode(){}[0]
     }
 }
-abstract interface androidx.compose.foundation.lazy.grid/LazyGridPrefetchScope { // androidx.compose.foundation.lazy.grid/LazyGridPrefetchScope|null[0]
-    abstract fun scheduleLinePrefetch(kotlin/Int): kotlin.collections/List<androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState.PrefetchHandle> // androidx.compose.foundation.lazy.grid/LazyGridPrefetchScope.scheduleLinePrefetch|scheduleLinePrefetch(kotlin.Int){}[0]
-}
-abstract interface androidx.compose.foundation.lazy.grid/LazyGridPrefetchStrategy { // androidx.compose.foundation.lazy.grid/LazyGridPrefetchStrategy|null[0]
-    abstract fun (androidx.compose.foundation.lazy.grid/LazyGridPrefetchScope).onScroll(kotlin/Float, androidx.compose.foundation.lazy.grid/LazyGridLayoutInfo) // androidx.compose.foundation.lazy.grid/LazyGridPrefetchStrategy.onScroll|onScroll@androidx.compose.foundation.lazy.grid.LazyGridPrefetchScope(kotlin.Float;androidx.compose.foundation.lazy.grid.LazyGridLayoutInfo){}[0]
-    abstract fun (androidx.compose.foundation.lazy.grid/LazyGridPrefetchScope).onVisibleItemsUpdated(androidx.compose.foundation.lazy.grid/LazyGridLayoutInfo) // androidx.compose.foundation.lazy.grid/LazyGridPrefetchStrategy.onVisibleItemsUpdated|onVisibleItemsUpdated@androidx.compose.foundation.lazy.grid.LazyGridPrefetchScope(androidx.compose.foundation.lazy.grid.LazyGridLayoutInfo){}[0]
-    abstract fun (androidx.compose.foundation.lazy.layout/NestedPrefetchScope).onNestedPrefetch(kotlin/Int) // androidx.compose.foundation.lazy.grid/LazyGridPrefetchStrategy.onNestedPrefetch|onNestedPrefetch@androidx.compose.foundation.lazy.layout.NestedPrefetchScope(kotlin.Int){}[0]
-    open val prefetchScheduler // androidx.compose.foundation.lazy.grid/LazyGridPrefetchStrategy.prefetchScheduler|{}prefetchScheduler[0]
-        open fun <get-prefetchScheduler>(): androidx.compose.foundation.lazy.layout/PrefetchScheduler? // androidx.compose.foundation.lazy.grid/LazyGridPrefetchStrategy.prefetchScheduler.<get-prefetchScheduler>|<get-prefetchScheduler>(){}[0]
-}
-abstract interface androidx.compose.foundation.lazy.layout/LazyLayoutItemProvider { // androidx.compose.foundation.lazy.layout/LazyLayoutItemProvider|null[0]
-    abstract fun Item(kotlin/Int, kotlin/Any) // androidx.compose.foundation.lazy.layout/LazyLayoutItemProvider.Item|Item(kotlin.Int;kotlin.Any){}[0]
-    abstract val itemCount // androidx.compose.foundation.lazy.layout/LazyLayoutItemProvider.itemCount|{}itemCount[0]
-        abstract fun <get-itemCount>(): kotlin/Int // androidx.compose.foundation.lazy.layout/LazyLayoutItemProvider.itemCount.<get-itemCount>|<get-itemCount>(){}[0]
-    open fun getContentType(kotlin/Int): kotlin/Any? // androidx.compose.foundation.lazy.layout/LazyLayoutItemProvider.getContentType|getContentType(kotlin.Int){}[0]
-    open fun getIndex(kotlin/Any): kotlin/Int // androidx.compose.foundation.lazy.layout/LazyLayoutItemProvider.getIndex|getIndex(kotlin.Any){}[0]
-    open fun getKey(kotlin/Int): kotlin/Any // androidx.compose.foundation.lazy.layout/LazyLayoutItemProvider.getKey|getKey(kotlin.Int){}[0]
-}
-abstract interface androidx.compose.foundation.lazy.layout/PrefetchRequestScope { // androidx.compose.foundation.lazy.layout/PrefetchRequestScope|null[0]
-    abstract fun availableTimeNanos(): kotlin/Long // androidx.compose.foundation.lazy.layout/PrefetchRequestScope.availableTimeNanos|availableTimeNanos(){}[0]
-}
-abstract interface androidx.compose.foundation.lazy.layout/PrefetchScheduler { // androidx.compose.foundation.lazy.layout/PrefetchScheduler|null[0]
-    abstract fun schedulePrefetch(androidx.compose.foundation.lazy.layout/PrefetchRequest) // androidx.compose.foundation.lazy.layout/PrefetchScheduler.schedulePrefetch|schedulePrefetch(androidx.compose.foundation.lazy.layout.PrefetchRequest){}[0]
-}
 abstract interface androidx.compose.foundation.lazy.staggeredgrid/StaggeredGridCells { // androidx.compose.foundation.lazy.staggeredgrid/StaggeredGridCells|null[0]
     abstract fun (androidx.compose.ui.unit/Density).calculateCrossAxisCellSizes(kotlin/Int, kotlin/Int): kotlin/IntArray // androidx.compose.foundation.lazy.staggeredgrid/StaggeredGridCells.calculateCrossAxisCellSizes|[email protected](kotlin.Int;kotlin.Int){}[0]
     final class Adaptive : androidx.compose.foundation.lazy.staggeredgrid/StaggeredGridCells { // androidx.compose.foundation.lazy.staggeredgrid/StaggeredGridCells.Adaptive|null[0]
@@ -330,7 +248,6 @@
     abstract fun (androidx.compose.ui/Modifier).fillParentMaxSize(kotlin/Float =...): androidx.compose.ui/Modifier // androidx.compose.foundation.lazy/LazyItemScope.fillParentMaxSize|[email protected](kotlin.Float){}[0]
     abstract fun (androidx.compose.ui/Modifier).fillParentMaxWidth(kotlin/Float =...): androidx.compose.ui/Modifier // androidx.compose.foundation.lazy/LazyItemScope.fillParentMaxWidth|[email protected](kotlin.Float){}[0]
     open fun (androidx.compose.ui/Modifier).animateItem(androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float>? =..., androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntOffset>? =..., androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float>? =...): androidx.compose.ui/Modifier // androidx.compose.foundation.lazy/LazyItemScope.animateItem|[email protected](androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>?;androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>?;androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>?){}[0]
-    open fun (androidx.compose.ui/Modifier).animateItemPlacement(androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntOffset> =...): androidx.compose.ui/Modifier // androidx.compose.foundation.lazy/LazyItemScope.animateItemPlacement|[email protected](androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>){}[0]
 }
 abstract interface androidx.compose.foundation.lazy/LazyListItemInfo { // androidx.compose.foundation.lazy/LazyListItemInfo|null[0]
     abstract val index // androidx.compose.foundation.lazy/LazyListItemInfo.index|{}index[0]
@@ -366,18 +283,7 @@
     open val viewportSize // androidx.compose.foundation.lazy/LazyListLayoutInfo.viewportSize|{}viewportSize[0]
         open fun <get-viewportSize>(): androidx.compose.ui.unit/IntSize // androidx.compose.foundation.lazy/LazyListLayoutInfo.viewportSize.<get-viewportSize>|<get-viewportSize>(){}[0]
 }
-abstract interface androidx.compose.foundation.lazy/LazyListPrefetchScope { // androidx.compose.foundation.lazy/LazyListPrefetchScope|null[0]
-    abstract fun schedulePrefetch(kotlin/Int): androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState.PrefetchHandle // androidx.compose.foundation.lazy/LazyListPrefetchScope.schedulePrefetch|schedulePrefetch(kotlin.Int){}[0]
-}
-abstract interface androidx.compose.foundation.lazy/LazyListPrefetchStrategy { // androidx.compose.foundation.lazy/LazyListPrefetchStrategy|null[0]
-    abstract fun (androidx.compose.foundation.lazy.layout/NestedPrefetchScope).onNestedPrefetch(kotlin/Int) // androidx.compose.foundation.lazy/LazyListPrefetchStrategy.onNestedPrefetch|onNestedPrefetch@androidx.compose.foundation.lazy.layout.NestedPrefetchScope(kotlin.Int){}[0]
-    abstract fun (androidx.compose.foundation.lazy/LazyListPrefetchScope).onScroll(kotlin/Float, androidx.compose.foundation.lazy/LazyListLayoutInfo) // androidx.compose.foundation.lazy/LazyListPrefetchStrategy.onScroll|[email protected](kotlin.Float;androidx.compose.foundation.lazy.LazyListLayoutInfo){}[0]
-    abstract fun (androidx.compose.foundation.lazy/LazyListPrefetchScope).onVisibleItemsUpdated(androidx.compose.foundation.lazy/LazyListLayoutInfo) // androidx.compose.foundation.lazy/LazyListPrefetchStrategy.onVisibleItemsUpdated|onVisibleItemsUpdated@androidx.compose.foundation.lazy.LazyListPrefetchScope(androidx.compose.foundation.lazy.LazyListLayoutInfo){}[0]
-    open val prefetchScheduler // androidx.compose.foundation.lazy/LazyListPrefetchStrategy.prefetchScheduler|{}prefetchScheduler[0]
-        open fun <get-prefetchScheduler>(): androidx.compose.foundation.lazy.layout/PrefetchScheduler? // androidx.compose.foundation.lazy/LazyListPrefetchStrategy.prefetchScheduler.<get-prefetchScheduler>|<get-prefetchScheduler>(){}[0]
-}
 abstract interface androidx.compose.foundation.lazy/LazyListScope { // androidx.compose.foundation.lazy/LazyListScope|null[0]
-    abstract fun stickyHeader(kotlin/Any? =..., kotlin/Any? =..., kotlin/Function1<androidx.compose.foundation.lazy/LazyItemScope, kotlin/Unit>) // androidx.compose.foundation.lazy/LazyListScope.stickyHeader|stickyHeader(kotlin.Any?;kotlin.Any?;kotlin.Function1<androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit>){}[0]
     open fun item(kotlin/Any? =..., kotlin/Any? =..., kotlin/Function1<androidx.compose.foundation.lazy/LazyItemScope, kotlin/Unit>) // androidx.compose.foundation.lazy/LazyListScope.item|item(kotlin.Any?;kotlin.Any?;kotlin.Function1<androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit>){}[0]
     open fun item(kotlin/Any? =..., kotlin/Function1<androidx.compose.foundation.lazy/LazyItemScope, kotlin/Unit>) // androidx.compose.foundation.lazy/LazyListScope.item|item(kotlin.Any?;kotlin.Function1<androidx.compose.foundation.lazy.LazyItemScope,kotlin.Unit>){}[0]
     open fun items(kotlin/Int, kotlin/Function1<kotlin/Int, kotlin/Any>? =..., kotlin/Function1<kotlin/Int, kotlin/Any?> =..., kotlin/Function2<androidx.compose.foundation.lazy/LazyItemScope, kotlin/Int, kotlin/Unit>) // androidx.compose.foundation.lazy/LazyListScope.items|items(kotlin.Int;kotlin.Function1<kotlin.Int,kotlin.Any>?;kotlin.Function1<kotlin.Int,kotlin.Any?>;kotlin.Function2<androidx.compose.foundation.lazy.LazyItemScope,kotlin.Int,kotlin.Unit>){}[0]
@@ -403,25 +309,12 @@
         final fun atMost(kotlin/Int): androidx.compose.foundation.pager/PagerSnapDistance // androidx.compose.foundation.pager/PagerSnapDistance.Companion.atMost|atMost(kotlin.Int){}[0]
     }
 }
-abstract interface androidx.compose.foundation.relocation/BringIntoViewResponder { // androidx.compose.foundation.relocation/BringIntoViewResponder|null[0]
-    abstract fun calculateRectForParent(androidx.compose.ui.geometry/Rect): androidx.compose.ui.geometry/Rect // androidx.compose.foundation.relocation/BringIntoViewResponder.calculateRectForParent|calculateRectForParent(androidx.compose.ui.geometry.Rect){}[0]
-    abstract suspend fun bringChildIntoView(kotlin/Function0<androidx.compose.ui.geometry/Rect?>) // androidx.compose.foundation.relocation/BringIntoViewResponder.bringChildIntoView|bringChildIntoView(kotlin.Function0<androidx.compose.ui.geometry.Rect?>){}[0]
-}
 abstract interface androidx.compose.foundation.shape/CornerSize { // androidx.compose.foundation.shape/CornerSize|null[0]
     abstract fun toPx(androidx.compose.ui.geometry/Size, androidx.compose.ui.unit/Density): kotlin/Float // androidx.compose.foundation.shape/CornerSize.toPx|toPx(androidx.compose.ui.geometry.Size;androidx.compose.ui.unit.Density){}[0]
 }
 abstract interface androidx.compose.foundation.text/KeyboardActionScope { // androidx.compose.foundation.text/KeyboardActionScope|null[0]
     abstract fun defaultKeyboardAction(androidx.compose.ui.text.input/ImeAction) // androidx.compose.foundation.text/KeyboardActionScope.defaultKeyboardAction|defaultKeyboardAction(androidx.compose.ui.text.input.ImeAction){}[0]
 }
-abstract interface androidx.compose.foundation/BasicTooltipState { // androidx.compose.foundation/BasicTooltipState|null[0]
-    abstract fun dismiss() // androidx.compose.foundation/BasicTooltipState.dismiss|dismiss(){}[0]
-    abstract fun onDispose() // androidx.compose.foundation/BasicTooltipState.onDispose|onDispose(){}[0]
-    abstract suspend fun show(androidx.compose.foundation/MutatePriority =...) // androidx.compose.foundation/BasicTooltipState.show|show(androidx.compose.foundation.MutatePriority){}[0]
-    abstract val isPersistent // androidx.compose.foundation/BasicTooltipState.isPersistent|<get-isPersistent>(){}[0]
-        abstract fun <get-isPersistent>(): kotlin/Boolean // androidx.compose.foundation/BasicTooltipState.isPersistent.<get-isPersistent>|<get-isPersistent>(){}[0]
-    abstract val isVisible // androidx.compose.foundation/BasicTooltipState.isVisible|<get-isVisible>(){}[0]
-        abstract fun <get-isVisible>(): kotlin/Boolean // androidx.compose.foundation/BasicTooltipState.isVisible.<get-isVisible>|<get-isVisible>(){}[0]
-}
 abstract interface androidx.compose.foundation/Indication { // androidx.compose.foundation/Indication|null[0]
     open fun rememberUpdatedInstance(androidx.compose.foundation.interaction/InteractionSource): androidx.compose.foundation/IndicationInstance // androidx.compose.foundation/Indication.rememberUpdatedInstance|rememberUpdatedInstance(androidx.compose.foundation.interaction.InteractionSource){}[0]
 }
@@ -433,60 +326,6 @@
     abstract fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.foundation/IndicationNodeFactory.equals|equals(kotlin.Any?){}[0]
     abstract fun hashCode(): kotlin/Int // androidx.compose.foundation/IndicationNodeFactory.hashCode|hashCode(){}[0]
 }
-abstract interface androidx.compose.foundation/OverscrollEffect { // androidx.compose.foundation/OverscrollEffect|null[0]
-    abstract fun applyToScroll(androidx.compose.ui.geometry/Offset, androidx.compose.ui.input.nestedscroll/NestedScrollSource, kotlin/Function1<androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset>): androidx.compose.ui.geometry/Offset // androidx.compose.foundation/OverscrollEffect.applyToScroll|applyToScroll(androidx.compose.ui.geometry.Offset;androidx.compose.ui.input.nestedscroll.NestedScrollSource;kotlin.Function1<androidx.compose.ui.geometry.Offset,androidx.compose.ui.geometry.Offset>){}[0]
-    abstract suspend fun applyToFling(androidx.compose.ui.unit/Velocity, kotlin.coroutines/SuspendFunction1<androidx.compose.ui.unit/Velocity, androidx.compose.ui.unit/Velocity>) // androidx.compose.foundation/OverscrollEffect.applyToFling|applyToFling(androidx.compose.ui.unit.Velocity;kotlin.coroutines.SuspendFunction1<androidx.compose.ui.unit.Velocity,androidx.compose.ui.unit.Velocity>){}[0]
-    abstract val effectModifier // androidx.compose.foundation/OverscrollEffect.effectModifier|{}effectModifier[0]
-        abstract fun <get-effectModifier>(): androidx.compose.ui/Modifier // androidx.compose.foundation/OverscrollEffect.effectModifier.<get-effectModifier>|<get-effectModifier>(){}[0]
-    abstract val isInProgress // androidx.compose.foundation/OverscrollEffect.isInProgress|{}isInProgress[0]
-        abstract fun <get-isInProgress>(): kotlin/Boolean // androidx.compose.foundation/OverscrollEffect.isInProgress.<get-isInProgress>|<get-isInProgress>(){}[0]
-}
-final class <#A: kotlin/Any?> androidx.compose.foundation.gestures/AnchoredDraggableState { // androidx.compose.foundation.gestures/AnchoredDraggableState|null[0]
-    constructor <init>(#A, androidx.compose.foundation.gestures/DraggableAnchors<#A>, kotlin/Function1<kotlin/Float, kotlin/Float>, kotlin/Function0<kotlin/Float>, androidx.compose.animation.core/AnimationSpec<kotlin/Float>, androidx.compose.animation.core/DecayAnimationSpec<kotlin/Float>, kotlin/Function1<#A, kotlin/Boolean> =...) // androidx.compose.foundation.gestures/AnchoredDraggableState.<init>|<init>(1:0;androidx.compose.foundation.gestures.DraggableAnchors<1:0>;kotlin.Function1<kotlin.Float,kotlin.Float>;kotlin.Function0<kotlin.Float>;androidx.compose.animation.core.AnimationSpec<kotlin.Float>;androidx.compose.animation.core.DecayAnimationSpec<kotlin.Float>;kotlin.Function1<1:0,kotlin.Boolean>){}[0]
-    constructor <init>(#A, kotlin/Function1<kotlin/Float, kotlin/Float>, kotlin/Function0<kotlin/Float>, androidx.compose.animation.core/AnimationSpec<kotlin/Float>, androidx.compose.animation.core/DecayAnimationSpec<kotlin/Float>, kotlin/Function1<#A, kotlin/Boolean> =...) // androidx.compose.foundation.gestures/AnchoredDraggableState.<init>|<init>(1:0;kotlin.Function1<kotlin.Float,kotlin.Float>;kotlin.Function0<kotlin.Float>;androidx.compose.animation.core.AnimationSpec<kotlin.Float>;androidx.compose.animation.core.DecayAnimationSpec<kotlin.Float>;kotlin.Function1<1:0,kotlin.Boolean>){}[0]
-    final fun dispatchRawDelta(kotlin/Float): kotlin/Float // androidx.compose.foundation.gestures/AnchoredDraggableState.dispatchRawDelta|dispatchRawDelta(kotlin.Float){}[0]
-    final fun progress(#A, #A): kotlin/Float // androidx.compose.foundation.gestures/AnchoredDraggableState.progress|progress(1:0;1:0){}[0]
-    final fun requireOffset(): kotlin/Float // androidx.compose.foundation.gestures/AnchoredDraggableState.requireOffset|requireOffset(){}[0]
-    final fun updateAnchors(androidx.compose.foundation.gestures/DraggableAnchors<#A>, #A =...) // androidx.compose.foundation.gestures/AnchoredDraggableState.updateAnchors|updateAnchors(androidx.compose.foundation.gestures.DraggableAnchors<1:0>;1:0){}[0]
-    final object Companion { // androidx.compose.foundation.gestures/AnchoredDraggableState.Companion|null[0]
-        final fun <#A2: kotlin/Any> Saver(androidx.compose.animation.core/AnimationSpec<kotlin/Float>, androidx.compose.animation.core/DecayAnimationSpec<kotlin/Float>, kotlin/Function1<kotlin/Float, kotlin/Float>, kotlin/Function0<kotlin/Float>, kotlin/Function1<#A2, kotlin/Boolean> =...): androidx.compose.runtime.saveable/Saver<androidx.compose.foundation.gestures/AnchoredDraggableState<#A2>, #A2> // androidx.compose.foundation.gestures/AnchoredDraggableState.Companion.Saver|Saver(androidx.compose.animation.core.AnimationSpec<kotlin.Float>;androidx.compose.animation.core.DecayAnimationSpec<kotlin.Float>;kotlin.Function1<kotlin.Float,kotlin.Float>;kotlin.Function0<kotlin.Float>;kotlin.Function1<0:0,kotlin.Boolean>){0§<kotlin.Any>}[0]
-    }
-    final suspend fun anchoredDrag(#A, androidx.compose.foundation/MutatePriority =..., kotlin.coroutines/SuspendFunction3<androidx.compose.foundation.gestures/AnchoredDragScope, androidx.compose.foundation.gestures/DraggableAnchors<#A>, #A, kotlin/Unit>) // androidx.compose.foundation.gestures/AnchoredDraggableState.anchoredDrag|anchoredDrag(1:0;androidx.compose.foundation.MutatePriority;kotlin.coroutines.SuspendFunction3<androidx.compose.foundation.gestures.AnchoredDragScope,androidx.compose.foundation.gestures.DraggableAnchors<1:0>,1:0,kotlin.Unit>){}[0]
-    final suspend fun anchoredDrag(androidx.compose.foundation/MutatePriority =..., kotlin.coroutines/SuspendFunction2<androidx.compose.foundation.gestures/AnchoredDragScope, androidx.compose.foundation.gestures/DraggableAnchors<#A>, kotlin/Unit>) // androidx.compose.foundation.gestures/AnchoredDraggableState.anchoredDrag|anchoredDrag(androidx.compose.foundation.MutatePriority;kotlin.coroutines.SuspendFunction2<androidx.compose.foundation.gestures.AnchoredDragScope,androidx.compose.foundation.gestures.DraggableAnchors<1:0>,kotlin.Unit>){}[0]
-    final suspend fun settle(kotlin/Float): kotlin/Float // androidx.compose.foundation.gestures/AnchoredDraggableState.settle|settle(kotlin.Float){}[0]
-    final val decayAnimationSpec // androidx.compose.foundation.gestures/AnchoredDraggableState.decayAnimationSpec|{}decayAnimationSpec[0]
-        final fun <get-decayAnimationSpec>(): androidx.compose.animation.core/DecayAnimationSpec<kotlin/Float> // androidx.compose.foundation.gestures/AnchoredDraggableState.decayAnimationSpec.<get-decayAnimationSpec>|<get-decayAnimationSpec>(){}[0]
-    final val isAnimationRunning // androidx.compose.foundation.gestures/AnchoredDraggableState.isAnimationRunning|<get-isAnimationRunning>(){}[0]
-        final fun <get-isAnimationRunning>(): kotlin/Boolean // androidx.compose.foundation.gestures/AnchoredDraggableState.isAnimationRunning.<get-isAnimationRunning>|<get-isAnimationRunning>(){}[0]
-    final val progress // androidx.compose.foundation.gestures/AnchoredDraggableState.progress|{}progress[0]
-        final fun <get-progress>(): kotlin/Float // androidx.compose.foundation.gestures/AnchoredDraggableState.progress.<get-progress>|<get-progress>(){}[0]
-    final val snapAnimationSpec // androidx.compose.foundation.gestures/AnchoredDraggableState.snapAnimationSpec|{}snapAnimationSpec[0]
-        final fun <get-snapAnimationSpec>(): androidx.compose.animation.core/AnimationSpec<kotlin/Float> // androidx.compose.foundation.gestures/AnchoredDraggableState.snapAnimationSpec.<get-snapAnimationSpec>|<get-snapAnimationSpec>(){}[0]
-    final val targetValue // androidx.compose.foundation.gestures/AnchoredDraggableState.targetValue|{}targetValue[0]
-        final fun <get-targetValue>(): #A // androidx.compose.foundation.gestures/AnchoredDraggableState.targetValue.<get-targetValue>|<get-targetValue>(){}[0]
-    final var anchors // androidx.compose.foundation.gestures/AnchoredDraggableState.anchors|<get-anchors>(){}[0]
-        final fun <get-anchors>(): androidx.compose.foundation.gestures/DraggableAnchors<#A> // androidx.compose.foundation.gestures/AnchoredDraggableState.anchors.<get-anchors>|<get-anchors>(){}[0]
-    final var currentValue // androidx.compose.foundation.gestures/AnchoredDraggableState.currentValue|{}currentValue[0]
-        final fun <get-currentValue>(): #A // androidx.compose.foundation.gestures/AnchoredDraggableState.currentValue.<get-currentValue>|<get-currentValue>(){}[0]
-    final var lastVelocity // androidx.compose.foundation.gestures/AnchoredDraggableState.lastVelocity|{}lastVelocity[0]
-        final fun <get-lastVelocity>(): kotlin/Float // androidx.compose.foundation.gestures/AnchoredDraggableState.lastVelocity.<get-lastVelocity>|<get-lastVelocity>(){}[0]
-    final var offset // androidx.compose.foundation.gestures/AnchoredDraggableState.offset|<get-offset>(){}[0]
-        final fun <get-offset>(): kotlin/Float // androidx.compose.foundation.gestures/AnchoredDraggableState.offset.<get-offset>|<get-offset>(){}[0]
-    final var settledValue // androidx.compose.foundation.gestures/AnchoredDraggableState.settledValue|{}settledValue[0]
-        final fun <get-settledValue>(): #A // androidx.compose.foundation.gestures/AnchoredDraggableState.settledValue.<get-settledValue>|<get-settledValue>(){}[0]
-}
-final class <#A: kotlin/Any?> androidx.compose.foundation.gestures/DraggableAnchorsConfig { // androidx.compose.foundation.gestures/DraggableAnchorsConfig|null[0]
-    constructor <init>() // androidx.compose.foundation.gestures/DraggableAnchorsConfig.<init>|<init>(){}[0]
-    final fun (#A).at(kotlin/Float) // androidx.compose.foundation.gestures/DraggableAnchorsConfig.at|at@1:0(kotlin.Float){}[0]
-}
-final class <#A: kotlin/Any?> androidx.compose.foundation.lazy.layout/MutableIntervalList : androidx.compose.foundation.lazy.layout/IntervalList<#A> { // androidx.compose.foundation.lazy.layout/MutableIntervalList|null[0]
-    constructor <init>() // androidx.compose.foundation.lazy.layout/MutableIntervalList.<init>|<init>(){}[0]
-    final fun addInterval(kotlin/Int, #A) // androidx.compose.foundation.lazy.layout/MutableIntervalList.addInterval|addInterval(kotlin.Int;1:0){}[0]
-    final fun forEach(kotlin/Int, kotlin/Int, kotlin/Function1<androidx.compose.foundation.lazy.layout/IntervalList.Interval<#A>, kotlin/Unit>) // androidx.compose.foundation.lazy.layout/MutableIntervalList.forEach|forEach(kotlin.Int;kotlin.Int;kotlin.Function1<androidx.compose.foundation.lazy.layout.IntervalList.Interval<1:0>,kotlin.Unit>){}[0]
-    final fun get(kotlin/Int): androidx.compose.foundation.lazy.layout/IntervalList.Interval<#A> // androidx.compose.foundation.lazy.layout/MutableIntervalList.get|get(kotlin.Int){}[0]
-    final var size // androidx.compose.foundation.lazy.layout/MutableIntervalList.size|{}size[0]
-        final fun <get-size>(): kotlin/Int // androidx.compose.foundation.lazy.layout/MutableIntervalList.size.<get-size>|<get-size>(){}[0]
-}
 final class androidx.compose.foundation.content/MediaType { // androidx.compose.foundation.content/MediaType|null[0]
     constructor <init>(kotlin/String) // androidx.compose.foundation.content/MediaType.<init>|<init>(kotlin.String){}[0]
     final object Companion { // androidx.compose.foundation.content/MediaType.Companion|null[0]
@@ -504,42 +343,11 @@
     final val representation // androidx.compose.foundation.content/MediaType.representation|{}representation[0]
         final fun <get-representation>(): kotlin/String // androidx.compose.foundation.content/MediaType.representation.<get-representation>|<get-representation>(){}[0]
 }
-final class androidx.compose.foundation.content/PlatformTransferableContent // androidx.compose.foundation.content/PlatformTransferableContent|null[0]
-final class androidx.compose.foundation.content/TransferableContent { // androidx.compose.foundation.content/TransferableContent|null[0]
-    final val clipEntry // androidx.compose.foundation.content/TransferableContent.clipEntry|{}clipEntry[0]
-        final fun <get-clipEntry>(): androidx.compose.ui.platform/ClipEntry // androidx.compose.foundation.content/TransferableContent.clipEntry.<get-clipEntry>|<get-clipEntry>(){}[0]
-    final val clipMetadata // androidx.compose.foundation.content/TransferableContent.clipMetadata|{}clipMetadata[0]
-        final fun <get-clipMetadata>(): androidx.compose.ui.platform/ClipMetadata // androidx.compose.foundation.content/TransferableContent.clipMetadata.<get-clipMetadata>|<get-clipMetadata>(){}[0]
-    final val platformTransferableContent // androidx.compose.foundation.content/TransferableContent.platformTransferableContent|{}platformTransferableContent[0]
-        final fun <get-platformTransferableContent>(): androidx.compose.foundation.content/PlatformTransferableContent? // androidx.compose.foundation.content/TransferableContent.platformTransferableContent.<get-platformTransferableContent>|<get-platformTransferableContent>(){}[0]
-    final val source // androidx.compose.foundation.content/TransferableContent.source|{}source[0]
-        final fun <get-source>(): androidx.compose.foundation.content/TransferableContent.Source // androidx.compose.foundation.content/TransferableContent.source.<get-source>|<get-source>(){}[0]
-    final value class Source { // androidx.compose.foundation.content/TransferableContent.Source|null[0]
-        final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.foundation.content/TransferableContent.Source.equals|equals(kotlin.Any?){}[0]
-        final fun hashCode(): kotlin/Int // androidx.compose.foundation.content/TransferableContent.Source.hashCode|hashCode(){}[0]
-        final fun toString(): kotlin/String // androidx.compose.foundation.content/TransferableContent.Source.toString|toString(){}[0]
-        final object Companion { // androidx.compose.foundation.content/TransferableContent.Source.Companion|null[0]
-            final val Clipboard // androidx.compose.foundation.content/TransferableContent.Source.Companion.Clipboard|{}Clipboard[0]
-                final fun <get-Clipboard>(): androidx.compose.foundation.content/TransferableContent.Source // androidx.compose.foundation.content/TransferableContent.Source.Companion.Clipboard.<get-Clipboard>|<get-Clipboard>(){}[0]
-            final val DragAndDrop // androidx.compose.foundation.content/TransferableContent.Source.Companion.DragAndDrop|{}DragAndDrop[0]
-                final fun <get-DragAndDrop>(): androidx.compose.foundation.content/TransferableContent.Source // androidx.compose.foundation.content/TransferableContent.Source.Companion.DragAndDrop.<get-DragAndDrop>|<get-DragAndDrop>(){}[0]
-            final val Keyboard // androidx.compose.foundation.content/TransferableContent.Source.Companion.Keyboard|{}Keyboard[0]
-                final fun <get-Keyboard>(): androidx.compose.foundation.content/TransferableContent.Source // androidx.compose.foundation.content/TransferableContent.Source.Companion.Keyboard.<get-Keyboard>|<get-Keyboard>(){}[0]
-        }
-    }
-}
-final class androidx.compose.foundation.gestures.snapping/SnapFlingBehavior : androidx.compose.foundation.gestures/TargetedFlingBehavior { // androidx.compose.foundation.gestures.snapping/SnapFlingBehavior|null[0]
-    constructor <init>(androidx.compose.foundation.gestures.snapping/SnapLayoutInfoProvider, androidx.compose.animation.core/DecayAnimationSpec<kotlin/Float>, androidx.compose.animation.core/AnimationSpec<kotlin/Float>) // androidx.compose.foundation.gestures.snapping/SnapFlingBehavior.<init>|<init>(androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider;androidx.compose.animation.core.DecayAnimationSpec<kotlin.Float>;androidx.compose.animation.core.AnimationSpec<kotlin.Float>){}[0]
-    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.foundation.gestures.snapping/SnapFlingBehavior.equals|equals(kotlin.Any?){}[0]
-    final fun hashCode(): kotlin/Int // androidx.compose.foundation.gestures.snapping/SnapFlingBehavior.hashCode|hashCode(){}[0]
-    final suspend fun (androidx.compose.foundation.gestures/ScrollScope).performFling(kotlin/Float, kotlin/Function1<kotlin/Float, kotlin/Unit>): kotlin/Float // androidx.compose.foundation.gestures.snapping/SnapFlingBehavior.performFling|[email protected](kotlin.Float;kotlin.Function1<kotlin.Float,kotlin.Unit>){}[0]
-}
 final class androidx.compose.foundation.gestures/GestureCancellationException : kotlin.coroutines.cancellation/CancellationException { // androidx.compose.foundation.gestures/GestureCancellationException|null[0]
     constructor <init>(kotlin/String? =...) // androidx.compose.foundation.gestures/GestureCancellationException.<init>|<init>(kotlin.String?){}[0]
 }
 final class androidx.compose.foundation.lazy.grid/LazyGridState : androidx.compose.foundation.gestures/ScrollableState { // androidx.compose.foundation.lazy.grid/LazyGridState|null[0]
     constructor <init>(kotlin/Int =..., kotlin/Int =...) // androidx.compose.foundation.lazy.grid/LazyGridState.<init>|<init>(kotlin.Int;kotlin.Int){}[0]
-    constructor <init>(kotlin/Int =..., kotlin/Int =..., androidx.compose.foundation.lazy.grid/LazyGridPrefetchStrategy =...) // androidx.compose.foundation.lazy.grid/LazyGridState.<init>|<init>(kotlin.Int;kotlin.Int;androidx.compose.foundation.lazy.grid.LazyGridPrefetchStrategy){}[0]
     final fun dispatchRawDelta(kotlin/Float): kotlin/Float // androidx.compose.foundation.lazy.grid/LazyGridState.dispatchRawDelta|dispatchRawDelta(kotlin.Float){}[0]
     final fun requestScrollToItem(kotlin/Int, kotlin/Int =...) // androidx.compose.foundation.lazy.grid/LazyGridState.requestScrollToItem|requestScrollToItem(kotlin.Int;kotlin.Int){}[0]
     final object Companion { // androidx.compose.foundation.lazy.grid/LazyGridState.Companion|null[0]
@@ -568,36 +376,6 @@
     final var canScrollForward // androidx.compose.foundation.lazy.grid/LazyGridState.canScrollForward|{}canScrollForward[0]
         final fun <get-canScrollForward>(): kotlin/Boolean // androidx.compose.foundation.lazy.grid/LazyGridState.canScrollForward.<get-canScrollForward>|<get-canScrollForward>(){}[0]
 }
-final class androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList : kotlin.collections/List<androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem> { // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList|null[0]
-    constructor <init>() // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.<init>|<init>(){}[0]
-    final fun contains(androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem): kotlin/Boolean // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.contains|contains(androidx.compose.foundation.lazy.layout.LazyLayoutPinnedItemList.PinnedItem){}[0]
-    final fun containsAll(kotlin.collections/Collection<androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem>): kotlin/Boolean // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.containsAll|containsAll(kotlin.collections.Collection<androidx.compose.foundation.lazy.layout.LazyLayoutPinnedItemList.PinnedItem>){}[0]
-    final fun get(kotlin/Int): androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.get|get(kotlin.Int){}[0]
-    final fun indexOf(androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem): kotlin/Int // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.indexOf|indexOf(androidx.compose.foundation.lazy.layout.LazyLayoutPinnedItemList.PinnedItem){}[0]
-    final fun isEmpty(): kotlin/Boolean // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.isEmpty|isEmpty(){}[0]
-    final fun iterator(): kotlin.collections/Iterator<androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem> // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.iterator|iterator(){}[0]
-    final fun lastIndexOf(androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem): kotlin/Int // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.lastIndexOf|lastIndexOf(androidx.compose.foundation.lazy.layout.LazyLayoutPinnedItemList.PinnedItem){}[0]
-    final fun listIterator(): kotlin.collections/ListIterator<androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem> // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.listIterator|listIterator(){}[0]
-    final fun listIterator(kotlin/Int): kotlin.collections/ListIterator<androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem> // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.listIterator|listIterator(kotlin.Int){}[0]
-    final fun subList(kotlin/Int, kotlin/Int): kotlin.collections/List<androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem> // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.subList|subList(kotlin.Int;kotlin.Int){}[0]
-    final val size // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.size|{}size[0]
-        final fun <get-size>(): kotlin/Int // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.size.<get-size>|<get-size>(){}[0]
-    sealed interface PinnedItem { // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem|null[0]
-        abstract val index // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem.index|{}index[0]
-            abstract fun <get-index>(): kotlin/Int // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem.index.<get-index>|<get-index>(){}[0]
-        abstract val key // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem.key|{}key[0]
-            abstract fun <get-key>(): kotlin/Any? // androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList.PinnedItem.key.<get-key>|<get-key>(){}[0]
-    }
-}
-final class androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState { // androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState|null[0]
-    constructor <init>(androidx.compose.foundation.lazy.layout/PrefetchScheduler? =..., kotlin/Function1<androidx.compose.foundation.lazy.layout/NestedPrefetchScope, kotlin/Unit>? =...) // androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState.<init>|<init>(androidx.compose.foundation.lazy.layout.PrefetchScheduler?;kotlin.Function1<androidx.compose.foundation.lazy.layout.NestedPrefetchScope,kotlin.Unit>?){}[0]
-    final fun schedulePrefetch(kotlin/Int): androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState.PrefetchHandle // androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState.schedulePrefetch|schedulePrefetch(kotlin.Int){}[0]
-    final fun schedulePrefetch(kotlin/Int, androidx.compose.ui.unit/Constraints): androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState.PrefetchHandle // androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState.schedulePrefetch|schedulePrefetch(kotlin.Int;androidx.compose.ui.unit.Constraints){}[0]
-    sealed interface PrefetchHandle { // androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState.PrefetchHandle|null[0]
-        abstract fun cancel() // androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState.PrefetchHandle.cancel|cancel(){}[0]
-        abstract fun markAsUrgent() // androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState.PrefetchHandle.markAsUrgent|markAsUrgent(){}[0]
-    }
-}
 final class androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridState : androidx.compose.foundation.gestures/ScrollableState { // androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridState|null[0]
     constructor <init>(kotlin/Int =..., kotlin/Int =...) // androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridState.<init>|<init>(kotlin.Int;kotlin.Int){}[0]
     final fun dispatchRawDelta(kotlin/Float): kotlin/Float // androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridState.dispatchRawDelta|dispatchRawDelta(kotlin.Float){}[0]
@@ -638,7 +416,6 @@
 }
 final class androidx.compose.foundation.lazy/LazyListState : androidx.compose.foundation.gestures/ScrollableState { // androidx.compose.foundation.lazy/LazyListState|null[0]
     constructor <init>(kotlin/Int =..., kotlin/Int =...) // androidx.compose.foundation.lazy/LazyListState.<init>|<init>(kotlin.Int;kotlin.Int){}[0]
-    constructor <init>(kotlin/Int =..., kotlin/Int =..., androidx.compose.foundation.lazy/LazyListPrefetchStrategy =...) // androidx.compose.foundation.lazy/LazyListState.<init>|<init>(kotlin.Int;kotlin.Int;androidx.compose.foundation.lazy.LazyListPrefetchStrategy){}[0]
     final fun dispatchRawDelta(kotlin/Float): kotlin/Float // androidx.compose.foundation.lazy/LazyListState.dispatchRawDelta|dispatchRawDelta(kotlin.Float){}[0]
     final fun requestScrollToItem(kotlin/Int, kotlin/Int =...) // androidx.compose.foundation.lazy/LazyListState.requestScrollToItem|requestScrollToItem(kotlin.Int;kotlin.Int){}[0]
     final object Companion { // androidx.compose.foundation.lazy/LazyListState.Companion|null[0]
@@ -706,12 +483,6 @@
     final fun toString(): kotlin/String // androidx.compose.foundation.shape/RoundedCornerShape.toString|toString(){}[0]
 }
 final class androidx.compose.foundation.text.input/TextFieldBuffer : kotlin.text/Appendable { // androidx.compose.foundation.text.input/TextFieldBuffer|null[0]
-    abstract interface ChangeList { // androidx.compose.foundation.text.input/TextFieldBuffer.ChangeList|null[0]
-        abstract fun getOriginalRange(kotlin/Int): androidx.compose.ui.text/TextRange // androidx.compose.foundation.text.input/TextFieldBuffer.ChangeList.getOriginalRange|getOriginalRange(kotlin.Int){}[0]
-        abstract fun getRange(kotlin/Int): androidx.compose.ui.text/TextRange // androidx.compose.foundation.text.input/TextFieldBuffer.ChangeList.getRange|getRange(kotlin.Int){}[0]
-        abstract val changeCount // androidx.compose.foundation.text.input/TextFieldBuffer.ChangeList.changeCount|{}changeCount[0]
-            abstract fun <get-changeCount>(): kotlin/Int // androidx.compose.foundation.text.input/TextFieldBuffer.ChangeList.changeCount.<get-changeCount>|<get-changeCount>(){}[0]
-    }
     final fun append(kotlin/Char): kotlin.text/Appendable // androidx.compose.foundation.text.input/TextFieldBuffer.append|append(kotlin.Char){}[0]
     final fun append(kotlin/CharSequence?): kotlin.text/Appendable // androidx.compose.foundation.text.input/TextFieldBuffer.append|append(kotlin.CharSequence?){}[0]
     final fun append(kotlin/CharSequence?, kotlin/Int, kotlin/Int): kotlin.text/Appendable // androidx.compose.foundation.text.input/TextFieldBuffer.append|append(kotlin.CharSequence?;kotlin.Int;kotlin.Int){}[0]
@@ -722,8 +493,6 @@
     final fun replace(kotlin/Int, kotlin/Int, kotlin/CharSequence) // androidx.compose.foundation.text.input/TextFieldBuffer.replace|replace(kotlin.Int;kotlin.Int;kotlin.CharSequence){}[0]
     final fun revertAllChanges() // androidx.compose.foundation.text.input/TextFieldBuffer.revertAllChanges|revertAllChanges(){}[0]
     final fun toString(): kotlin/String // androidx.compose.foundation.text.input/TextFieldBuffer.toString|toString(){}[0]
-    final val changes // androidx.compose.foundation.text.input/TextFieldBuffer.changes|{}changes[0]
-        final fun <get-changes>(): androidx.compose.foundation.text.input/TextFieldBuffer.ChangeList // androidx.compose.foundation.text.input/TextFieldBuffer.changes.<get-changes>|<get-changes>(){}[0]
     final val hasSelection // androidx.compose.foundation.text.input/TextFieldBuffer.hasSelection|{}hasSelection[0]
         final fun <get-hasSelection>(): kotlin/Boolean // androidx.compose.foundation.text.input/TextFieldBuffer.hasSelection.<get-hasSelection>|<get-hasSelection>(){}[0]
     final val length // androidx.compose.foundation.text.input/TextFieldBuffer.length|{}length[0]
@@ -753,17 +522,6 @@
         final fun <get-selection>(): androidx.compose.ui.text/TextRange // androidx.compose.foundation.text.input/TextFieldState.selection.<get-selection>|<get-selection>(){}[0]
     final val text // androidx.compose.foundation.text.input/TextFieldState.text|{}text[0]
         final fun <get-text>(): kotlin/CharSequence // androidx.compose.foundation.text.input/TextFieldState.text.<get-text>|<get-text>(){}[0]
-    final val undoState // androidx.compose.foundation.text.input/TextFieldState.undoState|{}undoState[0]
-        final fun <get-undoState>(): androidx.compose.foundation.text.input/UndoState // androidx.compose.foundation.text.input/TextFieldState.undoState.<get-undoState>|<get-undoState>(){}[0]
-}
-final class androidx.compose.foundation.text.input/UndoState { // androidx.compose.foundation.text.input/UndoState|null[0]
-    final fun clearHistory() // androidx.compose.foundation.text.input/UndoState.clearHistory|clearHistory(){}[0]
-    final fun redo() // androidx.compose.foundation.text.input/UndoState.redo|redo(){}[0]
-    final fun undo() // androidx.compose.foundation.text.input/UndoState.undo|undo(){}[0]
-    final val canRedo // androidx.compose.foundation.text.input/UndoState.canRedo|{}canRedo[0]
-        final fun <get-canRedo>(): kotlin/Boolean // androidx.compose.foundation.text.input/UndoState.canRedo.<get-canRedo>|<get-canRedo>(){}[0]
-    final val canUndo // androidx.compose.foundation.text.input/UndoState.canUndo|{}canUndo[0]
-        final fun <get-canUndo>(): kotlin/Boolean // androidx.compose.foundation.text.input/UndoState.canUndo.<get-canUndo>|<get-canUndo>(){}[0]
 }
 final class androidx.compose.foundation.text.selection/TextSelectionColors { // androidx.compose.foundation.text.selection/TextSelectionColors|null[0]
     constructor <init>(androidx.compose.ui.graphics/Color, androidx.compose.ui.graphics/Color) // androidx.compose.foundation.text.selection/TextSelectionColors.<init>|<init>(androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
@@ -900,7 +658,6 @@
     final fun valueOf(kotlin/String): androidx.compose.foundation/MutatePriority // androidx.compose.foundation/MutatePriority.valueOf|valueOf#static(kotlin.String){}[0]
     final fun values(): kotlin/Array<androidx.compose.foundation/MutatePriority> // androidx.compose.foundation/MutatePriority.values|values#static(){}[0]
 }
-final fun (androidx.compose.foundation.content/TransferableContent).androidx.compose.foundation.content/hasMediaType(androidx.compose.foundation.content/MediaType): kotlin/Boolean // androidx.compose.foundation.content/hasMediaType|hasMediaType@androidx.compose.foundation.content.TransferableContent(androidx.compose.foundation.content.MediaType){}[0]
 final fun (androidx.compose.foundation.interaction/InteractionSource).androidx.compose.foundation.interaction/collectIsDraggedAsState(): androidx.compose.runtime/State<kotlin/Boolean> // androidx.compose.foundation.interaction/collectIsDraggedAsState|collectIsDraggedAsState@androidx.compose.foundation.interaction.InteractionSource(){}[0]
 final fun (androidx.compose.foundation.interaction/InteractionSource).androidx.compose.foundation.interaction/collectIsFocusedAsState(): androidx.compose.runtime/State<kotlin/Boolean> // androidx.compose.foundation.interaction/collectIsFocusedAsState|collectIsFocusedAsState@androidx.compose.foundation.interaction.InteractionSource(){}[0]
 final fun (androidx.compose.foundation.interaction/InteractionSource).androidx.compose.foundation.interaction/collectIsHoveredAsState(): androidx.compose.runtime/State<kotlin/Boolean> // androidx.compose.foundation.interaction/collectIsHoveredAsState|collectIsHoveredAsState@androidx.compose.foundation.interaction.InteractionSource(){}[0]
@@ -922,18 +679,9 @@
 final fun (androidx.compose.ui.input.pointer/PointerEvent).androidx.compose.foundation.gestures/calculateRotation(): kotlin/Float // androidx.compose.foundation.gestures/calculateRotation|[email protected](){}[0]
 final fun (androidx.compose.ui.input.pointer/PointerEvent).androidx.compose.foundation.gestures/calculateZoom(): kotlin/Float // androidx.compose.foundation.gestures/calculateZoom|[email protected](){}[0]
 final fun (androidx.compose.ui.text/AnnotatedString.Builder).androidx.compose.foundation.text/appendInlineContent(kotlin/String, kotlin/String =...) // androidx.compose.foundation.text/appendInlineContent|appendInlineContent@androidx.compose.ui.text.AnnotatedString.Builder(kotlin.String;kotlin.String){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.content/contentReceiver(androidx.compose.foundation.content/ReceiveContentListener): androidx.compose.ui/Modifier // androidx.compose.foundation.content/contentReceiver|[email protected](androidx.compose.foundation.content.ReceiveContentListener){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.draganddrop/dragAndDropSource(kotlin/Function1<androidx.compose.ui.graphics.drawscope/DrawScope, kotlin/Unit>, kotlin.coroutines/SuspendFunction1<androidx.compose.foundation.draganddrop/DragAndDropSourceScope, kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.foundation.draganddrop/dragAndDropSource|[email protected](kotlin.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit>;kotlin.coroutines.SuspendFunction1<androidx.compose.foundation.draganddrop.DragAndDropSourceScope,kotlin.Unit>){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.draganddrop/dragAndDropTarget(kotlin/Function1<androidx.compose.ui.draganddrop/DragAndDropEvent, kotlin/Boolean>, androidx.compose.ui.draganddrop/DragAndDropTarget): androidx.compose.ui/Modifier // androidx.compose.foundation.draganddrop/dragAndDropTarget|[email protected](kotlin.Function1<androidx.compose.ui.draganddrop.DragAndDropEvent,kotlin.Boolean>;androidx.compose.ui.draganddrop.DragAndDropTarget){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.gestures/draggable(androidx.compose.foundation.gestures/DraggableState, androidx.compose.foundation.gestures/Orientation, kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., kotlin/Boolean =..., kotlin.coroutines/SuspendFunction2<kotlinx.coroutines/CoroutineScope, androidx.compose.ui.geometry/Offset, kotlin/Unit> =..., kotlin.coroutines/SuspendFunction2<kotlinx.coroutines/CoroutineScope, kotlin/Float, kotlin/Unit> =..., kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.foundation.gestures/draggable|[email protected](androidx.compose.foundation.gestures.DraggableState;androidx.compose.foundation.gestures.Orientation;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;kotlin.Boolean;kotlin.coroutines.SuspendFunction2<kotlinx.coroutines.CoroutineScope,androidx.compose.ui.geometry.Offset,kotlin.Unit>;kotlin.coroutines.SuspendFunction2<kotlinx.coroutines.CoroutineScope,kotlin.Float,kotlin.Unit>;kotlin.Boolean){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.gestures/draggable2D(androidx.compose.foundation.gestures/Draggable2DState, kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., kotlin/Boolean =..., kotlin.coroutines/SuspendFunction2<kotlinx.coroutines/CoroutineScope, androidx.compose.ui.geometry/Offset, kotlin/Unit> =..., kotlin.coroutines/SuspendFunction2<kotlinx.coroutines/CoroutineScope, androidx.compose.ui.unit/Velocity, kotlin/Unit> =..., kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.foundation.gestures/draggable2D|[email protected](androidx.compose.foundation.gestures.Draggable2DState;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;kotlin.Boolean;kotlin.coroutines.SuspendFunction2<kotlinx.coroutines.CoroutineScope,androidx.compose.ui.geometry.Offset,kotlin.Unit>;kotlin.coroutines.SuspendFunction2<kotlinx.coroutines.CoroutineScope,androidx.compose.ui.unit.Velocity,kotlin.Unit>;kotlin.Boolean){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.gestures/draggable2D(androidx.compose.foundation.gestures/Draggable2DState, kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., kotlin/Boolean =..., kotlin/Function1<androidx.compose.ui.geometry/Offset, kotlin/Unit> =..., kotlin/Function1<androidx.compose.ui.unit/Velocity, kotlin/Unit> =..., kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.foundation.gestures/draggable2D|[email protected](androidx.compose.foundation.gestures.Draggable2DState;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;kotlin.Boolean;kotlin.Function1<androidx.compose.ui.geometry.Offset,kotlin.Unit>;kotlin.Function1<androidx.compose.ui.unit.Velocity,kotlin.Unit>;kotlin.Boolean){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.gestures/scrollable(androidx.compose.foundation.gestures/ScrollableState, androidx.compose.foundation.gestures/Orientation, androidx.compose.foundation/OverscrollEffect?, kotlin/Boolean =..., kotlin/Boolean =..., androidx.compose.foundation.gestures/FlingBehavior? =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.foundation.gestures/BringIntoViewSpec? =...): androidx.compose.ui/Modifier // androidx.compose.foundation.gestures/scrollable|[email protected](androidx.compose.foundation.gestures.ScrollableState;androidx.compose.foundation.gestures.Orientation;androidx.compose.foundation.OverscrollEffect?;kotlin.Boolean;kotlin.Boolean;androidx.compose.foundation.gestures.FlingBehavior?;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.foundation.gestures.BringIntoViewSpec?){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.gestures/scrollable(androidx.compose.foundation.gestures/ScrollableState, androidx.compose.foundation.gestures/Orientation, kotlin/Boolean =..., kotlin/Boolean =..., androidx.compose.foundation.gestures/FlingBehavior? =..., androidx.compose.foundation.interaction/MutableInteractionSource? =...): androidx.compose.ui/Modifier // androidx.compose.foundation.gestures/scrollable|[email protected](androidx.compose.foundation.gestures.ScrollableState;androidx.compose.foundation.gestures.Orientation;kotlin.Boolean;kotlin.Boolean;androidx.compose.foundation.gestures.FlingBehavior?;androidx.compose.foundation.interaction.MutableInteractionSource?){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.gestures/transformable(androidx.compose.foundation.gestures/TransformableState, kotlin/Boolean =..., kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.foundation.gestures/transformable|[email protected](androidx.compose.foundation.gestures.TransformableState;kotlin.Boolean;kotlin.Boolean){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.gestures/transformable(androidx.compose.foundation.gestures/TransformableState, kotlin/Function1<androidx.compose.ui.geometry/Offset, kotlin/Boolean>, kotlin/Boolean =..., kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.foundation.gestures/transformable|[email protected](androidx.compose.foundation.gestures.TransformableState;kotlin.Function1<androidx.compose.ui.geometry.Offset,kotlin.Boolean>;kotlin.Boolean;kotlin.Boolean){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.relocation/bringIntoViewRequester(androidx.compose.foundation.relocation/BringIntoViewRequester): androidx.compose.ui/Modifier // androidx.compose.foundation.relocation/bringIntoViewRequester|[email protected](androidx.compose.foundation.relocation.BringIntoViewRequester){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.relocation/bringIntoViewResponder(androidx.compose.foundation.relocation/BringIntoViewResponder): androidx.compose.ui/Modifier // androidx.compose.foundation.relocation/bringIntoViewResponder|[email protected](androidx.compose.foundation.relocation.BringIntoViewResponder){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.selection/selectable(kotlin/Boolean, androidx.compose.foundation.interaction/MutableInteractionSource?, androidx.compose.foundation/Indication?, kotlin/Boolean =..., androidx.compose.ui.semantics/Role? =..., kotlin/Function0<kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.foundation.selection/selectable|[email protected](kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.foundation.Indication?;kotlin.Boolean;androidx.compose.ui.semantics.Role?;kotlin.Function0<kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.selection/selectable(kotlin/Boolean, kotlin/Boolean =..., androidx.compose.ui.semantics/Role? =..., kotlin/Function0<kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.foundation.selection/selectable|[email protected](kotlin.Boolean;kotlin.Boolean;androidx.compose.ui.semantics.Role?;kotlin.Function0<kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation.selection/selectableGroup(): androidx.compose.ui/Modifier // androidx.compose.foundation.selection/selectableGroup|[email protected](){}[0]
@@ -950,62 +698,44 @@
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/clickable(androidx.compose.foundation.interaction/MutableInteractionSource?, androidx.compose.foundation/Indication?, kotlin/Boolean =..., kotlin/String? =..., androidx.compose.ui.semantics/Role? =..., kotlin/Function0<kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.foundation/clickable|[email protected](androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.foundation.Indication?;kotlin.Boolean;kotlin.String?;androidx.compose.ui.semantics.Role?;kotlin.Function0<kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/clickable(kotlin/Boolean =..., kotlin/String? =..., androidx.compose.ui.semantics/Role? =..., kotlin/Function0<kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.foundation/clickable|[email protected](kotlin.Boolean;kotlin.String?;androidx.compose.ui.semantics.Role?;kotlin.Function0<kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/clipScrollableContainer(androidx.compose.foundation.gestures/Orientation): androidx.compose.ui/Modifier // androidx.compose.foundation/clipScrollableContainer|[email protected](androidx.compose.foundation.gestures.Orientation){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/combinedClickable(androidx.compose.foundation.interaction/MutableInteractionSource?, androidx.compose.foundation/Indication?, kotlin/Boolean =..., kotlin/String? =..., androidx.compose.ui.semantics/Role? =..., kotlin/String? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.foundation/combinedClickable|[email protected](androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.foundation.Indication?;kotlin.Boolean;kotlin.String?;androidx.compose.ui.semantics.Role?;kotlin.String?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/combinedClickable(kotlin/Boolean =..., kotlin/String? =..., androidx.compose.ui.semantics/Role? =..., kotlin/String? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.foundation/combinedClickable|[email protected](kotlin.Boolean;kotlin.String?;androidx.compose.ui.semantics.Role?;kotlin.String?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/focusGroup(): androidx.compose.ui/Modifier // androidx.compose.foundation/focusGroup|[email protected](){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/focusable(kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =...): androidx.compose.ui/Modifier // androidx.compose.foundation/focusable|[email protected](kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/horizontalScroll(androidx.compose.foundation/ScrollState, kotlin/Boolean =..., androidx.compose.foundation.gestures/FlingBehavior? =..., kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.foundation/horizontalScroll|[email protected](androidx.compose.foundation.ScrollState;kotlin.Boolean;androidx.compose.foundation.gestures.FlingBehavior?;kotlin.Boolean){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/hoverable(androidx.compose.foundation.interaction/MutableInteractionSource, kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.foundation/hoverable|[email protected](androidx.compose.foundation.interaction.MutableInteractionSource;kotlin.Boolean){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/indication(androidx.compose.foundation.interaction/InteractionSource, androidx.compose.foundation/Indication?): androidx.compose.ui/Modifier // androidx.compose.foundation/indication|[email protected](androidx.compose.foundation.interaction.InteractionSource;androidx.compose.foundation.Indication?){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/onFocusedBoundsChanged(kotlin/Function1<androidx.compose.ui.layout/LayoutCoordinates?, kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.foundation/onFocusedBoundsChanged|[email protected](kotlin.Function1<androidx.compose.ui.layout.LayoutCoordinates?,kotlin.Unit>){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/overscroll(androidx.compose.foundation/OverscrollEffect): androidx.compose.ui/Modifier // androidx.compose.foundation/overscroll|[email protected](androidx.compose.foundation.OverscrollEffect){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/progressSemantics(): androidx.compose.ui/Modifier // androidx.compose.foundation/progressSemantics|[email protected](){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/progressSemantics(kotlin/Float, kotlin.ranges/ClosedFloatingPointRange<kotlin/Float> =..., kotlin/Int =...): androidx.compose.ui/Modifier // androidx.compose.foundation/progressSemantics|[email protected](kotlin.Float;kotlin.ranges.ClosedFloatingPointRange<kotlin.Float>;kotlin.Int){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.foundation/verticalScroll(androidx.compose.foundation/ScrollState, kotlin/Boolean =..., androidx.compose.foundation.gestures/FlingBehavior? =..., kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.foundation/verticalScroll|[email protected](androidx.compose.foundation.ScrollState;kotlin.Boolean;androidx.compose.foundation.gestures.FlingBehavior?;kotlin.Boolean){}[0]
-final fun <#A: kotlin/Any> androidx.compose.foundation.gestures/DraggableAnchors(kotlin/Function1<androidx.compose.foundation.gestures/DraggableAnchorsConfig<#A>, kotlin/Unit>): androidx.compose.foundation.gestures/DraggableAnchors<#A> // androidx.compose.foundation.gestures/DraggableAnchors|DraggableAnchors(kotlin.Function1<androidx.compose.foundation.gestures.DraggableAnchorsConfig<0:0>,kotlin.Unit>){0§<kotlin.Any>}[0]
-final fun <#A: kotlin/Any?> (androidx.compose.ui/Modifier).androidx.compose.foundation.gestures/anchoredDraggable(androidx.compose.foundation.gestures/AnchoredDraggableState<#A>, androidx.compose.foundation.gestures/Orientation, kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.foundation/OverscrollEffect? =..., kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.foundation.gestures/anchoredDraggable|[email protected](androidx.compose.foundation.gestures.AnchoredDraggableState<0:0>;androidx.compose.foundation.gestures.Orientation;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.foundation.OverscrollEffect?;kotlin.Boolean){0§<kotlin.Any?>}[0]
-final fun <#A: kotlin/Any?> (androidx.compose.ui/Modifier).androidx.compose.foundation.gestures/anchoredDraggable(androidx.compose.foundation.gestures/AnchoredDraggableState<#A>, kotlin/Boolean, androidx.compose.foundation.gestures/Orientation, kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.foundation/OverscrollEffect? =..., kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.foundation.gestures/anchoredDraggable|[email protected](androidx.compose.foundation.gestures.AnchoredDraggableState<0:0>;kotlin.Boolean;androidx.compose.foundation.gestures.Orientation;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.foundation.OverscrollEffect?;kotlin.Boolean){0§<kotlin.Any?>}[0]
 final fun androidx.compose.foundation.gestures.snapping/SnapLayoutInfoProvider(androidx.compose.foundation.lazy.grid/LazyGridState, androidx.compose.foundation.gestures.snapping/SnapPosition =...): androidx.compose.foundation.gestures.snapping/SnapLayoutInfoProvider // androidx.compose.foundation.gestures.snapping/SnapLayoutInfoProvider|SnapLayoutInfoProvider(androidx.compose.foundation.lazy.grid.LazyGridState;androidx.compose.foundation.gestures.snapping.SnapPosition){}[0]
 final fun androidx.compose.foundation.gestures.snapping/SnapLayoutInfoProvider(androidx.compose.foundation.lazy/LazyListState, androidx.compose.foundation.gestures.snapping/SnapPosition =...): androidx.compose.foundation.gestures.snapping/SnapLayoutInfoProvider // androidx.compose.foundation.gestures.snapping/SnapLayoutInfoProvider|SnapLayoutInfoProvider(androidx.compose.foundation.lazy.LazyListState;androidx.compose.foundation.gestures.snapping.SnapPosition){}[0]
 final fun androidx.compose.foundation.gestures.snapping/rememberSnapFlingBehavior(androidx.compose.foundation.gestures.snapping/SnapLayoutInfoProvider): androidx.compose.foundation.gestures/TargetedFlingBehavior // androidx.compose.foundation.gestures.snapping/rememberSnapFlingBehavior|rememberSnapFlingBehavior(androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider){}[0]
 final fun androidx.compose.foundation.gestures.snapping/rememberSnapFlingBehavior(androidx.compose.foundation.lazy.grid/LazyGridState, androidx.compose.foundation.gestures.snapping/SnapPosition =...): androidx.compose.foundation.gestures/FlingBehavior // androidx.compose.foundation.gestures.snapping/rememberSnapFlingBehavior|rememberSnapFlingBehavior(androidx.compose.foundation.lazy.grid.LazyGridState;androidx.compose.foundation.gestures.snapping.SnapPosition){}[0]
 final fun androidx.compose.foundation.gestures.snapping/rememberSnapFlingBehavior(androidx.compose.foundation.lazy/LazyListState, androidx.compose.foundation.gestures.snapping/SnapPosition =...): androidx.compose.foundation.gestures/FlingBehavior // androidx.compose.foundation.gestures.snapping/rememberSnapFlingBehavior|rememberSnapFlingBehavior(androidx.compose.foundation.lazy.LazyListState;androidx.compose.foundation.gestures.snapping.SnapPosition){}[0]
 final fun androidx.compose.foundation.gestures.snapping/snapFlingBehavior(androidx.compose.foundation.gestures.snapping/SnapLayoutInfoProvider, androidx.compose.animation.core/DecayAnimationSpec<kotlin/Float>, androidx.compose.animation.core/AnimationSpec<kotlin/Float>): androidx.compose.foundation.gestures/TargetedFlingBehavior // androidx.compose.foundation.gestures.snapping/snapFlingBehavior|snapFlingBehavior(androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider;androidx.compose.animation.core.DecayAnimationSpec<kotlin.Float>;androidx.compose.animation.core.AnimationSpec<kotlin.Float>){}[0]
-final fun androidx.compose.foundation.gestures/Draggable2DState(kotlin/Function1<androidx.compose.ui.geometry/Offset, kotlin/Unit>): androidx.compose.foundation.gestures/Draggable2DState // androidx.compose.foundation.gestures/Draggable2DState|Draggable2DState(kotlin.Function1<androidx.compose.ui.geometry.Offset,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.gestures/DraggableState(kotlin/Function1<kotlin/Float, kotlin/Unit>): androidx.compose.foundation.gestures/DraggableState // androidx.compose.foundation.gestures/DraggableState|DraggableState(kotlin.Function1<kotlin.Float,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.gestures/ScrollableState(kotlin/Function1<kotlin/Float, kotlin/Float>): androidx.compose.foundation.gestures/ScrollableState // androidx.compose.foundation.gestures/ScrollableState|ScrollableState(kotlin.Function1<kotlin.Float,kotlin.Float>){}[0]
 final fun androidx.compose.foundation.gestures/TransformableState(kotlin/Function3<kotlin/Float, androidx.compose.ui.geometry/Offset, kotlin/Float, kotlin/Unit>): androidx.compose.foundation.gestures/TransformableState // androidx.compose.foundation.gestures/TransformableState|TransformableState(kotlin.Function3<kotlin.Float,androidx.compose.ui.geometry.Offset,kotlin.Float,kotlin.Unit>){}[0]
-final fun androidx.compose.foundation.gestures/rememberDraggable2DState(kotlin/Function1<androidx.compose.ui.geometry/Offset, kotlin/Unit>): androidx.compose.foundation.gestures/Draggable2DState // androidx.compose.foundation.gestures/rememberDraggable2DState|rememberDraggable2DState(kotlin.Function1<androidx.compose.ui.geometry.Offset,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.gestures/rememberDraggableState(kotlin/Function1<kotlin/Float, kotlin/Unit>): androidx.compose.foundation.gestures/DraggableState // androidx.compose.foundation.gestures/rememberDraggableState|rememberDraggableState(kotlin.Function1<kotlin.Float,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.gestures/rememberScrollableState(kotlin/Function1<kotlin/Float, kotlin/Float>): androidx.compose.foundation.gestures/ScrollableState // androidx.compose.foundation.gestures/rememberScrollableState|rememberScrollableState(kotlin.Function1<kotlin.Float,kotlin.Float>){}[0]
 final fun androidx.compose.foundation.gestures/rememberTransformableState(kotlin/Function3<kotlin/Float, androidx.compose.ui.geometry/Offset, kotlin/Float, kotlin/Unit>): androidx.compose.foundation.gestures/TransformableState // androidx.compose.foundation.gestures/rememberTransformableState|rememberTransformableState(kotlin.Function3<kotlin.Float,androidx.compose.ui.geometry.Offset,kotlin.Float,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.interaction/MutableInteractionSource(): androidx.compose.foundation.interaction/MutableInteractionSource // androidx.compose.foundation.interaction/MutableInteractionSource|MutableInteractionSource(){}[0]
 final fun androidx.compose.foundation.lazy.grid/GridItemSpan(kotlin/Int): androidx.compose.foundation.lazy.grid/GridItemSpan // androidx.compose.foundation.lazy.grid/GridItemSpan|GridItemSpan(kotlin.Int){}[0]
-final fun androidx.compose.foundation.lazy.grid/LazyGridPrefetchStrategy(kotlin/Int =...): androidx.compose.foundation.lazy.grid/LazyGridPrefetchStrategy // androidx.compose.foundation.lazy.grid/LazyGridPrefetchStrategy|LazyGridPrefetchStrategy(kotlin.Int){}[0]
 final fun androidx.compose.foundation.lazy.grid/LazyHorizontalGrid(androidx.compose.foundation.lazy.grid/GridCells, androidx.compose.ui/Modifier =..., androidx.compose.foundation.lazy.grid/LazyGridState =..., androidx.compose.foundation.layout/PaddingValues =..., kotlin/Boolean =..., androidx.compose.foundation.layout/Arrangement.Horizontal =..., androidx.compose.foundation.layout/Arrangement.Vertical =..., androidx.compose.foundation.gestures/FlingBehavior =..., kotlin/Boolean =..., kotlin/Function1<androidx.compose.foundation.lazy.grid/LazyGridScope, kotlin/Unit>) // androidx.compose.foundation.lazy.grid/LazyHorizontalGrid|LazyHorizontalGrid(androidx.compose.foundation.lazy.grid.GridCells;androidx.compose.ui.Modifier;androidx.compose.foundation.lazy.grid.LazyGridState;androidx.compose.foundation.layout.PaddingValues;kotlin.Boolean;androidx.compose.foundation.layout.Arrangement.Horizontal;androidx.compose.foundation.layout.Arrangement.Vertical;androidx.compose.foundation.gestures.FlingBehavior;kotlin.Boolean;kotlin.Function1<androidx.compose.foundation.lazy.grid.LazyGridScope,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.lazy.grid/LazyVerticalGrid(androidx.compose.foundation.lazy.grid/GridCells, androidx.compose.ui/Modifier =..., androidx.compose.foundation.lazy.grid/LazyGridState =..., androidx.compose.foundation.layout/PaddingValues =..., kotlin/Boolean =..., androidx.compose.foundation.layout/Arrangement.Vertical =..., androidx.compose.foundation.layout/Arrangement.Horizontal =..., androidx.compose.foundation.gestures/FlingBehavior =..., kotlin/Boolean =..., kotlin/Function1<androidx.compose.foundation.lazy.grid/LazyGridScope, kotlin/Unit>) // androidx.compose.foundation.lazy.grid/LazyVerticalGrid|LazyVerticalGrid(androidx.compose.foundation.lazy.grid.GridCells;androidx.compose.ui.Modifier;androidx.compose.foundation.lazy.grid.LazyGridState;androidx.compose.foundation.layout.PaddingValues;kotlin.Boolean;androidx.compose.foundation.layout.Arrangement.Vertical;androidx.compose.foundation.layout.Arrangement.Horizontal;androidx.compose.foundation.gestures.FlingBehavior;kotlin.Boolean;kotlin.Function1<androidx.compose.foundation.lazy.grid.LazyGridScope,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.lazy.grid/rememberLazyGridState(kotlin/Int =..., kotlin/Int =...): androidx.compose.foundation.lazy.grid/LazyGridState // androidx.compose.foundation.lazy.grid/rememberLazyGridState|rememberLazyGridState(kotlin.Int;kotlin.Int){}[0]
-final fun androidx.compose.foundation.lazy.grid/rememberLazyGridState(kotlin/Int =..., kotlin/Int =..., androidx.compose.foundation.lazy.grid/LazyGridPrefetchStrategy =...): androidx.compose.foundation.lazy.grid/LazyGridState // androidx.compose.foundation.lazy.grid/rememberLazyGridState|rememberLazyGridState(kotlin.Int;kotlin.Int;androidx.compose.foundation.lazy.grid.LazyGridPrefetchStrategy){}[0]
-final fun androidx.compose.foundation.lazy.layout/LazyLayout(androidx.compose.foundation.lazy.layout/LazyLayoutItemProvider, androidx.compose.ui/Modifier =..., androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState? =..., kotlin/Function2<androidx.compose.foundation.lazy.layout/LazyLayoutMeasureScope, androidx.compose.ui.unit/Constraints, androidx.compose.ui.layout/MeasureResult>) // androidx.compose.foundation.lazy.layout/LazyLayout|LazyLayout(androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider;androidx.compose.ui.Modifier;androidx.compose.foundation.lazy.layout.LazyLayoutPrefetchState?;kotlin.Function2<androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope,androidx.compose.ui.unit.Constraints,androidx.compose.ui.layout.MeasureResult>){}[0]
-final fun androidx.compose.foundation.lazy.layout/LazyLayout(kotlin/Function0<androidx.compose.foundation.lazy.layout/LazyLayoutItemProvider>, androidx.compose.ui/Modifier =..., androidx.compose.foundation.lazy.layout/LazyLayoutPrefetchState? =..., kotlin/Function2<androidx.compose.foundation.lazy.layout/LazyLayoutMeasureScope, androidx.compose.ui.unit/Constraints, androidx.compose.ui.layout/MeasureResult>) // androidx.compose.foundation.lazy.layout/LazyLayout|LazyLayout(kotlin.Function0<androidx.compose.foundation.lazy.layout.LazyLayoutItemProvider>;androidx.compose.ui.Modifier;androidx.compose.foundation.lazy.layout.LazyLayoutPrefetchState?;kotlin.Function2<androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScope,androidx.compose.ui.unit.Constraints,androidx.compose.ui.layout.MeasureResult>){}[0]
-final fun androidx.compose.foundation.lazy.layout/LazyLayoutPinnableItem(kotlin/Any?, kotlin/Int, androidx.compose.foundation.lazy.layout/LazyLayoutPinnedItemList, kotlin/Function0<kotlin/Unit>) // androidx.compose.foundation.lazy.layout/LazyLayoutPinnableItem|LazyLayoutPinnableItem(kotlin.Any?;kotlin.Int;androidx.compose.foundation.lazy.layout.LazyLayoutPinnedItemList;kotlin.Function0<kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.lazy.layout/getDefaultLazyLayoutKey(kotlin/Int): kotlin/Any // androidx.compose.foundation.lazy.layout/getDefaultLazyLayoutKey|getDefaultLazyLayoutKey(kotlin.Int){}[0]
-final fun androidx.compose.foundation.lazy.layout/rememberDefaultPrefetchScheduler(): androidx.compose.foundation.lazy.layout/PrefetchScheduler // androidx.compose.foundation.lazy.layout/rememberDefaultPrefetchScheduler|rememberDefaultPrefetchScheduler(){}[0]
 final fun androidx.compose.foundation.lazy.staggeredgrid/LazyHorizontalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid/StaggeredGridCells, androidx.compose.ui/Modifier =..., androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridState =..., androidx.compose.foundation.layout/PaddingValues =..., kotlin/Boolean =..., androidx.compose.foundation.layout/Arrangement.Vertical =..., androidx.compose.ui.unit/Dp =..., androidx.compose.foundation.gestures/FlingBehavior =..., kotlin/Boolean =..., kotlin/Function1<androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridScope, kotlin/Unit>) // androidx.compose.foundation.lazy.staggeredgrid/LazyHorizontalStaggeredGrid|LazyHorizontalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells;androidx.compose.ui.Modifier;androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState;androidx.compose.foundation.layout.PaddingValues;kotlin.Boolean;androidx.compose.foundation.layout.Arrangement.Vertical;androidx.compose.ui.unit.Dp;androidx.compose.foundation.gestures.FlingBehavior;kotlin.Boolean;kotlin.Function1<androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridScope,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.lazy.staggeredgrid/LazyVerticalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid/StaggeredGridCells, androidx.compose.ui/Modifier =..., androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridState =..., androidx.compose.foundation.layout/PaddingValues =..., kotlin/Boolean =..., androidx.compose.ui.unit/Dp =..., androidx.compose.foundation.layout/Arrangement.Horizontal =..., androidx.compose.foundation.gestures/FlingBehavior =..., kotlin/Boolean =..., kotlin/Function1<androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridScope, kotlin/Unit>) // androidx.compose.foundation.lazy.staggeredgrid/LazyVerticalStaggeredGrid|LazyVerticalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells;androidx.compose.ui.Modifier;androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState;androidx.compose.foundation.layout.PaddingValues;kotlin.Boolean;androidx.compose.ui.unit.Dp;androidx.compose.foundation.layout.Arrangement.Horizontal;androidx.compose.foundation.gestures.FlingBehavior;kotlin.Boolean;kotlin.Function1<androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridScope,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.lazy.staggeredgrid/rememberLazyStaggeredGridState(kotlin/Int =..., kotlin/Int =...): androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridState // androidx.compose.foundation.lazy.staggeredgrid/rememberLazyStaggeredGridState|rememberLazyStaggeredGridState(kotlin.Int;kotlin.Int){}[0]
 final fun androidx.compose.foundation.lazy/LazyColumn(androidx.compose.ui/Modifier =..., androidx.compose.foundation.lazy/LazyListState =..., androidx.compose.foundation.layout/PaddingValues =..., kotlin/Boolean =..., androidx.compose.foundation.layout/Arrangement.Vertical =..., androidx.compose.ui/Alignment.Horizontal =..., androidx.compose.foundation.gestures/FlingBehavior =..., kotlin/Boolean =..., kotlin/Function1<androidx.compose.foundation.lazy/LazyListScope, kotlin/Unit>) // androidx.compose.foundation.lazy/LazyColumn|LazyColumn(androidx.compose.ui.Modifier;androidx.compose.foundation.lazy.LazyListState;androidx.compose.foundation.layout.PaddingValues;kotlin.Boolean;androidx.compose.foundation.layout.Arrangement.Vertical;androidx.compose.ui.Alignment.Horizontal;androidx.compose.foundation.gestures.FlingBehavior;kotlin.Boolean;kotlin.Function1<androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.lazy/LazyColumn(androidx.compose.ui/Modifier =..., androidx.compose.foundation.lazy/LazyListState =..., androidx.compose.foundation.layout/PaddingValues =..., kotlin/Boolean =..., androidx.compose.foundation.layout/Arrangement.Vertical =..., androidx.compose.ui/Alignment.Horizontal =..., androidx.compose.foundation.gestures/FlingBehavior =..., kotlin/Function1<androidx.compose.foundation.lazy/LazyListScope, kotlin/Unit>) // androidx.compose.foundation.lazy/LazyColumn|LazyColumn(androidx.compose.ui.Modifier;androidx.compose.foundation.lazy.LazyListState;androidx.compose.foundation.layout.PaddingValues;kotlin.Boolean;androidx.compose.foundation.layout.Arrangement.Vertical;androidx.compose.ui.Alignment.Horizontal;androidx.compose.foundation.gestures.FlingBehavior;kotlin.Function1<androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit>){}[0]
-final fun androidx.compose.foundation.lazy/LazyListPrefetchStrategy(kotlin/Int =...): androidx.compose.foundation.lazy/LazyListPrefetchStrategy // androidx.compose.foundation.lazy/LazyListPrefetchStrategy|LazyListPrefetchStrategy(kotlin.Int){}[0]
 final fun androidx.compose.foundation.lazy/LazyRow(androidx.compose.ui/Modifier =..., androidx.compose.foundation.lazy/LazyListState =..., androidx.compose.foundation.layout/PaddingValues =..., kotlin/Boolean =..., androidx.compose.foundation.layout/Arrangement.Horizontal =..., androidx.compose.ui/Alignment.Vertical =..., androidx.compose.foundation.gestures/FlingBehavior =..., kotlin/Boolean =..., kotlin/Function1<androidx.compose.foundation.lazy/LazyListScope, kotlin/Unit>) // androidx.compose.foundation.lazy/LazyRow|LazyRow(androidx.compose.ui.Modifier;androidx.compose.foundation.lazy.LazyListState;androidx.compose.foundation.layout.PaddingValues;kotlin.Boolean;androidx.compose.foundation.layout.Arrangement.Horizontal;androidx.compose.ui.Alignment.Vertical;androidx.compose.foundation.gestures.FlingBehavior;kotlin.Boolean;kotlin.Function1<androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.lazy/LazyRow(androidx.compose.ui/Modifier =..., androidx.compose.foundation.lazy/LazyListState =..., androidx.compose.foundation.layout/PaddingValues =..., kotlin/Boolean =..., androidx.compose.foundation.layout/Arrangement.Horizontal =..., androidx.compose.ui/Alignment.Vertical =..., androidx.compose.foundation.gestures/FlingBehavior =..., kotlin/Function1<androidx.compose.foundation.lazy/LazyListScope, kotlin/Unit>) // androidx.compose.foundation.lazy/LazyRow|LazyRow(androidx.compose.ui.Modifier;androidx.compose.foundation.lazy.LazyListState;androidx.compose.foundation.layout.PaddingValues;kotlin.Boolean;androidx.compose.foundation.layout.Arrangement.Horizontal;androidx.compose.ui.Alignment.Vertical;androidx.compose.foundation.gestures.FlingBehavior;kotlin.Function1<androidx.compose.foundation.lazy.LazyListScope,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.lazy/rememberLazyListState(kotlin/Int =..., kotlin/Int =...): androidx.compose.foundation.lazy/LazyListState // androidx.compose.foundation.lazy/rememberLazyListState|rememberLazyListState(kotlin.Int;kotlin.Int){}[0]
-final fun androidx.compose.foundation.lazy/rememberLazyListState(kotlin/Int =..., kotlin/Int =..., androidx.compose.foundation.lazy/LazyListPrefetchStrategy =...): androidx.compose.foundation.lazy/LazyListState // androidx.compose.foundation.lazy/rememberLazyListState|rememberLazyListState(kotlin.Int;kotlin.Int;androidx.compose.foundation.lazy.LazyListPrefetchStrategy){}[0]
 final fun androidx.compose.foundation.pager/HorizontalPager(androidx.compose.foundation.pager/PagerState, androidx.compose.ui/Modifier =..., androidx.compose.foundation.layout/PaddingValues =..., androidx.compose.foundation.pager/PageSize =..., kotlin/Int =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui/Alignment.Vertical =..., androidx.compose.foundation.gestures/TargetedFlingBehavior =..., kotlin/Boolean =..., kotlin/Boolean =..., kotlin/Function1<kotlin/Int, kotlin/Any>? =..., androidx.compose.ui.input.nestedscroll/NestedScrollConnection =..., androidx.compose.foundation.gestures.snapping/SnapPosition =..., kotlin/Function2<androidx.compose.foundation.pager/PagerScope, kotlin/Int, kotlin/Unit>) // androidx.compose.foundation.pager/HorizontalPager|HorizontalPager(androidx.compose.foundation.pager.PagerState;androidx.compose.ui.Modifier;androidx.compose.foundation.layout.PaddingValues;androidx.compose.foundation.pager.PageSize;kotlin.Int;androidx.compose.ui.unit.Dp;androidx.compose.ui.Alignment.Vertical;androidx.compose.foundation.gestures.TargetedFlingBehavior;kotlin.Boolean;kotlin.Boolean;kotlin.Function1<kotlin.Int,kotlin.Any>?;androidx.compose.ui.input.nestedscroll.NestedScrollConnection;androidx.compose.foundation.gestures.snapping.SnapPosition;kotlin.Function2<androidx.compose.foundation.pager.PagerScope,kotlin.Int,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.pager/PagerState(kotlin/Int =..., kotlin/Float =..., kotlin/Function0<kotlin/Int>): androidx.compose.foundation.pager/PagerState // androidx.compose.foundation.pager/PagerState|PagerState(kotlin.Int;kotlin.Float;kotlin.Function0<kotlin.Int>){}[0]
 final fun androidx.compose.foundation.pager/VerticalPager(androidx.compose.foundation.pager/PagerState, androidx.compose.ui/Modifier =..., androidx.compose.foundation.layout/PaddingValues =..., androidx.compose.foundation.pager/PageSize =..., kotlin/Int =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui/Alignment.Horizontal =..., androidx.compose.foundation.gestures/TargetedFlingBehavior =..., kotlin/Boolean =..., kotlin/Boolean =..., kotlin/Function1<kotlin/Int, kotlin/Any>? =..., androidx.compose.ui.input.nestedscroll/NestedScrollConnection =..., androidx.compose.foundation.gestures.snapping/SnapPosition =..., kotlin/Function2<androidx.compose.foundation.pager/PagerScope, kotlin/Int, kotlin/Unit>) // androidx.compose.foundation.pager/VerticalPager|VerticalPager(androidx.compose.foundation.pager.PagerState;androidx.compose.ui.Modifier;androidx.compose.foundation.layout.PaddingValues;androidx.compose.foundation.pager.PageSize;kotlin.Int;androidx.compose.ui.unit.Dp;androidx.compose.ui.Alignment.Horizontal;androidx.compose.foundation.gestures.TargetedFlingBehavior;kotlin.Boolean;kotlin.Boolean;kotlin.Function1<kotlin.Int,kotlin.Any>?;androidx.compose.ui.input.nestedscroll.NestedScrollConnection;androidx.compose.foundation.gestures.snapping.SnapPosition;kotlin.Function2<androidx.compose.foundation.pager.PagerScope,kotlin.Int,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.pager/rememberPagerState(kotlin/Int =..., kotlin/Float =..., kotlin/Function0<kotlin/Int>): androidx.compose.foundation.pager/PagerState // androidx.compose.foundation.pager/rememberPagerState|rememberPagerState(kotlin.Int;kotlin.Float;kotlin.Function0<kotlin.Int>){}[0]
-final fun androidx.compose.foundation.relocation/BringIntoViewRequester(): androidx.compose.foundation.relocation/BringIntoViewRequester // androidx.compose.foundation.relocation/BringIntoViewRequester|BringIntoViewRequester(){}[0]
 final fun androidx.compose.foundation.shape/AbsoluteCutCornerShape(androidx.compose.foundation.shape/CornerSize): androidx.compose.foundation.shape/AbsoluteCutCornerShape // androidx.compose.foundation.shape/AbsoluteCutCornerShape|AbsoluteCutCornerShape(androidx.compose.foundation.shape.CornerSize){}[0]
 final fun androidx.compose.foundation.shape/AbsoluteCutCornerShape(androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =...): androidx.compose.foundation.shape/AbsoluteCutCornerShape // androidx.compose.foundation.shape/AbsoluteCutCornerShape|AbsoluteCutCornerShape(androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp){}[0]
 final fun androidx.compose.foundation.shape/AbsoluteCutCornerShape(androidx.compose.ui.unit/Dp): androidx.compose.foundation.shape/AbsoluteCutCornerShape // androidx.compose.foundation.shape/AbsoluteCutCornerShape|AbsoluteCutCornerShape(androidx.compose.ui.unit.Dp){}[0]
@@ -1053,14 +783,10 @@
 final fun androidx.compose.foundation.text/BasicTextField(kotlin/String, kotlin/Function1<kotlin/String, kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., kotlin/Boolean =..., androidx.compose.ui.text/TextStyle =..., androidx.compose.foundation.text/KeyboardOptions =..., androidx.compose.foundation.text/KeyboardActions =..., kotlin/Boolean =..., kotlin/Int =..., androidx.compose.ui.text.input/VisualTransformation =..., kotlin/Function1<androidx.compose.ui.text/TextLayoutResult, kotlin/Unit> =..., androidx.compose.foundation.interaction/MutableInteractionSource =..., androidx.compose.ui.graphics/Brush =..., kotlin/Function1<kotlin/Function0<kotlin/Unit>, kotlin/Unit> =...) // androidx.compose.foundation.text/BasicTextField|BasicTextField(kotlin.String;kotlin.Function1<kotlin.String,kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;kotlin.Boolean;androidx.compose.ui.text.TextStyle;androidx.compose.foundation.text.KeyboardOptions;androidx.compose.foundation.text.KeyboardActions;kotlin.Boolean;kotlin.Int;androidx.compose.ui.text.input.VisualTransformation;kotlin.Function1<androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>;androidx.compose.foundation.interaction.MutableInteractionSource;androidx.compose.ui.graphics.Brush;kotlin.Function1<kotlin.Function0<kotlin.Unit>,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.text/BasicTextField(kotlin/String, kotlin/Function1<kotlin/String, kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., kotlin/Boolean =..., androidx.compose.ui.text/TextStyle =..., androidx.compose.foundation.text/KeyboardOptions =..., androidx.compose.foundation.text/KeyboardActions =..., kotlin/Boolean =..., kotlin/Int =..., kotlin/Int =..., androidx.compose.ui.text.input/VisualTransformation =..., kotlin/Function1<androidx.compose.ui.text/TextLayoutResult, kotlin/Unit> =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.ui.graphics/Brush =..., kotlin/Function1<kotlin/Function0<kotlin/Unit>, kotlin/Unit> =...) // androidx.compose.foundation.text/BasicTextField|BasicTextField(kotlin.String;kotlin.Function1<kotlin.String,kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;kotlin.Boolean;androidx.compose.ui.text.TextStyle;androidx.compose.foundation.text.KeyboardOptions;androidx.compose.foundation.text.KeyboardActions;kotlin.Boolean;kotlin.Int;kotlin.Int;androidx.compose.ui.text.input.VisualTransformation;kotlin.Function1<androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.ui.graphics.Brush;kotlin.Function1<kotlin.Function0<kotlin.Unit>,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.text/ClickableText(androidx.compose.ui.text/AnnotatedString, androidx.compose.ui/Modifier =..., androidx.compose.ui.text/TextStyle =..., kotlin/Boolean =..., androidx.compose.ui.text.style/TextOverflow =..., kotlin/Int =..., kotlin/Function1<androidx.compose.ui.text/TextLayoutResult, kotlin/Unit> =..., kotlin/Function1<kotlin/Int, kotlin/Unit>) // androidx.compose.foundation.text/ClickableText|ClickableText(androidx.compose.ui.text.AnnotatedString;androidx.compose.ui.Modifier;androidx.compose.ui.text.TextStyle;kotlin.Boolean;androidx.compose.ui.text.style.TextOverflow;kotlin.Int;kotlin.Function1<androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>;kotlin.Function1<kotlin.Int,kotlin.Unit>){}[0]
-final fun androidx.compose.foundation.text/ClickableText(androidx.compose.ui.text/AnnotatedString, kotlin/Function1<kotlin/Int?, kotlin/Unit>, androidx.compose.ui/Modifier =..., androidx.compose.ui.text/TextStyle =..., kotlin/Boolean =..., androidx.compose.ui.text.style/TextOverflow =..., kotlin/Int =..., kotlin/Function1<androidx.compose.ui.text/TextLayoutResult, kotlin/Unit> =..., kotlin/Function1<kotlin/Int, kotlin/Unit>) // androidx.compose.foundation.text/ClickableText|ClickableText(androidx.compose.ui.text.AnnotatedString;kotlin.Function1<kotlin.Int?,kotlin.Unit>;androidx.compose.ui.Modifier;androidx.compose.ui.text.TextStyle;kotlin.Boolean;androidx.compose.ui.text.style.TextOverflow;kotlin.Int;kotlin.Function1<androidx.compose.ui.text.TextLayoutResult,kotlin.Unit>;kotlin.Function1<kotlin.Int,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation.text/KeyboardActions(kotlin/Function1<androidx.compose.foundation.text/KeyboardActionScope, kotlin/Unit>): androidx.compose.foundation.text/KeyboardActions // androidx.compose.foundation.text/KeyboardActions|KeyboardActions(kotlin.Function1<androidx.compose.foundation.text.KeyboardActionScope,kotlin.Unit>){}[0]
-final fun androidx.compose.foundation/BasicTooltipBox(androidx.compose.ui.window/PopupPositionProvider, kotlin/Function0<kotlin/Unit>, androidx.compose.foundation/BasicTooltipState, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., kotlin/Boolean =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.foundation/BasicTooltipBox|BasicTooltipBox(androidx.compose.ui.window.PopupPositionProvider;kotlin.Function0<kotlin.Unit>;androidx.compose.foundation.BasicTooltipState;androidx.compose.ui.Modifier;kotlin.Boolean;kotlin.Boolean;kotlin.Function0<kotlin.Unit>){}[0]
-final fun androidx.compose.foundation/BasicTooltipState(kotlin/Boolean =..., kotlin/Boolean =..., androidx.compose.foundation/MutatorMutex =...): androidx.compose.foundation/BasicTooltipState // androidx.compose.foundation/BasicTooltipState|BasicTooltipState(kotlin.Boolean;kotlin.Boolean;androidx.compose.foundation.MutatorMutex){}[0]
 final fun androidx.compose.foundation/BorderStroke(androidx.compose.ui.unit/Dp, androidx.compose.ui.graphics/Color): androidx.compose.foundation/BorderStroke // androidx.compose.foundation/BorderStroke|BorderStroke(androidx.compose.ui.unit.Dp;androidx.compose.ui.graphics.Color){}[0]
 final fun androidx.compose.foundation/Canvas(androidx.compose.ui/Modifier, kotlin/Function1<androidx.compose.ui.graphics.drawscope/DrawScope, kotlin/Unit>) // androidx.compose.foundation/Canvas|Canvas(androidx.compose.ui.Modifier;kotlin.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit>){}[0]
 final fun androidx.compose.foundation/Canvas(androidx.compose.ui/Modifier, kotlin/String, kotlin/Function1<androidx.compose.ui.graphics.drawscope/DrawScope, kotlin/Unit>) // androidx.compose.foundation/Canvas|Canvas(androidx.compose.ui.Modifier;kotlin.String;kotlin.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit>){}[0]
-final fun androidx.compose.foundation/CombinedClickableNode(kotlin/Function0<kotlin/Unit>, kotlin/String?, kotlin/Function0<kotlin/Unit>?, kotlin/Function0<kotlin/Unit>?, androidx.compose.foundation.interaction/MutableInteractionSource?, androidx.compose.foundation/IndicationNodeFactory?, kotlin/Boolean, kotlin/String?, androidx.compose.ui.semantics/Role?): androidx.compose.foundation/CombinedClickableNode // androidx.compose.foundation/CombinedClickableNode|CombinedClickableNode(kotlin.Function0<kotlin.Unit>;kotlin.String?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.foundation.IndicationNodeFactory?;kotlin.Boolean;kotlin.String?;androidx.compose.ui.semantics.Role?){}[0]
 final fun androidx.compose.foundation/Image(androidx.compose.ui.graphics.painter/Painter, kotlin/String?, androidx.compose.ui/Modifier =..., androidx.compose.ui/Alignment =..., androidx.compose.ui.layout/ContentScale =..., kotlin/Float =..., androidx.compose.ui.graphics/ColorFilter? =...) // androidx.compose.foundation/Image|Image(androidx.compose.ui.graphics.painter.Painter;kotlin.String?;androidx.compose.ui.Modifier;androidx.compose.ui.Alignment;androidx.compose.ui.layout.ContentScale;kotlin.Float;androidx.compose.ui.graphics.ColorFilter?){}[0]
 final fun androidx.compose.foundation/Image(androidx.compose.ui.graphics.vector/ImageVector, kotlin/String?, androidx.compose.ui/Modifier =..., androidx.compose.ui/Alignment =..., androidx.compose.ui.layout/ContentScale =..., kotlin/Float =..., androidx.compose.ui.graphics/ColorFilter? =...) // androidx.compose.foundation/Image|Image(androidx.compose.ui.graphics.vector.ImageVector;kotlin.String?;androidx.compose.ui.Modifier;androidx.compose.ui.Alignment;androidx.compose.ui.layout.ContentScale;kotlin.Float;androidx.compose.ui.graphics.ColorFilter?){}[0]
 final fun androidx.compose.foundation/Image(androidx.compose.ui.graphics/ImageBitmap, kotlin/String?, androidx.compose.ui/Modifier =..., androidx.compose.ui/Alignment =..., androidx.compose.ui.layout/ContentScale =..., kotlin/Float =..., androidx.compose.ui.graphics/ColorFilter? =...) // androidx.compose.foundation/Image|Image(androidx.compose.ui.graphics.ImageBitmap;kotlin.String?;androidx.compose.ui.Modifier;androidx.compose.ui.Alignment;androidx.compose.ui.layout.ContentScale;kotlin.Float;androidx.compose.ui.graphics.ColorFilter?){}[0]
@@ -1068,10 +794,7 @@
 final fun androidx.compose.foundation/MarqueeSpacing(androidx.compose.ui.unit/Dp): androidx.compose.foundation/MarqueeSpacing // androidx.compose.foundation/MarqueeSpacing|MarqueeSpacing(androidx.compose.ui.unit.Dp){}[0]
 final fun androidx.compose.foundation/checkScrollableContainerConstraints(androidx.compose.ui.unit/Constraints, androidx.compose.foundation.gestures/Orientation) // androidx.compose.foundation/checkScrollableContainerConstraints|checkScrollableContainerConstraints(androidx.compose.ui.unit.Constraints;androidx.compose.foundation.gestures.Orientation){}[0]
 final fun androidx.compose.foundation/isSystemInDarkTheme(): kotlin/Boolean // androidx.compose.foundation/isSystemInDarkTheme|isSystemInDarkTheme(){}[0]
-final fun androidx.compose.foundation/rememberBasicTooltipState(kotlin/Boolean =..., kotlin/Boolean =..., androidx.compose.foundation/MutatorMutex =...): androidx.compose.foundation/BasicTooltipState // androidx.compose.foundation/rememberBasicTooltipState|rememberBasicTooltipState(kotlin.Boolean;kotlin.Boolean;androidx.compose.foundation.MutatorMutex){}[0]
 final fun androidx.compose.foundation/rememberScrollState(kotlin/Int =...): androidx.compose.foundation/ScrollState // androidx.compose.foundation/rememberScrollState|rememberScrollState(kotlin.Int){}[0]
-final inline fun (androidx.compose.foundation.text.input/TextFieldBuffer.ChangeList).androidx.compose.foundation.text.input/forEachChange(kotlin/Function2<androidx.compose.ui.text/TextRange, androidx.compose.ui.text/TextRange, kotlin/Unit>) // androidx.compose.foundation.text.input/forEachChange|forEachChange@androidx.compose.foundation.text.input.TextFieldBuffer.ChangeList(kotlin.Function2<androidx.compose.ui.text.TextRange,androidx.compose.ui.text.TextRange,kotlin.Unit>){}[0]
-final inline fun (androidx.compose.foundation.text.input/TextFieldBuffer.ChangeList).androidx.compose.foundation.text.input/forEachChangeReversed(kotlin/Function2<androidx.compose.ui.text/TextRange, androidx.compose.ui.text/TextRange, kotlin/Unit>) // androidx.compose.foundation.text.input/forEachChangeReversed|forEachChangeReversed@androidx.compose.foundation.text.input.TextFieldBuffer.ChangeList(kotlin.Function2<androidx.compose.ui.text.TextRange,androidx.compose.ui.text.TextRange,kotlin.Unit>){}[0]
 final inline fun <#A: kotlin/Any?> (androidx.compose.foundation.lazy.grid/LazyGridScope).androidx.compose.foundation.lazy.grid/items(kotlin.collections/List<#A>, noinline kotlin/Function1<#A, kotlin/Any>? =..., noinline kotlin/Function2<androidx.compose.foundation.lazy.grid/LazyGridItemSpanScope, #A, androidx.compose.foundation.lazy.grid/GridItemSpan>? =..., noinline kotlin/Function1<#A, kotlin/Any?> =..., crossinline kotlin/Function2<androidx.compose.foundation.lazy.grid/LazyGridItemScope, #A, kotlin/Unit>) // androidx.compose.foundation.lazy.grid/items|[email protected](kotlin.collections.List<0:0>;kotlin.Function1<0:0,kotlin.Any>?;kotlin.Function2<androidx.compose.foundation.lazy.grid.LazyGridItemSpanScope,0:0,androidx.compose.foundation.lazy.grid.GridItemSpan>?;kotlin.Function1<0:0,kotlin.Any?>;kotlin.Function2<androidx.compose.foundation.lazy.grid.LazyGridItemScope,0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
 final inline fun <#A: kotlin/Any?> (androidx.compose.foundation.lazy.grid/LazyGridScope).androidx.compose.foundation.lazy.grid/items(kotlin/Array<#A>, noinline kotlin/Function1<#A, kotlin/Any>? =..., noinline kotlin/Function2<androidx.compose.foundation.lazy.grid/LazyGridItemSpanScope, #A, androidx.compose.foundation.lazy.grid/GridItemSpan>? =..., noinline kotlin/Function1<#A, kotlin/Any?> =..., crossinline kotlin/Function2<androidx.compose.foundation.lazy.grid/LazyGridItemScope, #A, kotlin/Unit>) // androidx.compose.foundation.lazy.grid/items|[email protected](kotlin.Array<0:0>;kotlin.Function1<0:0,kotlin.Any>?;kotlin.Function2<androidx.compose.foundation.lazy.grid.LazyGridItemSpanScope,0:0,androidx.compose.foundation.lazy.grid.GridItemSpan>?;kotlin.Function1<0:0,kotlin.Any?>;kotlin.Function2<androidx.compose.foundation.lazy.grid.LazyGridItemScope,0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
 final inline fun <#A: kotlin/Any?> (androidx.compose.foundation.lazy.grid/LazyGridScope).androidx.compose.foundation.lazy.grid/itemsIndexed(kotlin.collections/List<#A>, noinline kotlin/Function2<kotlin/Int, #A, kotlin/Any>? =..., noinline kotlin/Function3<androidx.compose.foundation.lazy.grid/LazyGridItemSpanScope, kotlin/Int, #A, androidx.compose.foundation.lazy.grid/GridItemSpan>? =..., crossinline kotlin/Function2<kotlin/Int, #A, kotlin/Any?> =..., crossinline kotlin/Function3<androidx.compose.foundation.lazy.grid/LazyGridItemScope, kotlin/Int, #A, kotlin/Unit>) // androidx.compose.foundation.lazy.grid/itemsIndexed|[email protected](kotlin.collections.List<0:0>;kotlin.Function2<kotlin.Int,0:0,kotlin.Any>?;kotlin.Function3<androidx.compose.foundation.lazy.grid.LazyGridItemSpanScope,kotlin.Int,0:0,androidx.compose.foundation.lazy.grid.GridItemSpan>?;kotlin.Function2<kotlin.Int,0:0,kotlin.Any?>;kotlin.Function3<androidx.compose.foundation.lazy.grid.LazyGridItemScope,kotlin.Int,0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
@@ -1089,9 +812,7 @@
 final inline fun <#A: kotlin/Any?> (androidx.compose.foundation.lazy/LazyListScope).androidx.compose.foundation.lazy/itemsIndexed(kotlin/Array<#A>, noinline kotlin/Function2<kotlin/Int, #A, kotlin/Any>? =..., crossinline kotlin/Function2<kotlin/Int, #A, kotlin/Any?> =..., crossinline kotlin/Function3<androidx.compose.foundation.lazy/LazyItemScope, kotlin/Int, #A, kotlin/Unit>) // androidx.compose.foundation.lazy/itemsIndexed|[email protected](kotlin.Array<0:0>;kotlin.Function2<kotlin.Int,0:0,kotlin.Any>?;kotlin.Function2<kotlin.Int,0:0,kotlin.Any?>;kotlin.Function3<androidx.compose.foundation.lazy.LazyItemScope,kotlin.Int,0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
 final inline fun <#A: kotlin/Any?> (androidx.compose.foundation.lazy/LazyListScope).androidx.compose.foundation.lazy/itemsIndexed(kotlin/Array<#A>, noinline kotlin/Function2<kotlin/Int, #A, kotlin/Any>? =..., crossinline kotlin/Function3<androidx.compose.foundation.lazy/LazyItemScope, kotlin/Int, #A, kotlin/Unit>) // androidx.compose.foundation.lazy/itemsIndexed|[email protected](kotlin.Array<0:0>;kotlin.Function2<kotlin.Int,0:0,kotlin.Any>?;kotlin.Function3<androidx.compose.foundation.lazy.LazyItemScope,kotlin.Int,0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
 final object androidx.compose.foundation.gestures/ScrollableDefaults { // androidx.compose.foundation.gestures/ScrollableDefaults|null[0]
-    final fun bringIntoViewSpec(): androidx.compose.foundation.gestures/BringIntoViewSpec // androidx.compose.foundation.gestures/ScrollableDefaults.bringIntoViewSpec|bringIntoViewSpec(){}[0]
     final fun flingBehavior(): androidx.compose.foundation.gestures/FlingBehavior // androidx.compose.foundation.gestures/ScrollableDefaults.flingBehavior|flingBehavior(){}[0]
-    final fun overscrollEffect(): androidx.compose.foundation/OverscrollEffect // androidx.compose.foundation.gestures/ScrollableDefaults.overscrollEffect|overscrollEffect(){}[0]
     final fun reverseDirection(androidx.compose.ui.unit/LayoutDirection, androidx.compose.foundation.gestures/Orientation, kotlin/Boolean): kotlin/Boolean // androidx.compose.foundation.gestures/ScrollableDefaults.reverseDirection|reverseDirection(androidx.compose.ui.unit.LayoutDirection;androidx.compose.foundation.gestures.Orientation;kotlin.Boolean){}[0]
 }
 final object androidx.compose.foundation.pager/PagerDefaults { // androidx.compose.foundation.pager/PagerDefaults|null[0]
@@ -1100,12 +821,6 @@
     final fun flingBehavior(androidx.compose.foundation.pager/PagerState, androidx.compose.foundation.pager/PagerSnapDistance =..., androidx.compose.animation.core/DecayAnimationSpec<kotlin/Float> =..., androidx.compose.animation.core/AnimationSpec<kotlin/Float> =..., kotlin/Float =...): androidx.compose.foundation.gestures/TargetedFlingBehavior // androidx.compose.foundation.pager/PagerDefaults.flingBehavior|flingBehavior(androidx.compose.foundation.pager.PagerState;androidx.compose.foundation.pager.PagerSnapDistance;androidx.compose.animation.core.DecayAnimationSpec<kotlin.Float>;androidx.compose.animation.core.AnimationSpec<kotlin.Float>;kotlin.Float){}[0]
     final fun pageNestedScrollConnection(androidx.compose.foundation.pager/PagerState, androidx.compose.foundation.gestures/Orientation): androidx.compose.ui.input.nestedscroll/NestedScrollConnection // androidx.compose.foundation.pager/PagerDefaults.pageNestedScrollConnection|pageNestedScrollConnection(androidx.compose.foundation.pager.PagerState;androidx.compose.foundation.gestures.Orientation){}[0]
 }
-final object androidx.compose.foundation/BasicTooltipDefaults { // androidx.compose.foundation/BasicTooltipDefaults|null[0]
-    final const val TooltipDuration // androidx.compose.foundation/BasicTooltipDefaults.TooltipDuration|<get-TooltipDuration>(){}[0]
-        final fun <get-TooltipDuration>(): kotlin/Long // androidx.compose.foundation/BasicTooltipDefaults.TooltipDuration.<get-TooltipDuration>|<get-TooltipDuration>(){}[0]
-    final val GlobalMutatorMutex // androidx.compose.foundation/BasicTooltipDefaults.GlobalMutatorMutex|<get-GlobalMutatorMutex>(){}[0]
-        final fun <get-GlobalMutatorMutex>(): androidx.compose.foundation/MutatorMutex // androidx.compose.foundation/BasicTooltipDefaults.GlobalMutatorMutex.<get-GlobalMutatorMutex>|<get-GlobalMutatorMutex>(){}[0]
-}
 final object androidx.compose.foundation/MarqueeDefaults { // androidx.compose.foundation/MarqueeDefaults|null[0]
     final val Iterations // androidx.compose.foundation/MarqueeDefaults.Iterations|{}Iterations[0]
         final fun <get-Iterations>(): kotlin/Int // androidx.compose.foundation/MarqueeDefaults.Iterations.<get-Iterations>|<get-Iterations>(){}[0]
@@ -1148,11 +863,6 @@
 final suspend fun (androidx.compose.ui.input.pointer/PointerInputScope).androidx.compose.foundation.gestures/detectTransformGestures(kotlin/Boolean =..., kotlin/Function4<androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset, kotlin/Float, kotlin/Float, kotlin/Unit>) // androidx.compose.foundation.gestures/detectTransformGestures|detectTransformGestures@androidx.compose.ui.input.pointer.PointerInputScope(kotlin.Boolean;kotlin.Function4<androidx.compose.ui.geometry.Offset,androidx.compose.ui.geometry.Offset,kotlin.Float,kotlin.Float,kotlin.Unit>){}[0]
 final suspend fun (androidx.compose.ui.input.pointer/PointerInputScope).androidx.compose.foundation.gestures/detectVerticalDragGestures(kotlin/Function1<androidx.compose.ui.geometry/Offset, kotlin/Unit> =..., kotlin/Function0<kotlin/Unit> =..., kotlin/Function0<kotlin/Unit> =..., kotlin/Function2<androidx.compose.ui.input.pointer/PointerInputChange, kotlin/Float, kotlin/Unit>) // androidx.compose.foundation.gestures/detectVerticalDragGestures|detectVerticalDragGestures@androidx.compose.ui.input.pointer.PointerInputScope(kotlin.Function1<androidx.compose.ui.geometry.Offset,kotlin.Unit>;kotlin.Function0<kotlin.Unit>;kotlin.Function0<kotlin.Unit>;kotlin.Function2<androidx.compose.ui.input.pointer.PointerInputChange,kotlin.Float,kotlin.Unit>){}[0]
 final suspend fun (androidx.compose.ui.input.pointer/PointerInputScope).androidx.compose.foundation.gestures/forEachGesture(kotlin.coroutines/SuspendFunction1<androidx.compose.ui.input.pointer/PointerInputScope, kotlin/Unit>) // androidx.compose.foundation.gestures/forEachGesture|forEachGesture@androidx.compose.ui.input.pointer.PointerInputScope(kotlin.coroutines.SuspendFunction1<androidx.compose.ui.input.pointer.PointerInputScope,kotlin.Unit>){}[0]
-final suspend fun <#A: kotlin/Any?> (androidx.compose.foundation.gestures/AnchoredDraggableState<#A>).androidx.compose.foundation.gestures/animateTo(#A) // androidx.compose.foundation.gestures/animateTo|animateTo@androidx.compose.foundation.gestures.AnchoredDraggableState<0:0>(0:0){0§<kotlin.Any?>}[0]
-final suspend fun <#A: kotlin/Any?> (androidx.compose.foundation.gestures/AnchoredDraggableState<#A>).androidx.compose.foundation.gestures/animateToWithDecay(#A, kotlin/Float): kotlin/Float // androidx.compose.foundation.gestures/animateToWithDecay|animateToWithDecay@androidx.compose.foundation.gestures.AnchoredDraggableState<0:0>(0:0;kotlin.Float){0§<kotlin.Any?>}[0]
-final suspend fun <#A: kotlin/Any?> (androidx.compose.foundation.gestures/AnchoredDraggableState<#A>).androidx.compose.foundation.gestures/snapTo(#A) // androidx.compose.foundation.gestures/snapTo|snapTo@androidx.compose.foundation.gestures.AnchoredDraggableState<0:0>(0:0){0§<kotlin.Any?>}[0]
-final val androidx.compose.foundation.gestures/LocalBringIntoViewSpec // androidx.compose.foundation.gestures/LocalBringIntoViewSpec|{}LocalBringIntoViewSpec[0]
-    final fun <get-LocalBringIntoViewSpec>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.foundation.gestures/BringIntoViewSpec> // androidx.compose.foundation.gestures/LocalBringIntoViewSpec.<get-LocalBringIntoViewSpec>|<get-LocalBringIntoViewSpec>(){}[0]
 final val androidx.compose.foundation.shape/CircleShape // androidx.compose.foundation.shape/CircleShape|{}CircleShape[0]
     final fun <get-CircleShape>(): androidx.compose.foundation.shape/RoundedCornerShape // androidx.compose.foundation.shape/CircleShape.<get-CircleShape>|<get-CircleShape>(){}[0]
 final val androidx.compose.foundation.shape/ZeroCornerSize // androidx.compose.foundation.shape/ZeroCornerSize|{}ZeroCornerSize[0]
@@ -1211,20 +921,6 @@
 open annotation class androidx.compose.foundation/InternalFoundationApi : kotlin/Annotation { // androidx.compose.foundation/InternalFoundationApi|null[0]
     constructor <init>() // androidx.compose.foundation/InternalFoundationApi.<init>|<init>(){}[0]
 }
-sealed interface <#A: out kotlin/Any?> androidx.compose.foundation.lazy.layout/IntervalList { // androidx.compose.foundation.lazy.layout/IntervalList|null[0]
-    abstract fun forEach(kotlin/Int =..., kotlin/Int =..., kotlin/Function1<androidx.compose.foundation.lazy.layout/IntervalList.Interval<#A>, kotlin/Unit>) // androidx.compose.foundation.lazy.layout/IntervalList.forEach|forEach(kotlin.Int;kotlin.Int;kotlin.Function1<androidx.compose.foundation.lazy.layout.IntervalList.Interval<1:0>,kotlin.Unit>){}[0]
-    abstract fun get(kotlin/Int): androidx.compose.foundation.lazy.layout/IntervalList.Interval<#A> // androidx.compose.foundation.lazy.layout/IntervalList.get|get(kotlin.Int){}[0]
-    abstract val size // androidx.compose.foundation.lazy.layout/IntervalList.size|{}size[0]
-        abstract fun <get-size>(): kotlin/Int // androidx.compose.foundation.lazy.layout/IntervalList.size.<get-size>|<get-size>(){}[0]
-    final class <#A1: out kotlin/Any?> Interval { // androidx.compose.foundation.lazy.layout/IntervalList.Interval|null[0]
-        final val size // androidx.compose.foundation.lazy.layout/IntervalList.Interval.size|{}size[0]
-            final fun <get-size>(): kotlin/Int // androidx.compose.foundation.lazy.layout/IntervalList.Interval.size.<get-size>|<get-size>(){}[0]
-        final val startIndex // androidx.compose.foundation.lazy.layout/IntervalList.Interval.startIndex|{}startIndex[0]
-            final fun <get-startIndex>(): kotlin/Int // androidx.compose.foundation.lazy.layout/IntervalList.Interval.startIndex.<get-startIndex>|<get-startIndex>(){}[0]
-        final val value // androidx.compose.foundation.lazy.layout/IntervalList.Interval.value|{}value[0]
-            final fun <get-value>(): #A1 // androidx.compose.foundation.lazy.layout/IntervalList.Interval.value.<get-value>|<get-value>(){}[0]
-    }
-}
 sealed interface androidx.compose.foundation.lazy.grid/LazyGridItemInfo { // androidx.compose.foundation.lazy.grid/LazyGridItemInfo|null[0]
     abstract val column // androidx.compose.foundation.lazy.grid/LazyGridItemInfo.column|{}column[0]
         abstract fun <get-column>(): kotlin/Int // androidx.compose.foundation.lazy.grid/LazyGridItemInfo.column.<get-column>|<get-column>(){}[0]
@@ -1249,7 +945,6 @@
 }
 sealed interface androidx.compose.foundation.lazy.grid/LazyGridItemScope { // androidx.compose.foundation.lazy.grid/LazyGridItemScope|null[0]
     abstract fun (androidx.compose.ui/Modifier).animateItem(androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float>? =..., androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntOffset>? =..., androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float>? =...): androidx.compose.ui/Modifier // androidx.compose.foundation.lazy.grid/LazyGridItemScope.animateItem|[email protected](androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>?;androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>?;androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>?){}[0]
-    open fun (androidx.compose.ui/Modifier).animateItemPlacement(androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntOffset> =...): androidx.compose.ui/Modifier // androidx.compose.foundation.lazy.grid/LazyGridItemScope.animateItemPlacement|[email protected](androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>){}[0]
 }
 sealed interface androidx.compose.foundation.lazy.grid/LazyGridItemSpanScope { // androidx.compose.foundation.lazy.grid/LazyGridItemSpanScope|null[0]
     abstract val maxCurrentLineSpan // androidx.compose.foundation.lazy.grid/LazyGridItemSpanScope.maxCurrentLineSpan|{}maxCurrentLineSpan[0]
@@ -1283,24 +978,6 @@
     abstract fun item(kotlin/Any? =..., kotlin/Function1<androidx.compose.foundation.lazy.grid/LazyGridItemSpanScope, androidx.compose.foundation.lazy.grid/GridItemSpan>? =..., kotlin/Any? =..., kotlin/Function1<androidx.compose.foundation.lazy.grid/LazyGridItemScope, kotlin/Unit>) // androidx.compose.foundation.lazy.grid/LazyGridScope.item|item(kotlin.Any?;kotlin.Function1<androidx.compose.foundation.lazy.grid.LazyGridItemSpanScope,androidx.compose.foundation.lazy.grid.GridItemSpan>?;kotlin.Any?;kotlin.Function1<androidx.compose.foundation.lazy.grid.LazyGridItemScope,kotlin.Unit>){}[0]
     abstract fun items(kotlin/Int, kotlin/Function1<kotlin/Int, kotlin/Any>? =..., kotlin/Function2<androidx.compose.foundation.lazy.grid/LazyGridItemSpanScope, kotlin/Int, androidx.compose.foundation.lazy.grid/GridItemSpan>? =..., kotlin/Function1<kotlin/Int, kotlin/Any?> =..., kotlin/Function2<androidx.compose.foundation.lazy.grid/LazyGridItemScope, kotlin/Int, kotlin/Unit>) // androidx.compose.foundation.lazy.grid/LazyGridScope.items|items(kotlin.Int;kotlin.Function1<kotlin.Int,kotlin.Any>?;kotlin.Function2<androidx.compose.foundation.lazy.grid.LazyGridItemSpanScope,kotlin.Int,androidx.compose.foundation.lazy.grid.GridItemSpan>?;kotlin.Function1<kotlin.Int,kotlin.Any?>;kotlin.Function2<androidx.compose.foundation.lazy.grid.LazyGridItemScope,kotlin.Int,kotlin.Unit>){}[0]
 }
-sealed interface androidx.compose.foundation.lazy.layout/LazyLayoutMeasureScope : androidx.compose.ui.layout/MeasureScope { // androidx.compose.foundation.lazy.layout/LazyLayoutMeasureScope|null[0]
-    abstract fun measure(kotlin/Int, androidx.compose.ui.unit/Constraints): kotlin.collections/List<androidx.compose.ui.layout/Placeable> // androidx.compose.foundation.lazy.layout/LazyLayoutMeasureScope.measure|measure(kotlin.Int;androidx.compose.ui.unit.Constraints){}[0]
-    open fun (androidx.compose.ui.geometry/Size).toDpSize(): androidx.compose.ui.unit/DpSize // androidx.compose.foundation.lazy.layout/LazyLayoutMeasureScope.toDpSize|[email protected](){}[0]
-    open fun (androidx.compose.ui.unit/Dp).toSp(): androidx.compose.ui.unit/TextUnit // androidx.compose.foundation.lazy.layout/LazyLayoutMeasureScope.toSp|[email protected](){}[0]
-    open fun (androidx.compose.ui.unit/DpSize).toSize(): androidx.compose.ui.geometry/Size // androidx.compose.foundation.lazy.layout/LazyLayoutMeasureScope.toSize|[email protected](){}[0]
-    open fun (androidx.compose.ui.unit/TextUnit).toDp(): androidx.compose.ui.unit/Dp // androidx.compose.foundation.lazy.layout/LazyLayoutMeasureScope.toDp|[email protected](){}[0]
-    open fun (kotlin/Float).toDp(): androidx.compose.ui.unit/Dp // androidx.compose.foundation.lazy.layout/LazyLayoutMeasureScope.toDp|[email protected](){}[0]
-    open fun (kotlin/Float).toSp(): androidx.compose.ui.unit/TextUnit // androidx.compose.foundation.lazy.layout/LazyLayoutMeasureScope.toSp|[email protected](){}[0]
-    open fun (kotlin/Int).toDp(): androidx.compose.ui.unit/Dp // androidx.compose.foundation.lazy.layout/LazyLayoutMeasureScope.toDp|[email protected](){}[0]
-    open fun (kotlin/Int).toSp(): androidx.compose.ui.unit/TextUnit // androidx.compose.foundation.lazy.layout/LazyLayoutMeasureScope.toSp|[email protected](){}[0]
-}
-sealed interface androidx.compose.foundation.lazy.layout/NestedPrefetchScope { // androidx.compose.foundation.lazy.layout/NestedPrefetchScope|null[0]
-    abstract fun schedulePrefetch(kotlin/Int) // androidx.compose.foundation.lazy.layout/NestedPrefetchScope.schedulePrefetch|schedulePrefetch(kotlin.Int){}[0]
-    abstract fun schedulePrefetch(kotlin/Int, androidx.compose.ui.unit/Constraints) // androidx.compose.foundation.lazy.layout/NestedPrefetchScope.schedulePrefetch|schedulePrefetch(kotlin.Int;androidx.compose.ui.unit.Constraints){}[0]
-}
-sealed interface androidx.compose.foundation.lazy.layout/PrefetchRequest { // androidx.compose.foundation.lazy.layout/PrefetchRequest|null[0]
-    abstract fun (androidx.compose.foundation.lazy.layout/PrefetchRequestScope).execute(): kotlin/Boolean // androidx.compose.foundation.lazy.layout/PrefetchRequest.execute|execute@androidx.compose.foundation.lazy.layout.PrefetchRequestScope(){}[0]
-}
 sealed interface androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridItemInfo { // androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridItemInfo|null[0]
     abstract val contentType // androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridItemInfo.contentType|{}contentType[0]
         abstract fun <get-contentType>(): kotlin/Any? // androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridItemInfo.contentType.<get-contentType>|<get-contentType>(){}[0]
@@ -1317,7 +994,6 @@
 }
 sealed interface androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridItemScope { // androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridItemScope|null[0]
     abstract fun (androidx.compose.ui/Modifier).animateItem(androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float>? =..., androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntOffset>? =..., androidx.compose.animation.core/FiniteAnimationSpec<kotlin/Float>? =...): androidx.compose.ui/Modifier // androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridItemScope.animateItem|[email protected](androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>?;androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>?;androidx.compose.animation.core.FiniteAnimationSpec<kotlin.Float>?){}[0]
-    open fun (androidx.compose.ui/Modifier).animateItemPlacement(androidx.compose.animation.core/FiniteAnimationSpec<androidx.compose.ui.unit/IntOffset> =...): androidx.compose.ui/Modifier // androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridItemScope.animateItemPlacement|[email protected](androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>){}[0]
 }
 sealed interface androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridLayoutInfo { // androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridLayoutInfo|null[0]
     abstract val afterContentPadding // androidx.compose.foundation.lazy.staggeredgrid/LazyStaggeredGridLayoutInfo.afterContentPadding|{}afterContentPadding[0]
@@ -1378,9 +1054,6 @@
         abstract fun <get-visiblePagesInfo>(): kotlin.collections/List<androidx.compose.foundation.pager/PageInfo> // androidx.compose.foundation.pager/PagerLayoutInfo.visiblePagesInfo.<get-visiblePagesInfo>|<get-visiblePagesInfo>(){}[0]
 }
 sealed interface androidx.compose.foundation.pager/PagerScope // androidx.compose.foundation.pager/PagerScope|null[0]
-sealed interface androidx.compose.foundation.relocation/BringIntoViewRequester { // androidx.compose.foundation.relocation/BringIntoViewRequester|null[0]
-    abstract suspend fun bringIntoView(androidx.compose.ui.geometry/Rect? =...) // androidx.compose.foundation.relocation/BringIntoViewRequester.bringIntoView|bringIntoView(androidx.compose.ui.geometry.Rect?){}[0]
-}
 sealed interface androidx.compose.foundation.text.input/TextFieldLineLimits { // androidx.compose.foundation.text.input/TextFieldLineLimits|null[0]
     final class MultiLine : androidx.compose.foundation.text.input/TextFieldLineLimits { // androidx.compose.foundation.text.input/TextFieldLineLimits.MultiLine|null[0]
         constructor <init>(kotlin/Int =..., kotlin/Int =...) // androidx.compose.foundation.text.input/TextFieldLineLimits.MultiLine.<init>|<init>(kotlin.Int;kotlin.Int){}[0]
@@ -1400,6 +1073,3 @@
         final fun toString(): kotlin/String // androidx.compose.foundation.text.input/TextFieldLineLimits.SingleLine.toString|toString(){}[0]
     }
 }
-sealed interface androidx.compose.foundation/CombinedClickableNode : androidx.compose.ui.node/PointerInputModifierNode { // androidx.compose.foundation/CombinedClickableNode|null[0]
-    abstract fun update(kotlin/Function0<kotlin/Unit>, kotlin/String?, kotlin/Function0<kotlin/Unit>?, kotlin/Function0<kotlin/Unit>?, androidx.compose.foundation.interaction/MutableInteractionSource?, androidx.compose.foundation/IndicationNodeFactory?, kotlin/Boolean, kotlin/String?, androidx.compose.ui.semantics/Role?) // androidx.compose.foundation/CombinedClickableNode.update|update(kotlin.Function0<kotlin.Unit>;kotlin.String?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.foundation.IndicationNodeFactory?;kotlin.Boolean;kotlin.String?;androidx.compose.ui.semantics.Role?){}[0]
-}
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/draganddrop/DragAndDropIntegrationTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/draganddrop/DragAndDropIntegrationTest.kt
new file mode 100644
index 0000000..398baff
--- /dev/null
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/draganddrop/DragAndDropIntegrationTest.kt
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.draganddrop
+
+import android.app.UiAutomation
+import android.content.ClipData
+import android.os.SystemClock
+import android.view.InputDevice
+import android.view.MotionEvent
+import android.view.View
+import androidx.compose.foundation.background
+import androidx.compose.foundation.content.assertClipData
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.size
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draganddrop.DragAndDropEvent
+import androidx.compose.ui.draganddrop.DragAndDropTarget
+import androidx.compose.ui.draganddrop.DragAndDropTransferData
+import androidx.compose.ui.draganddrop.toAndroidDragEvent
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalViewConfiguration
+import androidx.compose.ui.platform.ViewConfiguration
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.unit.center
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.toOffset
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import kotlin.test.assertNotNull
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class AndroidDragAndDropIntegrationTest {
+    @get:Rule val rule = createComposeRule()
+
+    @SdkSuppress(minSdkVersion = 24)
+    @Test
+    fun testPlainTextDragAndDrop() {
+        val sourceClipData = ClipData.newPlainText("testClipData", "Test Clip Data")
+        var droppedClipData: ClipData? = null
+
+        val dropTarget =
+            object : DragAndDropTarget {
+                override fun onDrop(event: DragAndDropEvent): Boolean {
+                    droppedClipData = ClipData(event.toAndroidDragEvent().clipData)
+                    return true
+                }
+            }
+        lateinit var viewConfiguration: ViewConfiguration
+
+        rule.setContent {
+            viewConfiguration = LocalViewConfiguration.current
+            Column {
+                Spacer(
+                    Modifier.size(100.dp)
+                        .background(Color.Blue)
+                        .testTag("TestDropSource")
+                        .dragAndDropSource { _ ->
+                            DragAndDropTransferData(
+                                clipData = sourceClipData,
+                                flags = View.DRAG_FLAG_GLOBAL,
+                            )
+                        }
+                )
+                Spacer(
+                    Modifier.size(100.dp)
+                        .background(Color.Red)
+                        .testTag("TestDropTarget")
+                        .dragAndDropTarget(
+                            shouldStartDragAndDrop = { true },
+                            target = dropTarget,
+                        )
+                )
+            }
+        }
+
+        // Compute the locations of the source and target in screen coordinates in preparation
+        // for raw motion event injection
+        val testDropSourceCenterScreenCoordinates: Offset =
+            rule.onNodeWithTag("TestDropSource").fetchSemanticsNode().let { node ->
+                node.positionOnScreen + node.size.center.toOffset()
+            }
+        val testDropTargetCenterScreenCoordinates: Offset =
+            rule.onNodeWithTag("TestDropTarget").fetchSemanticsNode().let { node ->
+                node.positionOnScreen + node.size.center.toOffset()
+            }
+
+        // Use raw motion event injection to move around the dragged object at the system level,
+        // which can leave the bounds of the app in the general case
+        val automation = InstrumentationRegistry.getInstrumentation().uiAutomation
+        val downTime = SystemClock.uptimeMillis()
+
+        // Press down on the source component
+        automation.injectMotionEvent(
+            downTime,
+            MotionEvent.ACTION_DOWN,
+            testDropSourceCenterScreenCoordinates,
+        )
+
+        rule.mainClock.advanceTimeBy(viewConfiguration.longPressTimeoutMillis + 100)
+
+        // Move to the drop component
+        automation.injectMotionEvent(
+            downTime,
+            MotionEvent.ACTION_MOVE,
+            testDropTargetCenterScreenCoordinates,
+        )
+
+        // Release to trigger the drop
+        automation.injectMotionEvent(
+            downTime,
+            MotionEvent.ACTION_UP,
+            testDropTargetCenterScreenCoordinates,
+        )
+
+        rule.waitForIdle()
+
+        assertClipData(assertNotNull(droppedClipData)).isEqualToClipData(sourceClipData, true)
+    }
+}
+
+private fun UiAutomation.injectMotionEvent(
+    downTime: Long,
+    action: Int,
+    screenOffset: Offset,
+    eventTime: Long = SystemClock.uptimeMillis(),
+) {
+    MotionEvent.obtain(
+            downTime,
+            eventTime,
+            action,
+            screenOffset.x,
+            screenOffset.y,
+            0,
+        )
+        .run {
+            source = InputDevice.SOURCE_TOUCHSCREEN
+            injectInputEvent(this, true)
+            recycle()
+        }
+}
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/draganddrop/DragAndDropSourceTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/draganddrop/DragAndDropSourceTest.kt
deleted file mode 100644
index 1b8cac3..0000000
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/draganddrop/DragAndDropSourceTest.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.draganddrop
-
-import android.os.Build
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.setValue
-import androidx.compose.testutils.assertPixels
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
-import androidx.compose.ui.draw.drawBehind
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Size
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.RectangleShape
-import androidx.compose.ui.layout.layout
-import androidx.compose.ui.platform.LocalDensity
-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.unit.Constraints
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.MediumTest
-import androidx.test.filters.SdkSuppress
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
-@MediumTest
-class DragAndDropSourceTest {
-    @get:Rule val rule = createComposeRule()
-
-    /** Regression test for b/379682458 */
-    @Test
-    fun dragAndDropSource_doesNotPreventChildInvalidations() {
-        var moveBox by mutableStateOf(false)
-        val tag = "source"
-        rule.setContent {
-            with(LocalDensity.current) {
-                Box(
-                    Modifier.size(200.toDp())
-                        .testTag(tag)
-                        .dragAndDropSource { _ -> null }
-                        .clip(RectangleShape)
-                        .layout { measurable, constraints ->
-                            val placeable =
-                                measurable.measure(
-                                    constraints.copy(maxWidth = Constraints.Infinity)
-                                )
-                            layout(constraints.maxWidth, constraints.maxHeight) {
-                                placeable.place(x = if (moveBox) -200 else 0, y = 0)
-                            }
-                        }
-                        .width(400.toDp())
-                        .drawBehind {
-                            val halfWidth = 200f
-                            val halfWidthSize = Size(halfWidth, size.height)
-                            drawRect(Color.Blue, size = halfWidthSize)
-                            drawRect(
-                                Color.Red,
-                                topLeft = Offset(halfWidth, 0f),
-                                size = halfWidthSize
-                            )
-                        }
-                )
-            }
-        }
-
-        rule.onNodeWithTag(tag).captureToImage().assertPixels { Color.Blue }
-
-        // Make the layout move the child so that the red box is now visible
-        rule.runOnIdle { moveBox = true }
-
-        rule.onNodeWithTag(tag).captureToImage().assertPixels { Color.Red }
-    }
-}
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/gestures/AwaitEachGestureTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/gestures/AwaitEachGestureTest.kt
index 48b90d1..2eb0a71 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/gestures/AwaitEachGestureTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/gestures/AwaitEachGestureTest.kt
@@ -19,14 +19,21 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.input.pointer.PointerEventType
+import androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode
 import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.node.DelegatingNode
+import androidx.compose.ui.node.ModifierNodeElement
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.click
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.onRoot
 import androidx.compose.ui.test.performTouchInput
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -116,4 +123,43 @@
         assertThat(events).hasSize(2)
         assertThat(events).containsExactly(PointerEventType.Press, PointerEventType.Press)
     }
+
+    @Test
+    fun undelegateSuspendingPointerInputModifierNodeDuringEventStream() {
+        var enabled by mutableStateOf(true)
+        rule.setContent { Box(Modifier.fillMaxSize().then(ParentElement(enabled))) }
+
+        rule.onRoot().performTouchInput { down(center) }
+
+        enabled = false
+        rule.waitForIdle()
+
+        rule.onRoot().performTouchInput { up() }
+    }
+
+    private data class ParentElement(private val enabled: Boolean) :
+        ModifierNodeElement<ParentNode>() {
+        override fun create(): ParentNode = ParentNode(enabled)
+
+        override fun update(node: ParentNode) {
+            node.update(enabled)
+        }
+    }
+
+    private class ParentNode(enabled: Boolean) : DelegatingNode() {
+        private var child: SuspendingPointerInputModifierNode? = if (enabled) childNode() else null
+
+        fun update(enabled: Boolean) {
+            if (!enabled) {
+                child?.onCancelPointerInput()
+                child?.let { undelegate(it) }
+                child = null
+            } else {
+                check(child == null)
+                child = childNode()
+            }
+        }
+
+        private fun childNode() = delegate(SuspendingPointerInputModifierNode {})
+    }
 }
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/draganddrop/AndroidDragAndDropSource.android.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/draganddrop/AndroidDragAndDropSource.android.kt
index 1182e61..4981f7c 100644
--- a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/draganddrop/AndroidDragAndDropSource.android.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/draganddrop/AndroidDragAndDropSource.android.kt
@@ -19,13 +19,15 @@
 
 package androidx.compose.foundation.draganddrop
 
+import android.graphics.Picture
 import androidx.compose.foundation.gestures.detectTapGestures
 import androidx.compose.runtime.Immutable
 import androidx.compose.ui.draw.CacheDrawScope
 import androidx.compose.ui.draw.DrawResult
 import androidx.compose.ui.graphics.drawscope.DrawScope
-import androidx.compose.ui.graphics.layer.GraphicsLayer
-import androidx.compose.ui.graphics.layer.drawLayer
+import androidx.compose.ui.graphics.drawscope.draw
+import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
+import androidx.compose.ui.graphics.nativeCanvas
 
 @Immutable
 internal actual object DragAndDropSourceDefaults {
@@ -35,24 +37,39 @@
 }
 
 internal actual class CacheDrawScopeDragShadowCallback {
-    private var graphicsLayer: GraphicsLayer? = null
+    private var cachedPicture: Picture? = null
 
     actual fun drawDragShadow(drawScope: DrawScope) =
         with(drawScope) {
-            when (val layer = graphicsLayer) {
+            when (val picture = cachedPicture) {
                 null ->
                     throw IllegalArgumentException(
                         "No cached drag shadow. Check if Modifier.cacheDragShadow(painter) was called."
                     )
-                else -> {
-                    if (!layer.isReleased) drawLayer(layer)
-                }
+                else -> drawIntoCanvas { canvas -> canvas.nativeCanvas.drawPicture(picture) }
             }
         }
 
     actual fun cachePicture(scope: CacheDrawScope): DrawResult =
         with(scope) {
-            graphicsLayer = scope.obtainGraphicsLayer().apply { record { drawContent() } }
-            onDrawWithContent { drawLayer(graphicsLayer!!) }
+            val picture = Picture()
+            cachedPicture = picture
+            val width = this.size.width.toInt()
+            val height = this.size.height.toInt()
+            onDrawWithContent {
+                val pictureCanvas =
+                    androidx.compose.ui.graphics.Canvas(picture.beginRecording(width, height))
+                draw(
+                    density = this,
+                    layoutDirection = this.layoutDirection,
+                    canvas = pictureCanvas,
+                    size = this.size
+                ) {
+                    [email protected]()
+                }
+                picture.endRecording()
+
+                drawIntoCanvas { canvas -> canvas.nativeCanvas.drawPicture(picture) }
+            }
         }
 }
diff --git a/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/ui/specification/SpecificationTopAppBar.kt b/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/ui/specification/SpecificationTopAppBar.kt
index 1f1d14b..644965f 100644
--- a/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/ui/specification/SpecificationTopAppBar.kt
+++ b/compose/integration-tests/material-catalog/src/main/java/androidx/compose/material/catalog/ui/specification/SpecificationTopAppBar.kt
@@ -51,7 +51,7 @@
         )
 
     val foregroundColors =
-        TopAppBarDefaults.centerAlignedTopAppBarColors(
+        TopAppBarDefaults.topAppBarColors(
             containerColor = Color.Transparent,
             scrolledContainerColor = Color.Transparent
         )
diff --git a/compose/material/material-navigation/build.gradle b/compose/material/material-navigation/build.gradle
index a80dfb7..7f8be4a 100644
--- a/compose/material/material-navigation/build.gradle
+++ b/compose/material/material-navigation/build.gradle
@@ -34,7 +34,6 @@
     androidTestImplementation(project(":compose:test-utils"))
     androidTestImplementation("androidx.navigation:navigation-testing:2.7.7")
     androidTestImplementation(project(":compose:ui:ui-test-junit4"))
-    androidTestImplementation(project(":compose:ui:ui-test-manifest"))
     androidTestImplementation(libs.testRunner)
     androidTestImplementation(libs.junit)
     androidTestImplementation(libs.truth)
diff --git a/compose/material/material/bcv/native/1.7.0.txt b/compose/material/material/bcv/native/1.7.0.txt
index 9bfc324..7b8eef8 100644
--- a/compose/material/material/bcv/native/1.7.0.txt
+++ b/compose/material/material/bcv/native/1.7.0.txt
@@ -18,11 +18,6 @@
     abstract fun boxColor(kotlin/Boolean, androidx.compose.ui.state/ToggleableState): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.material/CheckboxColors.boxColor|boxColor(kotlin.Boolean;androidx.compose.ui.state.ToggleableState){}[0]
     abstract fun checkmarkColor(androidx.compose.ui.state/ToggleableState): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.material/CheckboxColors.checkmarkColor|checkmarkColor(androidx.compose.ui.state.ToggleableState){}[0]
 }
-abstract interface androidx.compose.material/ChipColors { // androidx.compose.material/ChipColors|null[0]
-    abstract fun backgroundColor(kotlin/Boolean): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.material/ChipColors.backgroundColor|backgroundColor(kotlin.Boolean){}[0]
-    abstract fun contentColor(kotlin/Boolean): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.material/ChipColors.contentColor|contentColor(kotlin.Boolean){}[0]
-    abstract fun leadingIconContentColor(kotlin/Boolean): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.material/ChipColors.leadingIconContentColor|leadingIconContentColor(kotlin.Boolean){}[0]
-}
 abstract interface androidx.compose.material/ElevationOverlay { // androidx.compose.material/ElevationOverlay|null[0]
     abstract fun apply(androidx.compose.ui.graphics/Color, androidx.compose.ui.unit/Dp): androidx.compose.ui.graphics/Color // androidx.compose.material/ElevationOverlay.apply|apply(androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.Dp){}[0]
 }
@@ -32,11 +27,6 @@
 abstract interface androidx.compose.material/RadioButtonColors { // androidx.compose.material/RadioButtonColors|null[0]
     abstract fun radioColor(kotlin/Boolean, kotlin/Boolean): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.material/RadioButtonColors.radioColor|radioColor(kotlin.Boolean;kotlin.Boolean){}[0]
 }
-abstract interface androidx.compose.material/SelectableChipColors { // androidx.compose.material/SelectableChipColors|null[0]
-    abstract fun backgroundColor(kotlin/Boolean, kotlin/Boolean): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.material/SelectableChipColors.backgroundColor|backgroundColor(kotlin.Boolean;kotlin.Boolean){}[0]
-    abstract fun contentColor(kotlin/Boolean, kotlin/Boolean): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.material/SelectableChipColors.contentColor|contentColor(kotlin.Boolean;kotlin.Boolean){}[0]
-    abstract fun leadingIconColor(kotlin/Boolean, kotlin/Boolean): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.material/SelectableChipColors.leadingIconColor|leadingIconColor(kotlin.Boolean;kotlin.Boolean){}[0]
-}
 abstract interface androidx.compose.material/SliderColors { // androidx.compose.material/SliderColors|null[0]
     abstract fun thumbColor(kotlin/Boolean): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.material/SliderColors.thumbColor|thumbColor(kotlin.Boolean){}[0]
     abstract fun tickColor(kotlin/Boolean, kotlin/Boolean): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.material/SliderColors.tickColor|tickColor(kotlin.Boolean;kotlin.Boolean){}[0]
@@ -68,26 +58,6 @@
     open fun leadingIconColor(kotlin/Boolean, kotlin/Boolean, androidx.compose.foundation.interaction/InteractionSource): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.material/TextFieldColors.leadingIconColor|leadingIconColor(kotlin.Boolean;kotlin.Boolean;androidx.compose.foundation.interaction.InteractionSource){}[0]
     open fun trailingIconColor(kotlin/Boolean, kotlin/Boolean, androidx.compose.foundation.interaction/InteractionSource): androidx.compose.runtime/State<androidx.compose.ui.graphics/Color> // androidx.compose.material/TextFieldColors.trailingIconColor|trailingIconColor(kotlin.Boolean;kotlin.Boolean;androidx.compose.foundation.interaction.InteractionSource){}[0]
 }
-abstract interface androidx.compose.material/TextFieldColorsWithIcons : androidx.compose.material/TextFieldColors // androidx.compose.material/TextFieldColorsWithIcons|null[0]
-abstract interface androidx.compose.material/ThresholdConfig { // androidx.compose.material/ThresholdConfig|null[0]
-    abstract fun (androidx.compose.ui.unit/Density).computeThreshold(kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.material/ThresholdConfig.computeThreshold|[email protected](kotlin.Float;kotlin.Float){}[0]
-}
-final class <#A: kotlin/Any?> androidx.compose.material/SwipeProgress { // androidx.compose.material/SwipeProgress|null[0]
-    constructor <init>(#A, #A, kotlin/Float) // androidx.compose.material/SwipeProgress.<init>|<init>(1:0;1:0;kotlin.Float){}[0]
-    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material/SwipeProgress.equals|equals(kotlin.Any?){}[0]
-    final fun hashCode(): kotlin/Int // androidx.compose.material/SwipeProgress.hashCode|hashCode(){}[0]
-    final fun toString(): kotlin/String // androidx.compose.material/SwipeProgress.toString|toString(){}[0]
-    final val fraction // androidx.compose.material/SwipeProgress.fraction|{}fraction[0]
-        final fun <get-fraction>(): kotlin/Float // androidx.compose.material/SwipeProgress.fraction.<get-fraction>|<get-fraction>(){}[0]
-    final val from // androidx.compose.material/SwipeProgress.from|{}from[0]
-        final fun <get-from>(): #A // androidx.compose.material/SwipeProgress.from.<get-from>|<get-from>(){}[0]
-    final val to // androidx.compose.material/SwipeProgress.to|{}to[0]
-        final fun <get-to>(): #A // androidx.compose.material/SwipeProgress.to.<get-to>|<get-to>(){}[0]
-}
-final class androidx.compose.material.pullrefresh/PullRefreshState { // androidx.compose.material.pullrefresh/PullRefreshState|null[0]
-    final val progress // androidx.compose.material.pullrefresh/PullRefreshState.progress|{}progress[0]
-        final fun <get-progress>(): kotlin/Float // androidx.compose.material.pullrefresh/PullRefreshState.progress.<get-progress>|<get-progress>(){}[0]
-}
 final class androidx.compose.material/BackdropScaffoldState { // androidx.compose.material/BackdropScaffoldState|null[0]
     constructor <init>(androidx.compose.material/BackdropValue, androidx.compose.animation.core/AnimationSpec<kotlin/Float> =..., kotlin/Function1<androidx.compose.material/BackdropValue, kotlin/Boolean> =..., androidx.compose.material/SnackbarHostState =...) // androidx.compose.material/BackdropScaffoldState.<init>|<init>(androidx.compose.material.BackdropValue;androidx.compose.animation.core.AnimationSpec<kotlin.Float>;kotlin.Function1<androidx.compose.material.BackdropValue,kotlin.Boolean>;androidx.compose.material.SnackbarHostState){}[0]
     final fun progress(androidx.compose.material/BackdropValue, androidx.compose.material/BackdropValue): kotlin/Float // androidx.compose.material/BackdropScaffoldState.progress|progress(androidx.compose.material.BackdropValue;androidx.compose.material.BackdropValue){}[0]
@@ -129,8 +99,6 @@
         final fun <get-isOpen>(): kotlin/Boolean // androidx.compose.material/BottomDrawerState.isOpen.<get-isOpen>|<get-isOpen>(){}[0]
     final val offset // androidx.compose.material/BottomDrawerState.offset|{}offset[0]
         final fun <get-offset>(): kotlin/Float // androidx.compose.material/BottomDrawerState.offset.<get-offset>|<get-offset>(){}[0]
-    final val progress // androidx.compose.material/BottomDrawerState.progress|{}progress[0]
-        final fun <get-progress>(): kotlin/Float // androidx.compose.material/BottomDrawerState.progress.<get-progress>|<get-progress>(){}[0]
     final val targetValue // androidx.compose.material/BottomDrawerState.targetValue|{}targetValue[0]
         final fun <get-targetValue>(): androidx.compose.material/BottomDrawerValue // androidx.compose.material/BottomDrawerState.targetValue.<get-targetValue>|<get-targetValue>(){}[0]
 }
@@ -156,8 +124,6 @@
         final fun <get-isCollapsed>(): kotlin/Boolean // androidx.compose.material/BottomSheetState.isCollapsed.<get-isCollapsed>|<get-isCollapsed>(){}[0]
     final val isExpanded // androidx.compose.material/BottomSheetState.isExpanded|{}isExpanded[0]
         final fun <get-isExpanded>(): kotlin/Boolean // androidx.compose.material/BottomSheetState.isExpanded.<get-isExpanded>|<get-isExpanded>(){}[0]
-    final val progress // androidx.compose.material/BottomSheetState.progress|{}progress[0]
-        final fun <get-progress>(): kotlin/Float // androidx.compose.material/BottomSheetState.progress.<get-progress>|<get-progress>(){}[0]
     final val targetValue // androidx.compose.material/BottomSheetState.targetValue|{}targetValue[0]
         final fun <get-targetValue>(): androidx.compose.material/BottomSheetValue // androidx.compose.material/BottomSheetState.targetValue.<get-targetValue>|<get-targetValue>(){}[0]
 }
@@ -192,23 +158,11 @@
     final var surface // androidx.compose.material/Colors.surface|{}surface[0]
         final fun <get-surface>(): androidx.compose.ui.graphics/Color // androidx.compose.material/Colors.surface.<get-surface>|<get-surface>(){}[0]
 }
-final class androidx.compose.material/DismissState : androidx.compose.material/SwipeableState<androidx.compose.material/DismissValue> { // androidx.compose.material/DismissState|null[0]
-    constructor <init>(androidx.compose.material/DismissValue, kotlin/Function1<androidx.compose.material/DismissValue, kotlin/Boolean> =...) // androidx.compose.material/DismissState.<init>|<init>(androidx.compose.material.DismissValue;kotlin.Function1<androidx.compose.material.DismissValue,kotlin.Boolean>){}[0]
-    final fun isDismissed(androidx.compose.material/DismissDirection): kotlin/Boolean // androidx.compose.material/DismissState.isDismissed|isDismissed(androidx.compose.material.DismissDirection){}[0]
-    final object Companion { // androidx.compose.material/DismissState.Companion|null[0]
-        final fun Saver(kotlin/Function1<androidx.compose.material/DismissValue, kotlin/Boolean>): androidx.compose.runtime.saveable/Saver<androidx.compose.material/DismissState, androidx.compose.material/DismissValue> // androidx.compose.material/DismissState.Companion.Saver|Saver(kotlin.Function1<androidx.compose.material.DismissValue,kotlin.Boolean>){}[0]
-    }
-    final suspend fun dismiss(androidx.compose.material/DismissDirection) // androidx.compose.material/DismissState.dismiss|dismiss(androidx.compose.material.DismissDirection){}[0]
-    final suspend fun reset() // androidx.compose.material/DismissState.reset|reset(){}[0]
-    final val dismissDirection // androidx.compose.material/DismissState.dismissDirection|{}dismissDirection[0]
-        final fun <get-dismissDirection>(): androidx.compose.material/DismissDirection? // androidx.compose.material/DismissState.dismissDirection.<get-dismissDirection>|<get-dismissDirection>(){}[0]
-}
 final class androidx.compose.material/DrawerState { // androidx.compose.material/DrawerState|null[0]
     constructor <init>(androidx.compose.material/DrawerValue, kotlin/Function1<androidx.compose.material/DrawerValue, kotlin/Boolean> =...) // androidx.compose.material/DrawerState.<init>|<init>(androidx.compose.material.DrawerValue;kotlin.Function1<androidx.compose.material.DrawerValue,kotlin.Boolean>){}[0]
     final object Companion { // androidx.compose.material/DrawerState.Companion|null[0]
         final fun Saver(kotlin/Function1<androidx.compose.material/DrawerValue, kotlin/Boolean>): androidx.compose.runtime.saveable/Saver<androidx.compose.material/DrawerState, androidx.compose.material/DrawerValue> // androidx.compose.material/DrawerState.Companion.Saver|Saver(kotlin.Function1<androidx.compose.material.DrawerValue,kotlin.Boolean>){}[0]
     }
-    final suspend fun animateTo(androidx.compose.material/DrawerValue, androidx.compose.animation.core/AnimationSpec<kotlin/Float>) // androidx.compose.material/DrawerState.animateTo|animateTo(androidx.compose.material.DrawerValue;androidx.compose.animation.core.AnimationSpec<kotlin.Float>){}[0]
     final suspend fun close() // androidx.compose.material/DrawerState.close|close(){}[0]
     final suspend fun open() // androidx.compose.material/DrawerState.open|open(){}[0]
     final suspend fun snapTo(androidx.compose.material/DrawerValue) // androidx.compose.material/DrawerState.snapTo|snapTo(androidx.compose.material.DrawerValue){}[0]
@@ -220,26 +174,6 @@
         final fun <get-isClosed>(): kotlin/Boolean // androidx.compose.material/DrawerState.isClosed.<get-isClosed>|<get-isClosed>(){}[0]
     final val isOpen // androidx.compose.material/DrawerState.isOpen|{}isOpen[0]
         final fun <get-isOpen>(): kotlin/Boolean // androidx.compose.material/DrawerState.isOpen.<get-isOpen>|<get-isOpen>(){}[0]
-    final val offset // androidx.compose.material/DrawerState.offset|{}offset[0]
-        final fun <get-offset>(): kotlin/Float // androidx.compose.material/DrawerState.offset.<get-offset>|<get-offset>(){}[0]
-    final val targetValue // androidx.compose.material/DrawerState.targetValue|{}targetValue[0]
-        final fun <get-targetValue>(): androidx.compose.material/DrawerValue // androidx.compose.material/DrawerState.targetValue.<get-targetValue>|<get-targetValue>(){}[0]
-}
-final class androidx.compose.material/FixedThreshold : androidx.compose.material/ThresholdConfig { // androidx.compose.material/FixedThreshold|null[0]
-    constructor <init>(androidx.compose.ui.unit/Dp) // androidx.compose.material/FixedThreshold.<init>|<init>(androidx.compose.ui.unit.Dp){}[0]
-    final fun (androidx.compose.ui.unit/Density).computeThreshold(kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.material/FixedThreshold.computeThreshold|[email protected](kotlin.Float;kotlin.Float){}[0]
-    final fun copy(androidx.compose.ui.unit/Dp =...): androidx.compose.material/FixedThreshold // androidx.compose.material/FixedThreshold.copy|copy(androidx.compose.ui.unit.Dp){}[0]
-    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material/FixedThreshold.equals|equals(kotlin.Any?){}[0]
-    final fun hashCode(): kotlin/Int // androidx.compose.material/FixedThreshold.hashCode|hashCode(){}[0]
-    final fun toString(): kotlin/String // androidx.compose.material/FixedThreshold.toString|toString(){}[0]
-}
-final class androidx.compose.material/FractionalThreshold : androidx.compose.material/ThresholdConfig { // androidx.compose.material/FractionalThreshold|null[0]
-    constructor <init>(kotlin/Float) // androidx.compose.material/FractionalThreshold.<init>|<init>(kotlin.Float){}[0]
-    final fun (androidx.compose.ui.unit/Density).computeThreshold(kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.material/FractionalThreshold.computeThreshold|[email protected](kotlin.Float;kotlin.Float){}[0]
-    final fun copy(kotlin/Float =...): androidx.compose.material/FractionalThreshold // androidx.compose.material/FractionalThreshold.copy|copy(kotlin.Float){}[0]
-    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material/FractionalThreshold.equals|equals(kotlin.Any?){}[0]
-    final fun hashCode(): kotlin/Int // androidx.compose.material/FractionalThreshold.hashCode|hashCode(){}[0]
-    final fun toString(): kotlin/String // androidx.compose.material/FractionalThreshold.toString|toString(){}[0]
 }
 final class androidx.compose.material/ModalBottomSheetState { // androidx.compose.material/ModalBottomSheetState|null[0]
     constructor <init>(androidx.compose.material/ModalBottomSheetValue, androidx.compose.ui.unit/Density, kotlin/Function1<androidx.compose.material/ModalBottomSheetValue, kotlin/Boolean> =..., androidx.compose.animation.core/AnimationSpec<kotlin/Float> =..., kotlin/Boolean =...) // androidx.compose.material/ModalBottomSheetState.<init>|<init>(androidx.compose.material.ModalBottomSheetValue;androidx.compose.ui.unit.Density;kotlin.Function1<androidx.compose.material.ModalBottomSheetValue,kotlin.Boolean>;androidx.compose.animation.core.AnimationSpec<kotlin.Float>;kotlin.Boolean){}[0]
@@ -253,8 +187,6 @@
         final fun <get-currentValue>(): androidx.compose.material/ModalBottomSheetValue // androidx.compose.material/ModalBottomSheetState.currentValue.<get-currentValue>|<get-currentValue>(){}[0]
     final val isVisible // androidx.compose.material/ModalBottomSheetState.isVisible|{}isVisible[0]
         final fun <get-isVisible>(): kotlin/Boolean // androidx.compose.material/ModalBottomSheetState.isVisible.<get-isVisible>|<get-isVisible>(){}[0]
-    final val progress // androidx.compose.material/ModalBottomSheetState.progress|{}progress[0]
-        final fun <get-progress>(): kotlin/Float // androidx.compose.material/ModalBottomSheetState.progress.<get-progress>|<get-progress>(){}[0]
     final val targetValue // androidx.compose.material/ModalBottomSheetState.targetValue|{}targetValue[0]
         final fun <get-targetValue>(): androidx.compose.material/ModalBottomSheetValue // androidx.compose.material/ModalBottomSheetState.targetValue.<get-targetValue>|<get-targetValue>(){}[0]
 }
@@ -271,16 +203,6 @@
     final val factorAtMin // androidx.compose.material/ResistanceConfig.factorAtMin|{}factorAtMin[0]
         final fun <get-factorAtMin>(): kotlin/Float // androidx.compose.material/ResistanceConfig.factorAtMin.<get-factorAtMin>|<get-factorAtMin>(){}[0]
 }
-final class androidx.compose.material/RippleConfiguration { // androidx.compose.material/RippleConfiguration|null[0]
-    constructor <init>(androidx.compose.ui.graphics/Color =..., androidx.compose.material.ripple/RippleAlpha? =...) // androidx.compose.material/RippleConfiguration.<init>|<init>(androidx.compose.ui.graphics.Color;androidx.compose.material.ripple.RippleAlpha?){}[0]
-    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.material/RippleConfiguration.equals|equals(kotlin.Any?){}[0]
-    final fun hashCode(): kotlin/Int // androidx.compose.material/RippleConfiguration.hashCode|hashCode(){}[0]
-    final fun toString(): kotlin/String // androidx.compose.material/RippleConfiguration.toString|toString(){}[0]
-    final val color // androidx.compose.material/RippleConfiguration.color|{}color[0]
-        final fun <get-color>(): androidx.compose.ui.graphics/Color // androidx.compose.material/RippleConfiguration.color.<get-color>|<get-color>(){}[0]
-    final val rippleAlpha // androidx.compose.material/RippleConfiguration.rippleAlpha|{}rippleAlpha[0]
-        final fun <get-rippleAlpha>(): androidx.compose.material.ripple/RippleAlpha? // androidx.compose.material/RippleConfiguration.rippleAlpha.<get-rippleAlpha>|<get-rippleAlpha>(){}[0]
-}
 final class androidx.compose.material/ScaffoldState { // androidx.compose.material/ScaffoldState|null[0]
     constructor <init>(androidx.compose.material/DrawerState, androidx.compose.material/SnackbarHostState) // androidx.compose.material/ScaffoldState.<init>|<init>(androidx.compose.material.DrawerState;androidx.compose.material.SnackbarHostState){}[0]
     final val drawerState // androidx.compose.material/ScaffoldState.drawerState|{}drawerState[0]
@@ -411,14 +333,7 @@
 }
 final fun (androidx.compose.foundation.layout/RowScope).androidx.compose.material/BottomNavigationItem(kotlin/Boolean, kotlin/Function0<kotlin/Unit>, kotlin/Function0<kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =...) // androidx.compose.material/BottomNavigationItem|[email protected](kotlin.Boolean;kotlin.Function0<kotlin.Unit>;kotlin.Function0<kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;kotlin.Function0<kotlin.Unit>?;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
 final fun (androidx.compose.material/Colors).androidx.compose.material/contentColorFor(androidx.compose.ui.graphics/Color): androidx.compose.ui.graphics/Color // androidx.compose.material/contentColorFor|[email protected](androidx.compose.ui.graphics.Color){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.material.pullrefresh/pullRefresh(androidx.compose.material.pullrefresh/PullRefreshState, kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.material.pullrefresh/pullRefresh|[email protected](androidx.compose.material.pullrefresh.PullRefreshState;kotlin.Boolean){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.material.pullrefresh/pullRefresh(kotlin/Function1<kotlin/Float, kotlin/Float>, kotlin.coroutines/SuspendFunction1<kotlin/Float, kotlin/Float>, kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.material.pullrefresh/pullRefresh|[email protected](kotlin.Function1<kotlin.Float,kotlin.Float>;kotlin.coroutines.SuspendFunction1<kotlin.Float,kotlin.Float>;kotlin.Boolean){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.material.pullrefresh/pullRefreshIndicatorTransform(androidx.compose.material.pullrefresh/PullRefreshState, kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.material.pullrefresh/pullRefreshIndicatorTransform|[email protected](androidx.compose.material.pullrefresh.PullRefreshState;kotlin.Boolean){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.material/minimumInteractiveComponentSize(): androidx.compose.ui/Modifier // androidx.compose.material/minimumInteractiveComponentSize|[email protected](){}[0]
-final fun <#A: kotlin/Any> androidx.compose.material/rememberSwipeableState(#A, androidx.compose.animation.core/AnimationSpec<kotlin/Float> =..., kotlin/Function1<#A, kotlin/Boolean> =...): androidx.compose.material/SwipeableState<#A> // androidx.compose.material/rememberSwipeableState|rememberSwipeableState(0:0;androidx.compose.animation.core.AnimationSpec<kotlin.Float>;kotlin.Function1<0:0,kotlin.Boolean>){0§<kotlin.Any>}[0]
-final fun <#A: kotlin/Any?> (androidx.compose.ui/Modifier).androidx.compose.material/swipeable(androidx.compose.material/SwipeableState<#A>, kotlin.collections/Map<kotlin/Float, #A>, androidx.compose.foundation.gestures/Orientation, kotlin/Boolean =..., kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., kotlin/Function2<#A, #A, androidx.compose.material/ThresholdConfig> =..., androidx.compose.material/ResistanceConfig? =..., androidx.compose.ui.unit/Dp =...): androidx.compose.ui/Modifier // androidx.compose.material/swipeable|[email protected](androidx.compose.material.SwipeableState<0:0>;kotlin.collections.Map<kotlin.Float,0:0>;androidx.compose.foundation.gestures.Orientation;kotlin.Boolean;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;kotlin.Function2<0:0,0:0,androidx.compose.material.ThresholdConfig>;androidx.compose.material.ResistanceConfig?;androidx.compose.ui.unit.Dp){0§<kotlin.Any?>}[0]
-final fun androidx.compose.material.pullrefresh/PullRefreshIndicator(kotlin/Boolean, androidx.compose.material.pullrefresh/PullRefreshState, androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., kotlin/Boolean =...) // androidx.compose.material.pullrefresh/PullRefreshIndicator|PullRefreshIndicator(kotlin.Boolean;androidx.compose.material.pullrefresh.PullRefreshState;androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;kotlin.Boolean){}[0]
-final fun androidx.compose.material.pullrefresh/rememberPullRefreshState(kotlin/Boolean, kotlin/Function0<kotlin/Unit>, androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =...): androidx.compose.material.pullrefresh/PullRefreshState // androidx.compose.material.pullrefresh/rememberPullRefreshState|rememberPullRefreshState(kotlin.Boolean;kotlin.Function0<kotlin.Unit>;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp){}[0]
 final fun androidx.compose.material/BackdropScaffold(kotlin/Function0<kotlin/Unit>, kotlin/Function0<kotlin/Unit>, kotlin/Function0<kotlin/Unit>, androidx.compose.ui/Modifier =..., androidx.compose.material/BackdropScaffoldState =..., kotlin/Function1<androidx.compose.material/SnackbarHostState, kotlin/Unit> =..., kotlin/Boolean =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =..., kotlin/Boolean =..., kotlin/Boolean =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =...) // androidx.compose.material/BackdropScaffold|BackdropScaffold(kotlin.Function0<kotlin.Unit>;kotlin.Function0<kotlin.Unit>;kotlin.Function0<kotlin.Unit>;androidx.compose.ui.Modifier;androidx.compose.material.BackdropScaffoldState;kotlin.Function1<androidx.compose.material.SnackbarHostState,kotlin.Unit>;kotlin.Boolean;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;kotlin.Boolean;kotlin.Boolean;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Shape;androidx.compose.ui.unit.Dp;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
 final fun androidx.compose.material/BackdropScaffoldState(androidx.compose.material/BackdropValue, androidx.compose.ui.unit/Density, androidx.compose.animation.core/AnimationSpec<kotlin/Float> =..., kotlin/Function1<androidx.compose.material/BackdropValue, kotlin/Boolean> =..., androidx.compose.material/SnackbarHostState =...): androidx.compose.material/BackdropScaffoldState // androidx.compose.material/BackdropScaffoldState|BackdropScaffoldState(androidx.compose.material.BackdropValue;androidx.compose.ui.unit.Density;androidx.compose.animation.core.AnimationSpec<kotlin.Float>;kotlin.Function1<androidx.compose.material.BackdropValue,kotlin.Boolean>;androidx.compose.material.SnackbarHostState){}[0]
 final fun androidx.compose.material/Badge(androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., kotlin/Function1<androidx.compose.foundation.layout/RowScope, kotlin/Unit>? =...) // androidx.compose.material/Badge|Badge(androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;kotlin.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit>?){}[0]
@@ -431,16 +346,13 @@
 final fun androidx.compose.material/BottomSheetScaffold(kotlin/Function1<androidx.compose.foundation.layout/ColumnScope, kotlin/Unit>, androidx.compose.ui/Modifier =..., androidx.compose.material/BottomSheetScaffoldState =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function1<androidx.compose.material/SnackbarHostState, kotlin/Unit> =..., kotlin/Function0<kotlin/Unit>? =..., androidx.compose.material/FabPosition =..., kotlin/Boolean =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., kotlin/Function1<androidx.compose.foundation.layout/PaddingValues, kotlin/Unit>) // androidx.compose.material/BottomSheetScaffold|BottomSheetScaffold(kotlin.Function1<androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>;androidx.compose.ui.Modifier;androidx.compose.material.BottomSheetScaffoldState;kotlin.Function0<kotlin.Unit>?;kotlin.Function1<androidx.compose.material.SnackbarHostState,kotlin.Unit>;kotlin.Function0<kotlin.Unit>?;androidx.compose.material.FabPosition;kotlin.Boolean;androidx.compose.ui.graphics.Shape;androidx.compose.ui.unit.Dp;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.Dp;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;kotlin.Function1<androidx.compose.foundation.layout.PaddingValues,kotlin.Unit>){}[0]
 final fun androidx.compose.material/Button(kotlin/Function0<kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.material/ButtonElevation? =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.foundation/BorderStroke? =..., androidx.compose.material/ButtonColors =..., androidx.compose.foundation.layout/PaddingValues =..., kotlin/Function1<androidx.compose.foundation.layout/RowScope, kotlin/Unit>) // androidx.compose.material/Button|Button(kotlin.Function0<kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.material.ButtonElevation?;androidx.compose.ui.graphics.Shape;androidx.compose.foundation.BorderStroke?;androidx.compose.material.ButtonColors;androidx.compose.foundation.layout.PaddingValues;kotlin.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit>){}[0]
 final fun androidx.compose.material/Card(androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.foundation/BorderStroke? =..., androidx.compose.ui.unit/Dp =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.material/Card|Card(androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Shape;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.foundation.BorderStroke?;androidx.compose.ui.unit.Dp;kotlin.Function0<kotlin.Unit>){}[0]
-final fun androidx.compose.material/Card(kotlin/Function0<kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.foundation/BorderStroke? =..., androidx.compose.ui.unit/Dp =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.material/Card|Card(kotlin.Function0<kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;androidx.compose.ui.graphics.Shape;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.foundation.BorderStroke?;androidx.compose.ui.unit.Dp;androidx.compose.foundation.interaction.MutableInteractionSource?;kotlin.Function0<kotlin.Unit>){}[0]
 final fun androidx.compose.material/Checkbox(kotlin/Boolean, kotlin/Function1<kotlin/Boolean, kotlin/Unit>?, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.material/CheckboxColors =...) // androidx.compose.material/Checkbox|Checkbox(kotlin.Boolean;kotlin.Function1<kotlin.Boolean,kotlin.Unit>?;androidx.compose.ui.Modifier;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.material.CheckboxColors){}[0]
-final fun androidx.compose.material/Chip(kotlin/Function0<kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.foundation/BorderStroke? =..., androidx.compose.material/ChipColors =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function1<androidx.compose.foundation.layout/RowScope, kotlin/Unit>) // androidx.compose.material/Chip|Chip(kotlin.Function0<kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.ui.graphics.Shape;androidx.compose.foundation.BorderStroke?;androidx.compose.material.ChipColors;kotlin.Function0<kotlin.Unit>?;kotlin.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit>){}[0]
 final fun androidx.compose.material/CircularProgressIndicator(androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.unit/Dp =...) // androidx.compose.material/CircularProgressIndicator|CircularProgressIndicator(androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.Dp){}[0]
 final fun androidx.compose.material/CircularProgressIndicator(androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/StrokeCap =...) // androidx.compose.material/CircularProgressIndicator|CircularProgressIndicator(androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.Dp;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.StrokeCap){}[0]
 final fun androidx.compose.material/CircularProgressIndicator(kotlin/Float, androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.unit/Dp =...) // androidx.compose.material/CircularProgressIndicator|CircularProgressIndicator(kotlin.Float;androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.Dp){}[0]
 final fun androidx.compose.material/CircularProgressIndicator(kotlin/Float, androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/StrokeCap =...) // androidx.compose.material/CircularProgressIndicator|CircularProgressIndicator(kotlin.Float;androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.Dp;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.StrokeCap){}[0]
 final fun androidx.compose.material/Divider(androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =...) // androidx.compose.material/Divider|Divider(androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp){}[0]
 final fun androidx.compose.material/ExtendedFloatingActionButton(kotlin/Function0<kotlin/Unit>, kotlin/Function0<kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Function0<kotlin/Unit>? =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.material/FloatingActionButtonElevation =...) // androidx.compose.material/ExtendedFloatingActionButton|ExtendedFloatingActionButton(kotlin.Function0<kotlin.Unit>;kotlin.Function0<kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Function0<kotlin.Unit>?;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.ui.graphics.Shape;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.material.FloatingActionButtonElevation){}[0]
-final fun androidx.compose.material/FilterChip(kotlin/Boolean, kotlin/Function0<kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.foundation/BorderStroke? =..., androidx.compose.material/SelectableChipColors =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function1<androidx.compose.foundation.layout/RowScope, kotlin/Unit>) // androidx.compose.material/FilterChip|FilterChip(kotlin.Boolean;kotlin.Function0<kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.ui.graphics.Shape;androidx.compose.foundation.BorderStroke?;androidx.compose.material.SelectableChipColors;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit>){}[0]
 final fun androidx.compose.material/FloatingActionButton(kotlin/Function0<kotlin/Unit>, androidx.compose.ui/Modifier =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.material/FloatingActionButtonElevation =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.material/FloatingActionButton|FloatingActionButton(kotlin.Function0<kotlin.Unit>;androidx.compose.ui.Modifier;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.ui.graphics.Shape;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.material.FloatingActionButtonElevation;kotlin.Function0<kotlin.Unit>){}[0]
 final fun androidx.compose.material/Icon(androidx.compose.ui.graphics.painter/Painter, kotlin/String?, androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Color =...) // androidx.compose.material/Icon|Icon(androidx.compose.ui.graphics.painter.Painter;kotlin.String?;androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Color){}[0]
 final fun androidx.compose.material/Icon(androidx.compose.ui.graphics.vector/ImageVector, kotlin/String?, androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Color =...) // androidx.compose.material/Icon|Icon(androidx.compose.ui.graphics.vector.ImageVector;kotlin.String?;androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Color){}[0]
@@ -452,7 +364,6 @@
 final fun androidx.compose.material/LinearProgressIndicator(androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/StrokeCap =...) // androidx.compose.material/LinearProgressIndicator|LinearProgressIndicator(androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.StrokeCap){}[0]
 final fun androidx.compose.material/LinearProgressIndicator(kotlin/Float, androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =...) // androidx.compose.material/LinearProgressIndicator|LinearProgressIndicator(kotlin.Float;androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
 final fun androidx.compose.material/LinearProgressIndicator(kotlin/Float, androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/StrokeCap =...) // androidx.compose.material/LinearProgressIndicator|LinearProgressIndicator(kotlin.Float;androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.StrokeCap){}[0]
-final fun androidx.compose.material/ListItem(androidx.compose.ui/Modifier =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Boolean =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.material/ListItem|ListItem(androidx.compose.ui.Modifier;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Boolean;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>){}[0]
 final fun androidx.compose.material/MaterialTheme(androidx.compose.material/Colors =..., androidx.compose.material/Typography =..., androidx.compose.material/Shapes =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.material/MaterialTheme|MaterialTheme(androidx.compose.material.Colors;androidx.compose.material.Typography;androidx.compose.material.Shapes;kotlin.Function0<kotlin.Unit>){}[0]
 final fun androidx.compose.material/ModalBottomSheetLayout(kotlin/Function1<androidx.compose.foundation.layout/ColumnScope, kotlin/Unit>, androidx.compose.ui/Modifier =..., androidx.compose.material/ModalBottomSheetState =..., kotlin/Boolean =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.material/ModalBottomSheetLayout|ModalBottomSheetLayout(kotlin.Function1<androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>;androidx.compose.ui.Modifier;androidx.compose.material.ModalBottomSheetState;kotlin.Boolean;androidx.compose.ui.graphics.Shape;androidx.compose.ui.unit.Dp;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;kotlin.Function0<kotlin.Unit>){}[0]
 final fun androidx.compose.material/ModalDrawer(kotlin/Function1<androidx.compose.foundation.layout/ColumnScope, kotlin/Unit>, androidx.compose.ui/Modifier =..., androidx.compose.material/DrawerState =..., kotlin/Boolean =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.material/ModalDrawer|ModalDrawer(kotlin.Function1<androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>;androidx.compose.ui.Modifier;androidx.compose.material.DrawerState;kotlin.Boolean;androidx.compose.ui.graphics.Shape;androidx.compose.ui.unit.Dp;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;kotlin.Function0<kotlin.Unit>){}[0]
@@ -466,7 +377,6 @@
 final fun androidx.compose.material/OutlinedTextField(kotlin/String, kotlin/Function1<kotlin/String, kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., kotlin/Boolean =..., androidx.compose.ui.text/TextStyle =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Boolean =..., androidx.compose.ui.text.input/VisualTransformation =..., androidx.compose.foundation.text/KeyboardOptions =..., androidx.compose.foundation.text/KeyboardActions =..., kotlin/Boolean =..., kotlin/Int =..., kotlin/Int =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.material/TextFieldColors =...) // androidx.compose.material/OutlinedTextField|OutlinedTextField(kotlin.String;kotlin.Function1<kotlin.String,kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;kotlin.Boolean;androidx.compose.ui.text.TextStyle;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Boolean;androidx.compose.ui.text.input.VisualTransformation;androidx.compose.foundation.text.KeyboardOptions;androidx.compose.foundation.text.KeyboardActions;kotlin.Boolean;kotlin.Int;kotlin.Int;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.ui.graphics.Shape;androidx.compose.material.TextFieldColors){}[0]
 final fun androidx.compose.material/ProvideTextStyle(androidx.compose.ui.text/TextStyle, kotlin/Function0<kotlin/Unit>) // androidx.compose.material/ProvideTextStyle|ProvideTextStyle(androidx.compose.ui.text.TextStyle;kotlin.Function0<kotlin.Unit>){}[0]
 final fun androidx.compose.material/RadioButton(kotlin/Boolean, kotlin/Function0<kotlin/Unit>?, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.material/RadioButtonColors =...) // androidx.compose.material/RadioButton|RadioButton(kotlin.Boolean;kotlin.Function0<kotlin.Unit>?;androidx.compose.ui.Modifier;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.material.RadioButtonColors){}[0]
-final fun androidx.compose.material/RangeSlider(kotlin.ranges/ClosedFloatingPointRange<kotlin/Float>, kotlin/Function1<kotlin.ranges/ClosedFloatingPointRange<kotlin/Float>, kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., kotlin.ranges/ClosedFloatingPointRange<kotlin/Float> =..., kotlin/Int =..., kotlin/Function0<kotlin/Unit>? =..., androidx.compose.material/SliderColors =...) // androidx.compose.material/RangeSlider|RangeSlider(kotlin.ranges.ClosedFloatingPointRange<kotlin.Float>;kotlin.Function1<kotlin.ranges.ClosedFloatingPointRange<kotlin.Float>,kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;kotlin.ranges.ClosedFloatingPointRange<kotlin.Float>;kotlin.Int;kotlin.Function0<kotlin.Unit>?;androidx.compose.material.SliderColors){}[0]
 final fun androidx.compose.material/Scaffold(androidx.compose.foundation.layout/WindowInsets, androidx.compose.ui/Modifier =..., androidx.compose.material/ScaffoldState =..., kotlin/Function0<kotlin/Unit> =..., kotlin/Function0<kotlin/Unit> =..., kotlin/Function1<androidx.compose.material/SnackbarHostState, kotlin/Unit> =..., kotlin/Function0<kotlin/Unit> =..., androidx.compose.material/FabPosition =..., kotlin/Boolean =..., kotlin/Function1<androidx.compose.foundation.layout/ColumnScope, kotlin/Unit>? =..., kotlin/Boolean =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., kotlin/Function1<androidx.compose.foundation.layout/PaddingValues, kotlin/Unit>) // androidx.compose.material/Scaffold|Scaffold(androidx.compose.foundation.layout.WindowInsets;androidx.compose.ui.Modifier;androidx.compose.material.ScaffoldState;kotlin.Function0<kotlin.Unit>;kotlin.Function0<kotlin.Unit>;kotlin.Function1<androidx.compose.material.SnackbarHostState,kotlin.Unit>;kotlin.Function0<kotlin.Unit>;androidx.compose.material.FabPosition;kotlin.Boolean;kotlin.Function1<androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>?;kotlin.Boolean;androidx.compose.ui.graphics.Shape;androidx.compose.ui.unit.Dp;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;kotlin.Function1<androidx.compose.foundation.layout.PaddingValues,kotlin.Unit>){}[0]
 final fun androidx.compose.material/Scaffold(androidx.compose.ui/Modifier =..., androidx.compose.material/ScaffoldState =..., kotlin/Function0<kotlin/Unit> =..., kotlin/Function0<kotlin/Unit> =..., kotlin/Function1<androidx.compose.material/SnackbarHostState, kotlin/Unit> =..., kotlin/Function0<kotlin/Unit> =..., androidx.compose.material/FabPosition =..., kotlin/Boolean =..., kotlin/Function1<androidx.compose.foundation.layout/ColumnScope, kotlin/Unit>? =..., kotlin/Boolean =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., kotlin/Function1<androidx.compose.foundation.layout/PaddingValues, kotlin/Unit>) // androidx.compose.material/Scaffold|Scaffold(androidx.compose.ui.Modifier;androidx.compose.material.ScaffoldState;kotlin.Function0<kotlin.Unit>;kotlin.Function0<kotlin.Unit>;kotlin.Function1<androidx.compose.material.SnackbarHostState,kotlin.Unit>;kotlin.Function0<kotlin.Unit>;androidx.compose.material.FabPosition;kotlin.Boolean;kotlin.Function1<androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>?;kotlin.Boolean;androidx.compose.ui.graphics.Shape;androidx.compose.ui.unit.Dp;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;kotlin.Function1<androidx.compose.foundation.layout.PaddingValues,kotlin.Unit>){}[0]
 final fun androidx.compose.material/ScrollableTabRow(kotlin/Int, androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.unit/Dp =..., kotlin/Function1<kotlin.collections/List<androidx.compose.material/TabPosition>, kotlin/Unit> =..., kotlin/Function0<kotlin/Unit> =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.material/ScrollableTabRow|ScrollableTabRow(kotlin.Int;androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.Dp;kotlin.Function1<kotlin.collections.List<androidx.compose.material.TabPosition>,kotlin.Unit>;kotlin.Function0<kotlin.Unit>;kotlin.Function0<kotlin.Unit>){}[0]
@@ -475,10 +385,6 @@
 final fun androidx.compose.material/Snackbar(androidx.compose.ui/Modifier =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Boolean =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.unit/Dp =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.material/Snackbar|Snackbar(androidx.compose.ui.Modifier;kotlin.Function0<kotlin.Unit>?;kotlin.Boolean;androidx.compose.ui.graphics.Shape;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.unit.Dp;kotlin.Function0<kotlin.Unit>){}[0]
 final fun androidx.compose.material/SnackbarHost(androidx.compose.material/SnackbarHostState, androidx.compose.ui/Modifier =..., kotlin/Function1<androidx.compose.material/SnackbarData, kotlin/Unit> =...) // androidx.compose.material/SnackbarHost|SnackbarHost(androidx.compose.material.SnackbarHostState;androidx.compose.ui.Modifier;kotlin.Function1<androidx.compose.material.SnackbarData,kotlin.Unit>){}[0]
 final fun androidx.compose.material/Surface(androidx.compose.ui/Modifier =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.foundation/BorderStroke? =..., androidx.compose.ui.unit/Dp =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.material/Surface|Surface(androidx.compose.ui.Modifier;androidx.compose.ui.graphics.Shape;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.foundation.BorderStroke?;androidx.compose.ui.unit.Dp;kotlin.Function0<kotlin.Unit>){}[0]
-final fun androidx.compose.material/Surface(kotlin/Boolean, kotlin/Function0<kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.foundation/BorderStroke? =..., androidx.compose.ui.unit/Dp =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.material/Surface|Surface(kotlin.Boolean;kotlin.Function0<kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;androidx.compose.ui.graphics.Shape;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.foundation.BorderStroke?;androidx.compose.ui.unit.Dp;androidx.compose.foundation.interaction.MutableInteractionSource?;kotlin.Function0<kotlin.Unit>){}[0]
-final fun androidx.compose.material/Surface(kotlin/Boolean, kotlin/Function1<kotlin/Boolean, kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.foundation/BorderStroke? =..., androidx.compose.ui.unit/Dp =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.material/Surface|Surface(kotlin.Boolean;kotlin.Function1<kotlin.Boolean,kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;androidx.compose.ui.graphics.Shape;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.foundation.BorderStroke?;androidx.compose.ui.unit.Dp;androidx.compose.foundation.interaction.MutableInteractionSource?;kotlin.Function0<kotlin.Unit>){}[0]
-final fun androidx.compose.material/Surface(kotlin/Function0<kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.foundation/BorderStroke? =..., androidx.compose.ui.unit/Dp =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.material/Surface|Surface(kotlin.Function0<kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;androidx.compose.ui.graphics.Shape;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.foundation.BorderStroke?;androidx.compose.ui.unit.Dp;androidx.compose.foundation.interaction.MutableInteractionSource?;kotlin.Function0<kotlin.Unit>){}[0]
-final fun androidx.compose.material/SwipeToDismiss(androidx.compose.material/DismissState, androidx.compose.ui/Modifier =..., kotlin.collections/Set<androidx.compose.material/DismissDirection> =..., kotlin/Function1<androidx.compose.material/DismissDirection, androidx.compose.material/ThresholdConfig> =..., kotlin/Function1<androidx.compose.foundation.layout/RowScope, kotlin/Unit>, kotlin/Function1<androidx.compose.foundation.layout/RowScope, kotlin/Unit>) // androidx.compose.material/SwipeToDismiss|SwipeToDismiss(androidx.compose.material.DismissState;androidx.compose.ui.Modifier;kotlin.collections.Set<androidx.compose.material.DismissDirection>;kotlin.Function1<androidx.compose.material.DismissDirection,androidx.compose.material.ThresholdConfig>;kotlin.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit>;kotlin.Function1<androidx.compose.foundation.layout.RowScope,kotlin.Unit>){}[0]
 final fun androidx.compose.material/Switch(kotlin/Boolean, kotlin/Function1<kotlin/Boolean, kotlin/Unit>?, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.material/SwitchColors =...) // androidx.compose.material/Switch|Switch(kotlin.Boolean;kotlin.Function1<kotlin.Boolean,kotlin.Unit>?;androidx.compose.ui.Modifier;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.material.SwitchColors){}[0]
 final fun androidx.compose.material/Tab(kotlin/Boolean, kotlin/Function0<kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., kotlin/Function1<androidx.compose.foundation.layout/ColumnScope, kotlin/Unit>) // androidx.compose.material/Tab|Tab(kotlin.Boolean;kotlin.Function0<kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;kotlin.Function1<androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>){}[0]
 final fun androidx.compose.material/Tab(kotlin/Boolean, kotlin/Function0<kotlin/Unit>, androidx.compose.ui/Modifier =..., kotlin/Boolean =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., androidx.compose.foundation.interaction/MutableInteractionSource? =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =...) // androidx.compose.material/Tab|Tab(kotlin.Boolean;kotlin.Function0<kotlin.Unit>;androidx.compose.ui.Modifier;kotlin.Boolean;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;androidx.compose.foundation.interaction.MutableInteractionSource?;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
@@ -504,18 +410,11 @@
 final fun androidx.compose.material/rememberBottomDrawerState(androidx.compose.material/BottomDrawerValue, kotlin/Function1<androidx.compose.material/BottomDrawerValue, kotlin/Boolean> =..., androidx.compose.animation.core/AnimationSpec<kotlin/Float> =...): androidx.compose.material/BottomDrawerState // androidx.compose.material/rememberBottomDrawerState|rememberBottomDrawerState(androidx.compose.material.BottomDrawerValue;kotlin.Function1<androidx.compose.material.BottomDrawerValue,kotlin.Boolean>;androidx.compose.animation.core.AnimationSpec<kotlin.Float>){}[0]
 final fun androidx.compose.material/rememberBottomSheetScaffoldState(androidx.compose.material/BottomSheetState =..., androidx.compose.material/SnackbarHostState =...): androidx.compose.material/BottomSheetScaffoldState // androidx.compose.material/rememberBottomSheetScaffoldState|rememberBottomSheetScaffoldState(androidx.compose.material.BottomSheetState;androidx.compose.material.SnackbarHostState){}[0]
 final fun androidx.compose.material/rememberBottomSheetState(androidx.compose.material/BottomSheetValue, androidx.compose.animation.core/AnimationSpec<kotlin/Float> =..., kotlin/Function1<androidx.compose.material/BottomSheetValue, kotlin/Boolean> =...): androidx.compose.material/BottomSheetState // androidx.compose.material/rememberBottomSheetState|rememberBottomSheetState(androidx.compose.material.BottomSheetValue;androidx.compose.animation.core.AnimationSpec<kotlin.Float>;kotlin.Function1<androidx.compose.material.BottomSheetValue,kotlin.Boolean>){}[0]
-final fun androidx.compose.material/rememberDismissState(androidx.compose.material/DismissValue =..., kotlin/Function1<androidx.compose.material/DismissValue, kotlin/Boolean> =...): androidx.compose.material/DismissState // androidx.compose.material/rememberDismissState|rememberDismissState(androidx.compose.material.DismissValue;kotlin.Function1<androidx.compose.material.DismissValue,kotlin.Boolean>){}[0]
 final fun androidx.compose.material/rememberDrawerState(androidx.compose.material/DrawerValue, kotlin/Function1<androidx.compose.material/DrawerValue, kotlin/Boolean> =...): androidx.compose.material/DrawerState // androidx.compose.material/rememberDrawerState|rememberDrawerState(androidx.compose.material.DrawerValue;kotlin.Function1<androidx.compose.material.DrawerValue,kotlin.Boolean>){}[0]
 final fun androidx.compose.material/rememberModalBottomSheetState(androidx.compose.material/ModalBottomSheetValue, androidx.compose.animation.core/AnimationSpec<kotlin/Float> =..., kotlin/Function1<androidx.compose.material/ModalBottomSheetValue, kotlin/Boolean> =..., kotlin/Boolean =...): androidx.compose.material/ModalBottomSheetState // androidx.compose.material/rememberModalBottomSheetState|rememberModalBottomSheetState(androidx.compose.material.ModalBottomSheetValue;androidx.compose.animation.core.AnimationSpec<kotlin.Float>;kotlin.Function1<androidx.compose.material.ModalBottomSheetValue,kotlin.Boolean>;kotlin.Boolean){}[0]
 final fun androidx.compose.material/rememberScaffoldState(androidx.compose.material/DrawerState =..., androidx.compose.material/SnackbarHostState =...): androidx.compose.material/ScaffoldState // androidx.compose.material/rememberScaffoldState|rememberScaffoldState(androidx.compose.material.DrawerState;androidx.compose.material.SnackbarHostState){}[0]
 final fun androidx.compose.material/ripple(androidx.compose.ui.graphics/ColorProducer, kotlin/Boolean =..., androidx.compose.ui.unit/Dp =...): androidx.compose.foundation/IndicationNodeFactory // androidx.compose.material/ripple|ripple(androidx.compose.ui.graphics.ColorProducer;kotlin.Boolean;androidx.compose.ui.unit.Dp){}[0]
 final fun androidx.compose.material/ripple(kotlin/Boolean =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.graphics/Color =...): androidx.compose.foundation/IndicationNodeFactory // androidx.compose.material/ripple|ripple(kotlin.Boolean;androidx.compose.ui.unit.Dp;androidx.compose.ui.graphics.Color){}[0]
-final object androidx.compose.material.pullrefresh/PullRefreshDefaults { // androidx.compose.material.pullrefresh/PullRefreshDefaults|null[0]
-    final val RefreshThreshold // androidx.compose.material.pullrefresh/PullRefreshDefaults.RefreshThreshold|<get-RefreshThreshold>(){}[0]
-        final fun <get-RefreshThreshold>(): androidx.compose.ui.unit/Dp // androidx.compose.material.pullrefresh/PullRefreshDefaults.RefreshThreshold.<get-RefreshThreshold>|<get-RefreshThreshold>(){}[0]
-    final val RefreshingOffset // androidx.compose.material.pullrefresh/PullRefreshDefaults.RefreshingOffset|<get-RefreshingOffset>(){}[0]
-        final fun <get-RefreshingOffset>(): androidx.compose.ui.unit/Dp // androidx.compose.material.pullrefresh/PullRefreshDefaults.RefreshingOffset.<get-RefreshingOffset>|<get-RefreshingOffset>(){}[0]
-}
 final object androidx.compose.material/AppBarDefaults { // androidx.compose.material/AppBarDefaults|null[0]
     final val BottomAppBarElevation // androidx.compose.material/AppBarDefaults.BottomAppBarElevation|<get-BottomAppBarElevation>(){}[0]
         final fun <get-BottomAppBarElevation>(): androidx.compose.ui.unit/Dp // androidx.compose.material/AppBarDefaults.BottomAppBarElevation.<get-BottomAppBarElevation>|<get-BottomAppBarElevation>(){}[0]
@@ -584,28 +483,6 @@
 final object androidx.compose.material/CheckboxDefaults { // androidx.compose.material/CheckboxDefaults|null[0]
     final fun colors(androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =...): androidx.compose.material/CheckboxColors // androidx.compose.material/CheckboxDefaults.colors|colors(androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
 }
-final object androidx.compose.material/ChipDefaults { // androidx.compose.material/ChipDefaults|null[0]
-    final const val ContentOpacity // androidx.compose.material/ChipDefaults.ContentOpacity|<get-ContentOpacity>(){}[0]
-        final fun <get-ContentOpacity>(): kotlin/Float // androidx.compose.material/ChipDefaults.ContentOpacity.<get-ContentOpacity>|<get-ContentOpacity>(){}[0]
-    final const val LeadingIconOpacity // androidx.compose.material/ChipDefaults.LeadingIconOpacity|<get-LeadingIconOpacity>(){}[0]
-        final fun <get-LeadingIconOpacity>(): kotlin/Float // androidx.compose.material/ChipDefaults.LeadingIconOpacity.<get-LeadingIconOpacity>|<get-LeadingIconOpacity>(){}[0]
-    final const val OutlinedBorderOpacity // androidx.compose.material/ChipDefaults.OutlinedBorderOpacity|<get-OutlinedBorderOpacity>(){}[0]
-        final fun <get-OutlinedBorderOpacity>(): kotlin/Float // androidx.compose.material/ChipDefaults.OutlinedBorderOpacity.<get-OutlinedBorderOpacity>|<get-OutlinedBorderOpacity>(){}[0]
-    final fun chipColors(androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =...): androidx.compose.material/ChipColors // androidx.compose.material/ChipDefaults.chipColors|chipColors(androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
-    final fun filterChipColors(androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =...): androidx.compose.material/SelectableChipColors // androidx.compose.material/ChipDefaults.filterChipColors|filterChipColors(androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
-    final fun outlinedChipColors(androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =...): androidx.compose.material/ChipColors // androidx.compose.material/ChipDefaults.outlinedChipColors|outlinedChipColors(androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
-    final fun outlinedFilterChipColors(androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =...): androidx.compose.material/SelectableChipColors // androidx.compose.material/ChipDefaults.outlinedFilterChipColors|outlinedFilterChipColors(androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
-    final val LeadingIconSize // androidx.compose.material/ChipDefaults.LeadingIconSize|{}LeadingIconSize[0]
-        final fun <get-LeadingIconSize>(): androidx.compose.ui.unit/Dp // androidx.compose.material/ChipDefaults.LeadingIconSize.<get-LeadingIconSize>|<get-LeadingIconSize>(){}[0]
-    final val MinHeight // androidx.compose.material/ChipDefaults.MinHeight|<get-MinHeight>(){}[0]
-        final fun <get-MinHeight>(): androidx.compose.ui.unit/Dp // androidx.compose.material/ChipDefaults.MinHeight.<get-MinHeight>|<get-MinHeight>(){}[0]
-    final val OutlinedBorderSize // androidx.compose.material/ChipDefaults.OutlinedBorderSize|<get-OutlinedBorderSize>(){}[0]
-        final fun <get-OutlinedBorderSize>(): androidx.compose.ui.unit/Dp // androidx.compose.material/ChipDefaults.OutlinedBorderSize.<get-OutlinedBorderSize>|<get-OutlinedBorderSize>(){}[0]
-    final val SelectedIconSize // androidx.compose.material/ChipDefaults.SelectedIconSize|{}SelectedIconSize[0]
-        final fun <get-SelectedIconSize>(): androidx.compose.ui.unit/Dp // androidx.compose.material/ChipDefaults.SelectedIconSize.<get-SelectedIconSize>|<get-SelectedIconSize>(){}[0]
-    final val outlinedBorder // androidx.compose.material/ChipDefaults.outlinedBorder|{}outlinedBorder[0]
-        final fun <get-outlinedBorder>(): androidx.compose.foundation/BorderStroke // androidx.compose.material/ChipDefaults.outlinedBorder.<get-outlinedBorder>|<get-outlinedBorder>(){}[0]
-}
 final object androidx.compose.material/ContentAlpha { // androidx.compose.material/ContentAlpha|null[0]
     final val disabled // androidx.compose.material/ContentAlpha.disabled|{}disabled[0]
         final fun <get-disabled>(): kotlin/Float // androidx.compose.material/ContentAlpha.disabled.<get-disabled>|<get-disabled>(){}[0]
@@ -730,17 +607,8 @@
         final fun <get-IconOpacity>(): kotlin/Float // androidx.compose.material/TextFieldDefaults.IconOpacity.<get-IconOpacity>|<get-IconOpacity>(){}[0]
     final const val UnfocusedIndicatorLineOpacity // androidx.compose.material/TextFieldDefaults.UnfocusedIndicatorLineOpacity|{}UnfocusedIndicatorLineOpacity[0]
         final fun <get-UnfocusedIndicatorLineOpacity>(): kotlin/Float // androidx.compose.material/TextFieldDefaults.UnfocusedIndicatorLineOpacity.<get-UnfocusedIndicatorLineOpacity>|<get-UnfocusedIndicatorLineOpacity>(){}[0]
-    final fun (androidx.compose.ui/Modifier).indicatorLine(kotlin/Boolean, kotlin/Boolean, androidx.compose.foundation.interaction/InteractionSource, androidx.compose.material/TextFieldColors, androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =...): androidx.compose.ui/Modifier // androidx.compose.material/TextFieldDefaults.indicatorLine|[email protected](kotlin.Boolean;kotlin.Boolean;androidx.compose.foundation.interaction.InteractionSource;androidx.compose.material.TextFieldColors;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp){}[0]
-    final fun BorderBox(kotlin/Boolean, kotlin/Boolean, androidx.compose.foundation.interaction/InteractionSource, androidx.compose.material/TextFieldColors, androidx.compose.ui.graphics/Shape =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =...) // androidx.compose.material/TextFieldDefaults.BorderBox|BorderBox(kotlin.Boolean;kotlin.Boolean;androidx.compose.foundation.interaction.InteractionSource;androidx.compose.material.TextFieldColors;androidx.compose.ui.graphics.Shape;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp){}[0]
-    final fun OutlinedTextFieldDecorationBox(kotlin/String, kotlin/Function0<kotlin/Unit>, kotlin/Boolean, kotlin/Boolean, androidx.compose.ui.text.input/VisualTransformation, androidx.compose.foundation.interaction/InteractionSource, kotlin/Boolean =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., androidx.compose.material/TextFieldColors =..., androidx.compose.foundation.layout/PaddingValues =..., kotlin/Function0<kotlin/Unit> =...) // androidx.compose.material/TextFieldDefaults.OutlinedTextFieldDecorationBox|OutlinedTextFieldDecorationBox(kotlin.String;kotlin.Function0<kotlin.Unit>;kotlin.Boolean;kotlin.Boolean;androidx.compose.ui.text.input.VisualTransformation;androidx.compose.foundation.interaction.InteractionSource;kotlin.Boolean;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;androidx.compose.material.TextFieldColors;androidx.compose.foundation.layout.PaddingValues;kotlin.Function0<kotlin.Unit>){}[0]
-    final fun OutlinedTextFieldDecorationBox(kotlin/String, kotlin/Function0<kotlin/Unit>, kotlin/Boolean, kotlin/Boolean, androidx.compose.ui.text.input/VisualTransformation, androidx.compose.foundation.interaction/InteractionSource, kotlin/Boolean =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.material/TextFieldColors =..., androidx.compose.foundation.layout/PaddingValues =..., kotlin/Function0<kotlin/Unit> =...) // androidx.compose.material/TextFieldDefaults.OutlinedTextFieldDecorationBox|OutlinedTextFieldDecorationBox(kotlin.String;kotlin.Function0<kotlin.Unit>;kotlin.Boolean;kotlin.Boolean;androidx.compose.ui.text.input.VisualTransformation;androidx.compose.foundation.interaction.InteractionSource;kotlin.Boolean;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;androidx.compose.ui.graphics.Shape;androidx.compose.material.TextFieldColors;androidx.compose.foundation.layout.PaddingValues;kotlin.Function0<kotlin.Unit>){}[0]
-    final fun TextFieldDecorationBox(kotlin/String, kotlin/Function0<kotlin/Unit>, kotlin/Boolean, kotlin/Boolean, androidx.compose.ui.text.input/VisualTransformation, androidx.compose.foundation.interaction/InteractionSource, kotlin/Boolean =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., androidx.compose.material/TextFieldColors =..., androidx.compose.foundation.layout/PaddingValues =...) // androidx.compose.material/TextFieldDefaults.TextFieldDecorationBox|TextFieldDecorationBox(kotlin.String;kotlin.Function0<kotlin.Unit>;kotlin.Boolean;kotlin.Boolean;androidx.compose.ui.text.input.VisualTransformation;androidx.compose.foundation.interaction.InteractionSource;kotlin.Boolean;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;androidx.compose.material.TextFieldColors;androidx.compose.foundation.layout.PaddingValues){}[0]
-    final fun TextFieldDecorationBox(kotlin/String, kotlin/Function0<kotlin/Unit>, kotlin/Boolean, kotlin/Boolean, androidx.compose.ui.text.input/VisualTransformation, androidx.compose.foundation.interaction/InteractionSource, kotlin/Boolean =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., kotlin/Function0<kotlin/Unit>? =..., androidx.compose.ui.graphics/Shape =..., androidx.compose.material/TextFieldColors =..., androidx.compose.foundation.layout/PaddingValues =...) // androidx.compose.material/TextFieldDefaults.TextFieldDecorationBox|TextFieldDecorationBox(kotlin.String;kotlin.Function0<kotlin.Unit>;kotlin.Boolean;kotlin.Boolean;androidx.compose.ui.text.input.VisualTransformation;androidx.compose.foundation.interaction.InteractionSource;kotlin.Boolean;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;kotlin.Function0<kotlin.Unit>?;androidx.compose.ui.graphics.Shape;androidx.compose.material.TextFieldColors;androidx.compose.foundation.layout.PaddingValues){}[0]
     final fun outlinedTextFieldColors(androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =...): androidx.compose.material/TextFieldColors // androidx.compose.material/TextFieldDefaults.outlinedTextFieldColors|outlinedTextFieldColors(androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
-    final fun outlinedTextFieldPadding(androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =...): androidx.compose.foundation.layout/PaddingValues // androidx.compose.material/TextFieldDefaults.outlinedTextFieldPadding|outlinedTextFieldPadding(androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp){}[0]
     final fun textFieldColors(androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =...): androidx.compose.material/TextFieldColors // androidx.compose.material/TextFieldDefaults.textFieldColors|textFieldColors(androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color){}[0]
-    final fun textFieldWithLabelPadding(androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =...): androidx.compose.foundation.layout/PaddingValues // androidx.compose.material/TextFieldDefaults.textFieldWithLabelPadding|textFieldWithLabelPadding(androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp){}[0]
-    final fun textFieldWithoutLabelPadding(androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =..., androidx.compose.ui.unit/Dp =...): androidx.compose.foundation.layout/PaddingValues // androidx.compose.material/TextFieldDefaults.textFieldWithoutLabelPadding|textFieldWithoutLabelPadding(androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp){}[0]
     final val FocusedBorderThickness // androidx.compose.material/TextFieldDefaults.FocusedBorderThickness|{}FocusedBorderThickness[0]
         final fun <get-FocusedBorderThickness>(): androidx.compose.ui.unit/Dp // androidx.compose.material/TextFieldDefaults.FocusedBorderThickness.<get-FocusedBorderThickness>|<get-FocusedBorderThickness>(){}[0]
     final val MinHeight // androidx.compose.material/TextFieldDefaults.MinHeight|{}MinHeight[0]
@@ -762,16 +630,8 @@
     final fun <get-LocalContentColor>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.ui.graphics/Color> // androidx.compose.material/LocalContentColor.<get-LocalContentColor>|<get-LocalContentColor>(){}[0]
 final val androidx.compose.material/LocalElevationOverlay // androidx.compose.material/LocalElevationOverlay|{}LocalElevationOverlay[0]
     final fun <get-LocalElevationOverlay>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.material/ElevationOverlay?> // androidx.compose.material/LocalElevationOverlay.<get-LocalElevationOverlay>|<get-LocalElevationOverlay>(){}[0]
-final val androidx.compose.material/LocalMinimumInteractiveComponentEnforcement // androidx.compose.material/LocalMinimumInteractiveComponentEnforcement|<get-LocalMinimumInteractiveComponentEnforcement>(){}[0]
-    final fun <get-LocalMinimumInteractiveComponentEnforcement>(): androidx.compose.runtime/ProvidableCompositionLocal<kotlin/Boolean> // androidx.compose.material/LocalMinimumInteractiveComponentEnforcement.<get-LocalMinimumInteractiveComponentEnforcement>|<get-LocalMinimumInteractiveComponentEnforcement>(){}[0]
-final val androidx.compose.material/LocalMinimumTouchTargetEnforcement // androidx.compose.material/LocalMinimumTouchTargetEnforcement|{}LocalMinimumTouchTargetEnforcement[0]
-    final fun <get-LocalMinimumTouchTargetEnforcement>(): androidx.compose.runtime/ProvidableCompositionLocal<kotlin/Boolean> // androidx.compose.material/LocalMinimumTouchTargetEnforcement.<get-LocalMinimumTouchTargetEnforcement>|<get-LocalMinimumTouchTargetEnforcement>(){}[0]
-final val androidx.compose.material/LocalRippleConfiguration // androidx.compose.material/LocalRippleConfiguration|{}LocalRippleConfiguration[0]
-    final fun <get-LocalRippleConfiguration>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.material/RippleConfiguration?> // androidx.compose.material/LocalRippleConfiguration.<get-LocalRippleConfiguration>|<get-LocalRippleConfiguration>(){}[0]
 final val androidx.compose.material/LocalTextStyle // androidx.compose.material/LocalTextStyle|<get-LocalTextStyle>(){}[0]
     final fun <get-LocalTextStyle>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.ui.text/TextStyle> // androidx.compose.material/LocalTextStyle.<get-LocalTextStyle>|<get-LocalTextStyle>(){}[0]
-final val androidx.compose.material/LocalUseFallbackRippleImplementation // androidx.compose.material/LocalUseFallbackRippleImplementation|{}LocalUseFallbackRippleImplementation[0]
-    final fun <get-LocalUseFallbackRippleImplementation>(): androidx.compose.runtime/ProvidableCompositionLocal<kotlin/Boolean> // androidx.compose.material/LocalUseFallbackRippleImplementation.<get-LocalUseFallbackRippleImplementation>|<get-LocalUseFallbackRippleImplementation>(){}[0]
 final val androidx.compose.material/primarySurface // androidx.compose.material/primarySurface|@androidx.compose.material.Colors{}primarySurface[0]
     final fun (androidx.compose.material/Colors).<get-primarySurface>(): androidx.compose.ui.graphics/Color // androidx.compose.material/primarySurface.<get-primarySurface>|<get-primarySurface>@androidx.compose.material.Colors(){}[0]
 final value class androidx.compose.material/FabPosition { // androidx.compose.material/FabPosition|null[0]
@@ -790,27 +650,3 @@
 open annotation class androidx.compose.material/ExperimentalMaterialApi : kotlin/Annotation { // androidx.compose.material/ExperimentalMaterialApi|null[0]
     constructor <init>() // androidx.compose.material/ExperimentalMaterialApi.<init>|<init>(){}[0]
 }
-open class <#A: kotlin/Any?> androidx.compose.material/SwipeableState { // androidx.compose.material/SwipeableState|null[0]
-    constructor <init>(#A, androidx.compose.animation.core/AnimationSpec<kotlin/Float> =..., kotlin/Function1<#A, kotlin/Boolean> =...) // androidx.compose.material/SwipeableState.<init>|<init>(1:0;androidx.compose.animation.core.AnimationSpec<kotlin.Float>;kotlin.Function1<1:0,kotlin.Boolean>){}[0]
-    final fun performDrag(kotlin/Float): kotlin/Float // androidx.compose.material/SwipeableState.performDrag|performDrag(kotlin.Float){}[0]
-    final object Companion { // androidx.compose.material/SwipeableState.Companion|null[0]
-        final fun <#A2: kotlin/Any> Saver(androidx.compose.animation.core/AnimationSpec<kotlin/Float>, kotlin/Function1<#A2, kotlin/Boolean>): androidx.compose.runtime.saveable/Saver<androidx.compose.material/SwipeableState<#A2>, #A2> // androidx.compose.material/SwipeableState.Companion.Saver|Saver(androidx.compose.animation.core.AnimationSpec<kotlin.Float>;kotlin.Function1<0:0,kotlin.Boolean>){0§<kotlin.Any>}[0]
-    }
-    final suspend fun animateTo(#A, androidx.compose.animation.core/AnimationSpec<kotlin/Float> =...) // androidx.compose.material/SwipeableState.animateTo|animateTo(1:0;androidx.compose.animation.core.AnimationSpec<kotlin.Float>){}[0]
-    final suspend fun performFling(kotlin/Float) // androidx.compose.material/SwipeableState.performFling|performFling(kotlin.Float){}[0]
-    final suspend fun snapTo(#A) // androidx.compose.material/SwipeableState.snapTo|snapTo(1:0){}[0]
-    final val direction // androidx.compose.material/SwipeableState.direction|<get-direction>(){}[0]
-        final fun <get-direction>(): kotlin/Float // androidx.compose.material/SwipeableState.direction.<get-direction>|<get-direction>(){}[0]
-    final val offset // androidx.compose.material/SwipeableState.offset|{}offset[0]
-        final fun <get-offset>(): androidx.compose.runtime/State<kotlin/Float> // androidx.compose.material/SwipeableState.offset.<get-offset>|<get-offset>(){}[0]
-    final val overflow // androidx.compose.material/SwipeableState.overflow|{}overflow[0]
-        final fun <get-overflow>(): androidx.compose.runtime/State<kotlin/Float> // androidx.compose.material/SwipeableState.overflow.<get-overflow>|<get-overflow>(){}[0]
-    final val progress // androidx.compose.material/SwipeableState.progress|{}progress[0]
-        final fun <get-progress>(): androidx.compose.material/SwipeProgress<#A> // androidx.compose.material/SwipeableState.progress.<get-progress>|<get-progress>(){}[0]
-    final val targetValue // androidx.compose.material/SwipeableState.targetValue|{}targetValue[0]
-        final fun <get-targetValue>(): #A // androidx.compose.material/SwipeableState.targetValue.<get-targetValue>|<get-targetValue>(){}[0]
-    final var currentValue // androidx.compose.material/SwipeableState.currentValue|{}currentValue[0]
-        final fun <get-currentValue>(): #A // androidx.compose.material/SwipeableState.currentValue.<get-currentValue>|<get-currentValue>(){}[0]
-    final var isAnimationRunning // androidx.compose.material/SwipeableState.isAnimationRunning|{}isAnimationRunning[0]
-        final fun <get-isAnimationRunning>(): kotlin/Boolean // androidx.compose.material/SwipeableState.isAnimationRunning.<get-isAnimationRunning>|<get-isAnimationRunning>(){}[0]
-}
diff --git a/compose/material3/adaptive/adaptive-layout/api/current.txt b/compose/material3/adaptive/adaptive-layout/api/current.txt
index 1e5ab96..cbaeb22 100644
--- a/compose/material3/adaptive/adaptive-layout/api/current.txt
+++ b/compose/material3/adaptive/adaptive-layout/api/current.txt
@@ -106,20 +106,30 @@
   }
 
   @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public abstract sealed class PaneExpansionAnchor {
+    method @androidx.compose.runtime.Composable public abstract String getDescription();
+    property @androidx.compose.runtime.Composable public abstract String description;
   }
 
   public static final class PaneExpansionAnchor.Offset extends androidx.compose.material3.adaptive.layout.PaneExpansionAnchor {
     ctor public PaneExpansionAnchor.Offset(float offset);
+    method @androidx.compose.runtime.Composable public String getDescription();
     method public float getOffset();
+    property @androidx.compose.runtime.Composable public String description;
     property public final float offset;
   }
 
   public static final class PaneExpansionAnchor.Proportion extends androidx.compose.material3.adaptive.layout.PaneExpansionAnchor {
     ctor public PaneExpansionAnchor.Proportion(@FloatRange(from=0.0, to=1.0) float proportion);
+    method @androidx.compose.runtime.Composable public String getDescription();
     method public float getProportion();
+    property @androidx.compose.runtime.Composable public String description;
     property @FloatRange(from=0.0, to=1.0) public final float proportion;
   }
 
+  public final class PaneExpansionDraggableModifierKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static kotlin.jvm.functions.Function1<androidx.compose.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit> defaultDragHandleSemantics(androidx.compose.material3.adaptive.layout.PaneExpansionState);
+  }
+
   @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public final class PaneExpansionState {
     method public void clear();
     method public boolean isUnspecified();
@@ -297,7 +307,7 @@
   }
 
   public sealed interface PaneScaffoldScope {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public androidx.compose.ui.Modifier paneExpansionDraggable(androidx.compose.ui.Modifier, androidx.compose.material3.adaptive.layout.PaneExpansionState state, float minTouchTargetSize, androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public androidx.compose.ui.Modifier paneExpansionDraggable(androidx.compose.ui.Modifier, androidx.compose.material3.adaptive.layout.PaneExpansionState state, float minTouchTargetSize, androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit> semanticsProperties);
     method public androidx.compose.ui.Modifier preferredWidth(androidx.compose.ui.Modifier, float width);
   }
 
@@ -371,10 +381,6 @@
     property public int size;
   }
 
-  public final class ThreePaneScaffoldHorizontalOrderKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldHorizontalOrder toLtrOrder(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldHorizontalOrder, androidx.compose.ui.unit.LayoutDirection layoutDirection);
-  }
-
   public final class ThreePaneScaffoldKt {
     method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveComponentOverrideApi public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldOverride> getLocalThreePaneScaffoldOverride();
     property @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveComponentOverrideApi public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldOverride> LocalThreePaneScaffoldOverride;
diff --git a/compose/material3/adaptive/adaptive-layout/api/restricted_current.txt b/compose/material3/adaptive/adaptive-layout/api/restricted_current.txt
index 1e5ab96..cbaeb22 100644
--- a/compose/material3/adaptive/adaptive-layout/api/restricted_current.txt
+++ b/compose/material3/adaptive/adaptive-layout/api/restricted_current.txt
@@ -106,20 +106,30 @@
   }
 
   @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public abstract sealed class PaneExpansionAnchor {
+    method @androidx.compose.runtime.Composable public abstract String getDescription();
+    property @androidx.compose.runtime.Composable public abstract String description;
   }
 
   public static final class PaneExpansionAnchor.Offset extends androidx.compose.material3.adaptive.layout.PaneExpansionAnchor {
     ctor public PaneExpansionAnchor.Offset(float offset);
+    method @androidx.compose.runtime.Composable public String getDescription();
     method public float getOffset();
+    property @androidx.compose.runtime.Composable public String description;
     property public final float offset;
   }
 
   public static final class PaneExpansionAnchor.Proportion extends androidx.compose.material3.adaptive.layout.PaneExpansionAnchor {
     ctor public PaneExpansionAnchor.Proportion(@FloatRange(from=0.0, to=1.0) float proportion);
+    method @androidx.compose.runtime.Composable public String getDescription();
     method public float getProportion();
+    property @androidx.compose.runtime.Composable public String description;
     property @FloatRange(from=0.0, to=1.0) public final float proportion;
   }
 
+  public final class PaneExpansionDraggableModifierKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static kotlin.jvm.functions.Function1<androidx.compose.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit> defaultDragHandleSemantics(androidx.compose.material3.adaptive.layout.PaneExpansionState);
+  }
+
   @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public final class PaneExpansionState {
     method public void clear();
     method public boolean isUnspecified();
@@ -297,7 +307,7 @@
   }
 
   public sealed interface PaneScaffoldScope {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public androidx.compose.ui.Modifier paneExpansionDraggable(androidx.compose.ui.Modifier, androidx.compose.material3.adaptive.layout.PaneExpansionState state, float minTouchTargetSize, androidx.compose.foundation.interaction.MutableInteractionSource interactionSource);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public androidx.compose.ui.Modifier paneExpansionDraggable(androidx.compose.ui.Modifier, androidx.compose.material3.adaptive.layout.PaneExpansionState state, float minTouchTargetSize, androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, kotlin.jvm.functions.Function1<? super androidx.compose.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit> semanticsProperties);
     method public androidx.compose.ui.Modifier preferredWidth(androidx.compose.ui.Modifier, float width);
   }
 
@@ -371,10 +381,6 @@
     property public int size;
   }
 
-  public final class ThreePaneScaffoldHorizontalOrderKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldHorizontalOrder toLtrOrder(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldHorizontalOrder, androidx.compose.ui.unit.LayoutDirection layoutDirection);
-  }
-
   public final class ThreePaneScaffoldKt {
     method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveComponentOverrideApi public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldOverride> getLocalThreePaneScaffoldOverride();
     property @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveComponentOverrideApi public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.material3.adaptive.layout.ThreePaneScaffoldOverride> LocalThreePaneScaffoldOverride;
diff --git a/compose/material3/adaptive/adaptive-layout/build.gradle b/compose/material3/adaptive/adaptive-layout/build.gradle
index 4c3c2d5..7618be0d 100644
--- a/compose/material3/adaptive/adaptive-layout/build.gradle
+++ b/compose/material3/adaptive/adaptive-layout/build.gradle
@@ -68,6 +68,8 @@
             dependencies {
                 api("androidx.annotation:annotation:1.8.1")
                 api("androidx.annotation:annotation-experimental:1.4.1")
+                implementation("androidx.compose.runtime:runtime:1.6.5")
+                implementation("androidx.core:core:1.12.0")
             }
         }
 
diff --git a/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScreenshotTest.kt b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScreenshotTest.kt
index 1dba98e4..e39d484 100644
--- a/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScreenshotTest.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScreenshotTest.kt
@@ -532,7 +532,8 @@
             Modifier.paneExpansionDraggable(
                 state,
                 LocalMinimumInteractiveComponentSize.current,
-                interactionSource
+                interactionSource,
+                state.defaultDragHandleSemantics()
             ),
         interactionSource = interactionSource
     )
diff --git a/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldTest.kt b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldTest.kt
index 4426ce9..591c322 100644
--- a/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldTest.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldTest.kt
@@ -287,6 +287,40 @@
                 .isEqualTo(mockPaneExpansionState.maxExpansionWidth)
         }
     }
+
+    @Test
+    fun threePaneScaffold_paneExpansionWithDragHandle_noAnchorOnSettlingDirection() {
+        var mockDraggingPx = 0f
+        var expectedSettledOffsetPx = 0
+        lateinit var mockPaneExpansionState: PaneExpansionState
+        lateinit var scope: CoroutineScope
+
+        rule.setContentWithSimulatedSize(simulatedWidth = 1024.dp, simulatedHeight = 800.dp) {
+            scope = rememberCoroutineScope()
+            mockPaneExpansionState =
+                rememberPaneExpansionState(
+                    anchors =
+                        listOf(
+                            PaneExpansionAnchor.Proportion(0f),
+                            PaneExpansionAnchor.Offset(MockPaneExpansionMiddleAnchor)
+                        )
+                )
+            mockDraggingPx = with(LocalDensity.current) { 200.dp.toPx() }
+            expectedSettledOffsetPx =
+                with(LocalDensity.current) { MockPaneExpansionMiddleAnchor.toPx().toInt() }
+            SampleThreePaneScaffoldWithPaneExpansion(mockPaneExpansionState) { MockDragHandle(it) }
+        }
+
+        rule.runOnIdle {
+            mockPaneExpansionState.draggableState.dispatchRawDelta(mockDraggingPx)
+            scope.launch { mockPaneExpansionState.settleToAnchorIfNeeded(400F) }
+        }
+
+        rule.runOnIdle {
+            assertThat(mockPaneExpansionState.currentMeasuredDraggingOffset)
+                .isEqualTo(expectedSettledOffsetPx)
+        }
+    }
 }
 
 private val MockScaffoldDirective = PaneScaffoldDirective.Default
diff --git a/compose/material3/adaptive/adaptive-layout/src/androidMain/AndroidManifest.xml b/compose/material3/adaptive/adaptive-layout/src/androidMain/AndroidManifest.xml
new file mode 100644
index 0000000..c77c703
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-layout/src/androidMain/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2025 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">
+
+</manifest>
\ No newline at end of file
diff --git a/compose/material3/adaptive/adaptive-layout/src/androidMain/kotlin/androidx/compose/material3/adaptive/layout/Strings.android.kt b/compose/material3/adaptive/adaptive-layout/src/androidMain/kotlin/androidx/compose/material3/adaptive/layout/Strings.android.kt
new file mode 100644
index 0000000..a563fe9
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-layout/src/androidMain/kotlin/androidx/compose/material3/adaptive/layout/Strings.android.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.adaptive.layout
+
+import androidx.annotation.StringRes
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.ReadOnlyComposable
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalContext
+import androidx.core.os.ConfigurationCompat
+import java.util.Locale
+
+@Composable
+@ReadOnlyComposable
+internal actual fun getString(string: Strings): String {
+    // Do a no-op reading so when LocalConfiguration changes, this function will be recomposed.
+    LocalConfiguration.current
+    val resources = LocalContext.current.resources
+    return resources.getString(string.value)
+}
+
+@Composable
+@ReadOnlyComposable
+internal actual fun getString(string: Strings, vararg formatArgs: Any): String {
+    val raw = getString(string)
+    val locale =
+        ConfigurationCompat.getLocales(LocalConfiguration.current).get(0) ?: Locale.getDefault()
+    return String.format(locale, raw, *formatArgs)
+}
+
+@JvmInline
+@Immutable
+internal actual value class Strings(@StringRes val value: Int) {
+    actual companion object {
+        actual inline val defaultPaneExpansionDragHandleContentDescription
+            get() =
+                Strings(R.string.m3_adaptive_default_pane_expansion_drag_handle_content_description)
+
+        actual inline val defaultPaneExpansionDragHandleActionDescription
+            get() =
+                Strings(R.string.m3_adaptive_default_pane_expansion_drag_handle_action_description)
+
+        actual inline val defaultPaneExpansionProportionAnchorDescription
+            get() =
+                Strings(R.string.m3_adaptive_default_pane_expansion_proportion_anchor_description)
+
+        actual inline val defaultPaneExpansionOffsetAnchorDescription
+            get() = Strings(R.string.m3_adaptive_default_pane_expansion_offset_anchor_description)
+    }
+}
diff --git a/compose/material3/adaptive/adaptive-layout/src/androidMain/res/values/strings.xml b/compose/material3/adaptive/adaptive-layout/src/androidMain/res/values/strings.xml
new file mode 100644
index 0000000..38b807f
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-layout/src/androidMain/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright 2025 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>
+    <!-- Spoken content description of a drag handle that use to control pane expansion. -->
+    <string name="m3_adaptive_default_pane_expansion_drag_handle_content_description">
+        Pane expansion drag handle
+    </string>
+    <!-- Spoken action description of a drag handle that use to control pane expansion. -->
+    <string name="m3_adaptive_default_pane_expansion_drag_handle_action_description">
+        Change pane split to %s
+    </string>
+    <!-- Spoken description of a pane expansion anchor point based on proportion in percentages
+         a user can anchor the pane expansion to. -->
+    <string name="m3_adaptive_default_pane_expansion_proportion_anchor_description">
+        %d percent
+    </string>
+    <!-- Spoken description of a pane expansion anchor point based on offset in DPs a user can
+         anchor the pane expansion to. -->
+    <string name="m3_adaptive_default_pane_expansion_offset_anchor_description">%d DPs</string>
+</resources>
diff --git a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDraggableModifier.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDraggableModifier.kt
index 1881c29..0ae89ea 100644
--- a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDraggableModifier.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionDraggableModifier.kt
@@ -16,14 +16,55 @@
 
 package androidx.compose.material3.adaptive.layout
 
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
+import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.node.ModifierNodeElement
 import androidx.compose.ui.node.ParentDataModifierNode
 import androidx.compose.ui.platform.InspectorInfo
 import androidx.compose.ui.platform.debugInspectorInfo
+import androidx.compose.ui.semantics.SemanticsPropertyReceiver
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.onClick
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.Dp
 
+/**
+ * This function sets up the default semantics of pane expansion drag handles with the given
+ * [PaneExpansionState]. It will provide suitable [contentDescription] as well as [onClick] function
+ * to move the pane expansion among anchors that can be operated via accessibility services.
+ *
+ * It's supposed to be used with a [PaneScaffoldScope.paneExpansionDraggable] modifier, or a plain
+ * [semantics] modifier associated with a drag handle composable.
+ */
+@ExperimentalMaterial3AdaptiveApi
+@Composable
+fun PaneExpansionState.defaultDragHandleSemantics(): SemanticsPropertyReceiver.() -> Unit {
+    val description = getString(Strings.defaultPaneExpansionDragHandleContentDescription)
+    val nextAnchor = nextAnchor
+    val actionLabel =
+        if (nextAnchor != null) {
+            getString(
+                Strings.defaultPaneExpansionDragHandleActionDescription,
+                nextAnchor.description
+            )
+        } else {
+            null
+        }
+    return semantics@{
+        contentDescription = description
+        if (nextAnchor == null) {
+            // TODO(conrachen): handle this case
+            return@semantics
+        }
+        onClick(label = actionLabel) {
+            snapToAnchor(nextAnchor)
+            return@onClick true
+        }
+    }
+}
+
 internal expect fun Modifier.systemGestureExclusion(): Modifier
 
 internal data class MinTouchTargetSizeElement(val size: Dp) :
diff --git a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionState.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionState.kt
index 1b63b46..910b42e7 100644
--- a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionState.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneExpansionState.kt
@@ -200,7 +200,6 @@
     data: PaneExpansionStateData = PaneExpansionStateData(),
     anchors: List<PaneExpansionAnchor> = emptyList()
 ) {
-
     internal val firstPaneWidth
         get() =
             if (maxExpansionWidth == Unspecified || data.firstPaneWidthState == Unspecified) {
@@ -226,10 +225,32 @@
     @VisibleForTesting
     internal var currentAnchor
         get() = data.currentAnchorState
-        set(value) {
+        private set(value) {
             data.currentAnchorState = value
         }
 
+    internal val nextAnchor: PaneExpansionAnchor?
+        get() {
+            // maxExpansionWidth will be initialized in onMeasured and is backed by a state. Check
+            // it
+            // here so the next anchor will be updated when measuring is done.
+            if (maxExpansionWidth == Unspecified || anchors.isEmpty()) {
+                return null
+            }
+            val currentOffset =
+                if (currentDraggingOffset == Unspecified) {
+                    currentMeasuredDraggingOffset
+                } else {
+                    currentDraggingOffset
+                }
+            measuredAnchorPositions.forEach { index, position ->
+                if (currentOffset < position) {
+                    return anchors[index]
+                }
+            }
+            return anchors[0]
+        }
+
     private var data by mutableStateOf(data)
 
     internal var isDragging by mutableStateOf(false)
@@ -253,11 +274,14 @@
 
     private var anchors: List<PaneExpansionAnchor> by mutableStateOf(anchors)
 
+    internal var measuredAnchorPositions = IndexedAnchorPositionList(0)
+        private set
+
     private lateinit var anchoringAnimationSpec: FiniteAnimationSpec<Float>
 
     private lateinit var flingBehavior: FlingBehavior
 
-    private lateinit var measuredDensity: Density
+    private var measuredDensity: Density? = null
 
     private val dragScope =
         object : DragScope, ScrollScope {
@@ -348,6 +372,15 @@
         dragMutex.mutate(MutatePriority.PreventUserInput) {
             this.data = data
             this.anchors = anchors
+            measuredDensity?.let {
+                measuredAnchorPositions =
+                    anchors.toPositions(
+                        // When maxExpansionWidth is updated, the anchor positions will be
+                        // recalculated.
+                        Snapshot.withoutReadObservation { maxExpansionWidth },
+                        it
+                    )
+            }
             if (!anchors.contains(Snapshot.withoutReadObservation { currentAnchor })) {
                 currentAnchor = null
             }
@@ -357,12 +390,13 @@
     }
 
     internal fun onMeasured(measuredWidth: Int, density: Density) {
-        if (measuredWidth == maxExpansionWidth) {
+        if (measuredWidth == maxExpansionWidth && measuredDensity == density) {
             return
         }
         maxExpansionWidth = measuredWidth
         measuredDensity = density
         Snapshot.withoutReadObservation {
+            measuredAnchorPositions = anchors.toPositions(measuredWidth, density)
             // Changes will always apply to the ongoing measurement, no need to trigger remeasuring
             currentAnchor?.also { currentDraggingOffset = it.positionIn(measuredWidth, density) }
                 ?: {
@@ -378,9 +412,16 @@
         currentMeasuredDraggingOffset = measuredOffset
     }
 
+    internal fun snapToAnchor(anchor: PaneExpansionAnchor) {
+        Snapshot.withoutReadObservation {
+            measuredDensity?.let {
+                currentDraggingOffset = anchor.positionIn(maxExpansionWidth, it)
+            }
+        }
+    }
+
     internal suspend fun settleToAnchorIfNeeded(velocity: Float) {
-        val currentAnchorPositions = anchors.toPositions(maxExpansionWidth, measuredDensity)
-        if (currentAnchorPositions.isEmpty()) {
+        if (measuredAnchorPositions.isEmpty()) {
             return
         }
 
@@ -388,7 +429,7 @@
             isSettling = true
             val leftVelocity = flingBehavior.run { dragScope.performFling(velocity) }
             val anchorPosition =
-                currentAnchorPositions.getPositionOfTheClosestAnchor(
+                measuredAnchorPositions.getPositionOfTheClosestAnchor(
                     currentMeasuredDraggingOffset,
                     leftVelocity
                 )
@@ -418,13 +459,23 @@
                 velocity >= AnchoringVelocityThreshold -> {
                     { anchorPosition: Int ->
                         val delta = anchorPosition - currentPosition
-                        if (delta < 0) Int.MAX_VALUE else delta
+                        if (delta < 0) {
+                            // If there's no anchor on the swiping direction, use the closet anchor
+                            maxExpansionWidth - delta
+                        } else {
+                            delta
+                        }
                     }
                 }
                 velocity <= -AnchoringVelocityThreshold -> {
                     { anchorPosition: Int ->
                         val delta = currentPosition - anchorPosition
-                        if (delta < 0) Int.MAX_VALUE else delta
+                        if (delta < 0) {
+                            // If there's no anchor on the swiping direction, use the closet anchor
+                            maxExpansionWidth - delta
+                        } else {
+                            delta
+                        }
                     }
                 }
                 else -> {
@@ -488,12 +539,18 @@
  * the set anchors after user releases the drag.
  */
 @ExperimentalMaterial3AdaptiveApi
-sealed class PaneExpansionAnchor private constructor() {
+sealed class PaneExpansionAnchor {
     internal abstract fun positionIn(totalSizePx: Int, density: Density): Int
 
     internal abstract val type: Int
 
     /**
+     * The description of the anchor that will be used in
+     * [androidx.compose.ui.semantics.SemanticsProperties] like accessibility services.
+     */
+    @get:Composable abstract val description: String
+
+    /**
      * [PaneExpansionAnchor] implementation that specifies the anchor position in the proportion of
      * the total size of the layout at the start side of the anchor.
      *
@@ -502,6 +559,14 @@
     class Proportion(@FloatRange(0.0, 1.0) val proportion: Float) : PaneExpansionAnchor() {
         override val type = ProportionType
 
+        override val description
+            @Composable
+            get() =
+                getString(
+                    Strings.defaultPaneExpansionProportionAnchorDescription,
+                    (proportion * 100).toInt()
+                )
+
         override fun positionIn(totalSizePx: Int, density: Density) =
             (totalSizePx * proportion).roundToInt().coerceIn(0, totalSizePx)
 
@@ -528,6 +593,11 @@
     class Offset(val offset: Dp) : PaneExpansionAnchor() {
         override val type = OffsetType
 
+        override val description
+            @Composable
+            get() =
+                getString(Strings.defaultPaneExpansionOffsetAnchorDescription, offset.value.toInt())
+
         override fun positionIn(totalSizePx: Int, density: Density) =
             with(density) { offset.toPx() }.toInt().let { if (it < 0) totalSizePx + it else it }
 
@@ -684,7 +754,7 @@
 }
 
 @JvmInline
-private value class IndexedAnchorPositionList(val value: MutableLongList) {
+internal value class IndexedAnchorPositionList(val value: MutableLongList) {
     constructor(size: Int) : this(MutableLongList(size))
 
     val size
@@ -699,8 +769,12 @@
     operator fun get(index: Int) = IndexedAnchorPosition(value[index])
 }
 
+internal inline fun IndexedAnchorPositionList.forEach(action: (index: Int, position: Int) -> Unit) {
+    value.forEach { with(IndexedAnchorPosition(it)) { action(index, position) } }
+}
+
 @JvmInline
-private value class IndexedAnchorPosition(val value: Long) {
+internal value class IndexedAnchorPosition(val value: Long) {
     constructor(position: Int, index: Int) : this(packInts(position, index))
 
     val position
diff --git a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.kt
index be3751a..cc05a0f 100644
--- a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.kt
@@ -28,6 +28,7 @@
 import androidx.compose.ui.node.ParentDataModifierNode
 import androidx.compose.ui.platform.InspectorInfo
 import androidx.compose.ui.platform.debugInspectorInfo
+import androidx.compose.ui.semantics.SemanticsPropertyReceiver
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
@@ -93,10 +94,13 @@
      * @sample androidx.compose.material3.adaptive.samples.PaneExpansionDragHandleSample
      */
     @ExperimentalMaterial3AdaptiveApi
+    // TODO(conradchen): Change this to a composable function with default semantics after
+    //  b/165812010 is fixed
     fun Modifier.paneExpansionDraggable(
         state: PaneExpansionState,
         minTouchTargetSize: Dp,
-        interactionSource: MutableInteractionSource
+        interactionSource: MutableInteractionSource,
+        semanticsProperties: (SemanticsPropertyReceiver.() -> Unit)
     ): Modifier
 }
 
diff --git a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/Strings.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/Strings.kt
new file mode 100644
index 0000000..4ff2966
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/Strings.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.adaptive.layout
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.ReadOnlyComposable
+
+@Immutable
+@JvmInline
+internal expect value class Strings(val value: Int) {
+    companion object {
+        val defaultPaneExpansionDragHandleContentDescription: Strings
+        val defaultPaneExpansionDragHandleActionDescription: Strings
+        val defaultPaneExpansionProportionAnchorDescription: Strings
+        val defaultPaneExpansionOffsetAnchorDescription: Strings
+    }
+}
+
+@Composable @ReadOnlyComposable internal expect fun getString(string: Strings): String
+
+@Composable
+@ReadOnlyComposable
+internal expect fun getString(string: Strings, vararg formatArgs: Any): String
diff --git a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldHorizontalOrder.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldHorizontalOrder.kt
index c49ce79..f77a635 100644
--- a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldHorizontalOrder.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldHorizontalOrder.kt
@@ -90,12 +90,12 @@
 }
 
 /**
- * Converts a bidirectional order to a left-to-right order.
+ * Converts a bidirectional [ThreePaneScaffoldHorizontalOrder] to a left-to-right order.
  *
  * @param layoutDirection the current [LayoutDirection]
  */
 @ExperimentalMaterial3AdaptiveApi
-fun ThreePaneScaffoldHorizontalOrder.toLtrOrder(
+internal fun ThreePaneScaffoldHorizontalOrder.toLtrOrder(
     layoutDirection: LayoutDirection
 ): ThreePaneScaffoldHorizontalOrder {
     return if (layoutDirection == LayoutDirection.Rtl) {
diff --git a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScope.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScope.kt
index a605503..0bdd476 100644
--- a/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScope.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScope.kt
@@ -28,6 +28,8 @@
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.LookaheadScope
+import androidx.compose.ui.semantics.SemanticsPropertyReceiver
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.Dp
 
 /** Scope for the panes of [ThreePaneScaffold]. */
@@ -55,7 +57,8 @@
     override fun Modifier.paneExpansionDraggable(
         state: PaneExpansionState,
         minTouchTargetSize: Dp,
-        interactionSource: MutableInteractionSource
+        interactionSource: MutableInteractionSource,
+        semanticsProperties: (SemanticsPropertyReceiver.() -> Unit)
     ): Modifier =
         this.draggable(
                 state = state.draggableState,
@@ -69,6 +72,7 @@
                 animateFraction = { motionProgress },
                 lookaheadScope = this@ThreePaneScaffoldScopeImpl
             )
+            .semantics(mergeDescendants = true, properties = semanticsProperties)
             .then(MinTouchTargetSizeElement(minTouchTargetSize))
 }
 
diff --git a/compose/material3/adaptive/adaptive-layout/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/layout/Strings.jvmStubs.kt b/compose/material3/adaptive/adaptive-layout/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/layout/Strings.jvmStubs.kt
new file mode 100644
index 0000000..a419136
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-layout/src/jvmStubsMain/kotlin/androidx/compose/material3/adaptive/layout/Strings.jvmStubs.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.adaptive.layout
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.ReadOnlyComposable
+
+@Composable
+@ReadOnlyComposable
+internal actual fun getString(string: Strings): String = implementedInJetBrainsFork()
+
+@Composable
+@ReadOnlyComposable
+internal actual fun getString(string: Strings, vararg formatArgs: Any): String =
+    implementedInJetBrainsFork()
+
+@JvmInline
+@Immutable
+internal actual value class Strings(val value: Int) {
+    actual companion object {
+        actual val defaultPaneExpansionDragHandleContentDescription: Strings =
+            implementedInJetBrainsFork()
+        actual val defaultPaneExpansionDragHandleActionDescription: Strings =
+            implementedInJetBrainsFork()
+        actual val defaultPaneExpansionProportionAnchorDescription: Strings =
+            implementedInJetBrainsFork()
+        actual val defaultPaneExpansionOffsetAnchorDescription: Strings =
+            implementedInJetBrainsFork()
+    }
+}
diff --git a/compose/material3/adaptive/samples/src/main/java/androidx/compose/material3/adaptive/samples/ThreePaneScaffoldSample.kt b/compose/material3/adaptive/samples/src/main/java/androidx/compose/material3/adaptive/samples/ThreePaneScaffoldSample.kt
index 6331422..798e57e 100644
--- a/compose/material3/adaptive/samples/src/main/java/androidx/compose/material3/adaptive/samples/ThreePaneScaffoldSample.kt
+++ b/compose/material3/adaptive/samples/src/main/java/androidx/compose/material3/adaptive/samples/ThreePaneScaffoldSample.kt
@@ -60,6 +60,7 @@
 import androidx.compose.material3.adaptive.layout.PaneExpansionAnchor
 import androidx.compose.material3.adaptive.layout.PaneExpansionState
 import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope
+import androidx.compose.material3.adaptive.layout.defaultDragHandleSemantics
 import androidx.compose.material3.adaptive.layout.rememberPaneExpansionState
 import androidx.compose.material3.adaptive.navigation.BackNavigationBehavior
 import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator
@@ -213,7 +214,8 @@
                     Modifier.paneExpansionDraggable(
                         state,
                         LocalMinimumInteractiveComponentSize.current,
-                        interactionSource
+                        interactionSource,
+                        state.defaultDragHandleSemantics()
                     ),
                 interactionSource = interactionSource
             )
@@ -234,7 +236,8 @@
             Modifier.paneExpansionDraggable(
                 state,
                 LocalMinimumInteractiveComponentSize.current,
-                interactionSource
+                interactionSource,
+                state.defaultDragHandleSemantics()
             ),
         interactionSource = interactionSource
     )
diff --git a/compose/material3/material3/api/current.txt b/compose/material3/material3/api/current.txt
index 98fd41b..9c465b2e 100644
--- a/compose/material3/material3/api/current.txt
+++ b/compose/material3/material3/api/current.txt
@@ -42,15 +42,15 @@
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static androidx.compose.material3.BottomAppBarState BottomAppBarState(float initialHeightOffsetLimit, float initialHeightOffset, float initialContentOffset);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void CenterAlignedTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void CenterAlignedTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void LargeFlexibleTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? subtitle, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.ui.Alignment.Horizontal titleHorizontalAlignment, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void LargeTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void LargeTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void LargeTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit>? subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional int titleHorizontalAlignment, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void MediumFlexibleTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? subtitle, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.ui.Alignment.Horizontal titleHorizontalAlignment, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void MediumTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void MediumTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void MediumTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit>? subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional int titleHorizontalAlignment, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit> subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional int titleHorizontalAlignment, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit> subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.ui.Alignment.Horizontal titleHorizontalAlignment, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.BottomAppBarState rememberBottomAppBarState(optional float initialHeightOffsetLimit, optional float initialHeightOffset, optional float initialContentOffset);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.TopAppBarState rememberTopAppBarState(optional float initialHeightOffsetLimit, optional float initialHeightOffset, optional float initialContentOffset);
   }
@@ -2200,13 +2200,16 @@
     method public void dispatchRawDelta(float delta);
     method public suspend Object? drag(androidx.compose.foundation.MutatePriority dragPriority, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.gestures.DragScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block, kotlin.coroutines.Continuation<? super kotlin.Unit>);
     method public float getCoercedValueAsFraction();
+    method public kotlin.jvm.functions.Function1<java.lang.Float,kotlin.Unit>? getOnValueChange();
     method public kotlin.jvm.functions.Function0<kotlin.Unit>? getOnValueChangeFinished();
     method public int getSteps();
     method public float getValue();
     method public kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> getValueRange();
+    method public void setOnValueChange(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit>?);
     method public void setOnValueChangeFinished(kotlin.jvm.functions.Function0<kotlin.Unit>?);
     method public void setValue(float);
     property public final float coercedValueAsFraction;
+    property public final kotlin.jvm.functions.Function1<java.lang.Float,kotlin.Unit>? onValueChange;
     property public final kotlin.jvm.functions.Function0<kotlin.Unit>? onValueChangeFinished;
     property @IntRange(from=0L) public final int steps;
     property public final float value;
@@ -2900,51 +2903,55 @@
   }
 
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class TopAppBarColors {
-    ctor public TopAppBarColors(long containerColor, long scrolledContainerColor, long navigationIconContentColor, long titleContentColor, long actionIconContentColor);
-    method public androidx.compose.material3.TopAppBarColors copy(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    ctor @Deprecated public TopAppBarColors(long containerColor, long scrolledContainerColor, long navigationIconContentColor, long titleContentColor, long actionIconContentColor);
+    ctor public TopAppBarColors(long containerColor, long scrolledContainerColor, long navigationIconContentColor, long titleContentColor, long actionIconContentColor, long subtitleContentColor);
+    method public androidx.compose.material3.TopAppBarColors copy(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor, optional long subtitleContentColor);
     method public long getActionIconContentColor();
     method public long getContainerColor();
     method public long getNavigationIconContentColor();
     method public long getScrolledContainerColor();
+    method public long getSubtitleContentColor();
     method public long getTitleContentColor();
     property public final long actionIconContentColor;
     property public final long containerColor;
     property public final long navigationIconContentColor;
     property public final long scrolledContainerColor;
+    property public final long subtitleContentColor;
     property public final long titleContentColor;
   }
 
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public final class TopAppBarDefaults {
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors centerAlignedTopAppBarColors();
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors centerAlignedTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors centerAlignedTopAppBarColors();
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors centerAlignedTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarScrollBehavior enterAlwaysScrollBehavior(optional androidx.compose.material3.TopAppBarState state, optional kotlin.jvm.functions.Function0<java.lang.Boolean> canScroll, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float>? snapAnimationSpec, optional androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float>? flingAnimationSpec);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarScrollBehavior enterAlwaysScrollBehavior(optional androidx.compose.material3.TopAppBarState state, optional kotlin.jvm.functions.Function0<java.lang.Boolean> canScroll, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float>? snapAnimationSpec, optional androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float>? flingAnimationSpec, optional boolean reverseLayout);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarScrollBehavior exitUntilCollapsedScrollBehavior(optional androidx.compose.material3.TopAppBarState state, optional kotlin.jvm.functions.Function0<java.lang.Boolean> canScroll, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float>? snapAnimationSpec, optional androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float>? flingAnimationSpec);
     method public float getLargeAppBarCollapsedHeight();
     method public float getLargeAppBarExpandedHeight();
-    method public float getLargeAppBarWithSubtitleExpandedHeight();
-    method public float getLargeAppBarWithoutSubtitleExpandedHeight();
+    method public float getLargeFlexibleAppBarWithSubtitleExpandedHeight();
+    method public float getLargeFlexibleAppBarWithoutSubtitleExpandedHeight();
     method public float getMediumAppBarCollapsedHeight();
     method public float getMediumAppBarExpandedHeight();
-    method public float getMediumAppBarWithSubtitleExpandedHeight();
-    method public float getMediumAppBarWithoutSubtitleExpandedHeight();
+    method public float getMediumFlexibleAppBarWithSubtitleExpandedHeight();
+    method public float getMediumFlexibleAppBarWithoutSubtitleExpandedHeight();
     method public float getTopAppBarExpandedHeight();
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors largeTopAppBarColors();
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors largeTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors mediumTopAppBarColors();
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors mediumTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors largeTopAppBarColors();
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors largeTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors mediumTopAppBarColors();
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors mediumTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarScrollBehavior pinnedScrollBehavior(optional androidx.compose.material3.TopAppBarState state, optional kotlin.jvm.functions.Function0<java.lang.Boolean> canScroll);
     method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors topAppBarColors();
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors topAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors topAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors topAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor, optional long subtitleContentColor);
     property public final float LargeAppBarCollapsedHeight;
     property public final float LargeAppBarExpandedHeight;
-    property public final float LargeAppBarWithSubtitleExpandedHeight;
-    property public final float LargeAppBarWithoutSubtitleExpandedHeight;
+    property public final float LargeFlexibleAppBarWithSubtitleExpandedHeight;
+    property public final float LargeFlexibleAppBarWithoutSubtitleExpandedHeight;
     property public final float MediumAppBarCollapsedHeight;
     property public final float MediumAppBarExpandedHeight;
-    property public final float MediumAppBarWithSubtitleExpandedHeight;
-    property public final float MediumAppBarWithoutSubtitleExpandedHeight;
+    property public final float MediumFlexibleAppBarWithSubtitleExpandedHeight;
+    property public final float MediumFlexibleAppBarWithoutSubtitleExpandedHeight;
     property public final float TopAppBarExpandedHeight;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
     field public static final androidx.compose.material3.TopAppBarDefaults INSTANCE;
@@ -2986,19 +2993,6 @@
     property public final androidx.compose.runtime.saveable.Saver<androidx.compose.material3.TopAppBarState,? extends java.lang.Object?> Saver;
   }
 
-  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @kotlin.jvm.JvmInline public final value class TopAppBarTitleAlignment {
-    field public static final androidx.compose.material3.TopAppBarTitleAlignment.Companion Companion;
-  }
-
-  public static final class TopAppBarTitleAlignment.Companion {
-    method public int getCenter();
-    method public int getEnd();
-    method public int getStart();
-    property public final int Center;
-    property public final int End;
-    property public final int Start;
-  }
-
   @androidx.compose.runtime.Immutable public final class Typography {
     ctor @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public Typography();
     ctor public Typography(optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle headlineLarge, optional androidx.compose.ui.text.TextStyle headlineMedium, optional androidx.compose.ui.text.TextStyle headlineSmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall);
diff --git a/compose/material3/material3/api/restricted_current.txt b/compose/material3/material3/api/restricted_current.txt
index 98fd41b..9c465b2e 100644
--- a/compose/material3/material3/api/restricted_current.txt
+++ b/compose/material3/material3/api/restricted_current.txt
@@ -42,15 +42,15 @@
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static androidx.compose.material3.BottomAppBarState BottomAppBarState(float initialHeightOffsetLimit, float initialHeightOffset, float initialContentOffset);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void CenterAlignedTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void CenterAlignedTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void LargeFlexibleTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? subtitle, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.ui.Alignment.Horizontal titleHorizontalAlignment, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void LargeTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void LargeTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void LargeTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit>? subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional int titleHorizontalAlignment, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void MediumFlexibleTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? subtitle, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.ui.Alignment.Horizontal titleHorizontalAlignment, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void MediumTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void MediumTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void MediumTopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit>? subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional int titleHorizontalAlignment, optional float collapsedHeight, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit> subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional int titleHorizontalAlignment, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @androidx.compose.runtime.Composable public static void TopAppBar(kotlin.jvm.functions.Function0<kotlin.Unit> title, kotlin.jvm.functions.Function0<kotlin.Unit> subtitle, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit> navigationIcon, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> actions, optional androidx.compose.ui.Alignment.Horizontal titleHorizontalAlignment, optional float expandedHeight, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.TopAppBarColors colors, optional androidx.compose.material3.TopAppBarScrollBehavior? scrollBehavior);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.BottomAppBarState rememberBottomAppBarState(optional float initialHeightOffsetLimit, optional float initialHeightOffset, optional float initialContentOffset);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.TopAppBarState rememberTopAppBarState(optional float initialHeightOffsetLimit, optional float initialHeightOffset, optional float initialContentOffset);
   }
@@ -2200,13 +2200,16 @@
     method public void dispatchRawDelta(float delta);
     method public suspend Object? drag(androidx.compose.foundation.MutatePriority dragPriority, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.gestures.DragScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block, kotlin.coroutines.Continuation<? super kotlin.Unit>);
     method public float getCoercedValueAsFraction();
+    method public kotlin.jvm.functions.Function1<java.lang.Float,kotlin.Unit>? getOnValueChange();
     method public kotlin.jvm.functions.Function0<kotlin.Unit>? getOnValueChangeFinished();
     method public int getSteps();
     method public float getValue();
     method public kotlin.ranges.ClosedFloatingPointRange<java.lang.Float> getValueRange();
+    method public void setOnValueChange(kotlin.jvm.functions.Function1<? super java.lang.Float,kotlin.Unit>?);
     method public void setOnValueChangeFinished(kotlin.jvm.functions.Function0<kotlin.Unit>?);
     method public void setValue(float);
     property public final float coercedValueAsFraction;
+    property public final kotlin.jvm.functions.Function1<java.lang.Float,kotlin.Unit>? onValueChange;
     property public final kotlin.jvm.functions.Function0<kotlin.Unit>? onValueChangeFinished;
     property @IntRange(from=0L) public final int steps;
     property public final float value;
@@ -2900,51 +2903,55 @@
   }
 
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class TopAppBarColors {
-    ctor public TopAppBarColors(long containerColor, long scrolledContainerColor, long navigationIconContentColor, long titleContentColor, long actionIconContentColor);
-    method public androidx.compose.material3.TopAppBarColors copy(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    ctor @Deprecated public TopAppBarColors(long containerColor, long scrolledContainerColor, long navigationIconContentColor, long titleContentColor, long actionIconContentColor);
+    ctor public TopAppBarColors(long containerColor, long scrolledContainerColor, long navigationIconContentColor, long titleContentColor, long actionIconContentColor, long subtitleContentColor);
+    method public androidx.compose.material3.TopAppBarColors copy(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor, optional long subtitleContentColor);
     method public long getActionIconContentColor();
     method public long getContainerColor();
     method public long getNavigationIconContentColor();
     method public long getScrolledContainerColor();
+    method public long getSubtitleContentColor();
     method public long getTitleContentColor();
     property public final long actionIconContentColor;
     property public final long containerColor;
     property public final long navigationIconContentColor;
     property public final long scrolledContainerColor;
+    property public final long subtitleContentColor;
     property public final long titleContentColor;
   }
 
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public final class TopAppBarDefaults {
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors centerAlignedTopAppBarColors();
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors centerAlignedTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors centerAlignedTopAppBarColors();
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors centerAlignedTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
     method @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarScrollBehavior enterAlwaysScrollBehavior(optional androidx.compose.material3.TopAppBarState state, optional kotlin.jvm.functions.Function0<java.lang.Boolean> canScroll, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float>? snapAnimationSpec, optional androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float>? flingAnimationSpec);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarScrollBehavior enterAlwaysScrollBehavior(optional androidx.compose.material3.TopAppBarState state, optional kotlin.jvm.functions.Function0<java.lang.Boolean> canScroll, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float>? snapAnimationSpec, optional androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float>? flingAnimationSpec, optional boolean reverseLayout);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarScrollBehavior exitUntilCollapsedScrollBehavior(optional androidx.compose.material3.TopAppBarState state, optional kotlin.jvm.functions.Function0<java.lang.Boolean> canScroll, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float>? snapAnimationSpec, optional androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float>? flingAnimationSpec);
     method public float getLargeAppBarCollapsedHeight();
     method public float getLargeAppBarExpandedHeight();
-    method public float getLargeAppBarWithSubtitleExpandedHeight();
-    method public float getLargeAppBarWithoutSubtitleExpandedHeight();
+    method public float getLargeFlexibleAppBarWithSubtitleExpandedHeight();
+    method public float getLargeFlexibleAppBarWithoutSubtitleExpandedHeight();
     method public float getMediumAppBarCollapsedHeight();
     method public float getMediumAppBarExpandedHeight();
-    method public float getMediumAppBarWithSubtitleExpandedHeight();
-    method public float getMediumAppBarWithoutSubtitleExpandedHeight();
+    method public float getMediumFlexibleAppBarWithSubtitleExpandedHeight();
+    method public float getMediumFlexibleAppBarWithoutSubtitleExpandedHeight();
     method public float getTopAppBarExpandedHeight();
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors largeTopAppBarColors();
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors largeTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors mediumTopAppBarColors();
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors mediumTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors largeTopAppBarColors();
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors largeTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors mediumTopAppBarColors();
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors mediumTopAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
     method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarScrollBehavior pinnedScrollBehavior(optional androidx.compose.material3.TopAppBarState state, optional kotlin.jvm.functions.Function0<java.lang.Boolean> canScroll);
     method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors topAppBarColors();
-    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors topAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    method @Deprecated @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors topAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor);
+    method @androidx.compose.runtime.Composable public androidx.compose.material3.TopAppBarColors topAppBarColors(optional long containerColor, optional long scrolledContainerColor, optional long navigationIconContentColor, optional long titleContentColor, optional long actionIconContentColor, optional long subtitleContentColor);
     property public final float LargeAppBarCollapsedHeight;
     property public final float LargeAppBarExpandedHeight;
-    property public final float LargeAppBarWithSubtitleExpandedHeight;
-    property public final float LargeAppBarWithoutSubtitleExpandedHeight;
+    property public final float LargeFlexibleAppBarWithSubtitleExpandedHeight;
+    property public final float LargeFlexibleAppBarWithoutSubtitleExpandedHeight;
     property public final float MediumAppBarCollapsedHeight;
     property public final float MediumAppBarExpandedHeight;
-    property public final float MediumAppBarWithSubtitleExpandedHeight;
-    property public final float MediumAppBarWithoutSubtitleExpandedHeight;
+    property public final float MediumFlexibleAppBarWithSubtitleExpandedHeight;
+    property public final float MediumFlexibleAppBarWithoutSubtitleExpandedHeight;
     property public final float TopAppBarExpandedHeight;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
     field public static final androidx.compose.material3.TopAppBarDefaults INSTANCE;
@@ -2986,19 +2993,6 @@
     property public final androidx.compose.runtime.saveable.Saver<androidx.compose.material3.TopAppBarState,? extends java.lang.Object?> Saver;
   }
 
-  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi @kotlin.jvm.JvmInline public final value class TopAppBarTitleAlignment {
-    field public static final androidx.compose.material3.TopAppBarTitleAlignment.Companion Companion;
-  }
-
-  public static final class TopAppBarTitleAlignment.Companion {
-    method public int getCenter();
-    method public int getEnd();
-    method public int getStart();
-    property public final int Center;
-    property public final int End;
-    property public final int Start;
-  }
-
   @androidx.compose.runtime.Immutable public final class Typography {
     ctor @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3ExpressiveApi public Typography();
     ctor public Typography(optional androidx.compose.ui.text.TextStyle displayLarge, optional androidx.compose.ui.text.TextStyle displayMedium, optional androidx.compose.ui.text.TextStyle displaySmall, optional androidx.compose.ui.text.TextStyle headlineLarge, optional androidx.compose.ui.text.TextStyle headlineMedium, optional androidx.compose.ui.text.TextStyle headlineSmall, optional androidx.compose.ui.text.TextStyle titleLarge, optional androidx.compose.ui.text.TextStyle titleMedium, optional androidx.compose.ui.text.TextStyle titleSmall, optional androidx.compose.ui.text.TextStyle bodyLarge, optional androidx.compose.ui.text.TextStyle bodyMedium, optional androidx.compose.ui.text.TextStyle bodySmall, optional androidx.compose.ui.text.TextStyle labelLarge, optional androidx.compose.ui.text.TextStyle labelMedium, optional androidx.compose.ui.text.TextStyle labelSmall);
diff --git a/compose/material3/material3/build.gradle b/compose/material3/material3/build.gradle
index 153d2b4..c025935 100644
--- a/compose/material3/material3/build.gradle
+++ b/compose/material3/material3/build.gradle
@@ -111,6 +111,7 @@
                 implementation("androidx.compose.material:material-icons-core:1.7.5")
                 implementation(project(":test:screenshot:screenshot"))
                 implementation(project(":core:core"))
+                implementation(libs.espressoCore)
                 implementation(libs.testRules)
                 implementation(libs.testRunner)
                 implementation(libs.junit)
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
index 7bcb6d6..afd28629 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
@@ -76,8 +76,8 @@
 import androidx.compose.material3.samples.ExitAlwaysBottomAppBarSpacedAround
 import androidx.compose.material3.samples.ExitAlwaysBottomAppBarSpacedBetween
 import androidx.compose.material3.samples.ExitAlwaysBottomAppBarSpacedEvenly
-import androidx.compose.material3.samples.ExitUntilCollapsedCenterAlignedLargeTopAppBarWithSubtitle
-import androidx.compose.material3.samples.ExitUntilCollapsedCenterAlignedMediumTopAppBarWithSubtitle
+import androidx.compose.material3.samples.ExitUntilCollapsedCenterAlignedLargeFlexibleTopAppBar
+import androidx.compose.material3.samples.ExitUntilCollapsedCenterAlignedMediumFlexibleTopAppBar
 import androidx.compose.material3.samples.ExitUntilCollapsedLargeTopAppBar
 import androidx.compose.material3.samples.ExitUntilCollapsedMediumTopAppBar
 import androidx.compose.material3.samples.ExpandableHorizontalFloatingToolbarSample
@@ -817,11 +817,11 @@
             ExitUntilCollapsedMediumTopAppBar()
         },
         Example(
-            name = "ExitUntilCollapsedCenterAlignedMediumTopAppBarWithSubtitle",
+            name = "ExitUntilCollapsedCenterAlignedMediumFlexibleTopAppBar with subtitle",
             description = TopAppBarExampleDescription,
             sourceUrl = TopAppBarExampleSourceUrl,
         ) {
-            ExitUntilCollapsedCenterAlignedMediumTopAppBarWithSubtitle()
+            ExitUntilCollapsedCenterAlignedMediumFlexibleTopAppBar()
         },
         Example(
             name = "ExitUntilCollapsedLargeTopAppBar",
@@ -831,11 +831,11 @@
             ExitUntilCollapsedLargeTopAppBar()
         },
         Example(
-            name = "ExitUntilCollapsedCenterAlignedLargeTopAppBarWithSubtitle",
+            name = "ExitUntilCollapsedCenterAlignedLargeFlexibleTopAppBar with subtitle",
             description = TopAppBarExampleDescription,
             sourceUrl = TopAppBarExampleSourceUrl,
         ) {
-            ExitUntilCollapsedCenterAlignedLargeTopAppBarWithSubtitle()
+            ExitUntilCollapsedCenterAlignedLargeFlexibleTopAppBar()
         },
     )
 
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/AppBarSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/AppBarSamples.kt
index 20c9f6a..7d459ef 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/AppBarSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/AppBarSamples.kt
@@ -45,16 +45,18 @@
 import androidx.compose.material3.FloatingActionButtonDefaults
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
+import androidx.compose.material3.LargeFlexibleTopAppBar
 import androidx.compose.material3.LargeTopAppBar
 import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.MediumFlexibleTopAppBar
 import androidx.compose.material3.MediumTopAppBar
 import androidx.compose.material3.Scaffold
 import androidx.compose.material3.Text
 import androidx.compose.material3.TopAppBar
 import androidx.compose.material3.TopAppBarDefaults
-import androidx.compose.material3.TopAppBarTitleAlignment
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.platform.LocalContext
@@ -241,7 +243,7 @@
                     Text("Simple TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis)
                 },
                 subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
-                titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                titleHorizontalAlignment = Alignment.CenterHorizontally,
                 navigationIcon = {
                     IconButton(onClick = { /* doSomething() */ }) {
                         Icon(
@@ -448,24 +450,24 @@
 }
 
 /**
- * A sample for a [MediumTopAppBar] that collapses when the content is scrolled up, and appears when
- * the content is completely scrolled back down, centered with subtitle.
+ * A sample for a [MediumFlexibleTopAppBar] that collapses when the content is scrolled up, and
+ * appears when the content is completely scrolled back down, centered with subtitle.
  */
 @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
 @Preview
 @Sampled
 @Composable
-fun ExitUntilCollapsedCenterAlignedMediumTopAppBarWithSubtitle() {
+fun ExitUntilCollapsedCenterAlignedMediumFlexibleTopAppBar() {
     val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
     Scaffold(
         modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
         topBar = {
-            MediumTopAppBar(
+            MediumFlexibleTopAppBar(
                 title = {
                     Text("Medium TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis)
                 },
                 subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
-                titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                titleHorizontalAlignment = Alignment.CenterHorizontally,
                 navigationIcon = {
                     IconButton(onClick = { /* doSomething() */ }) {
                         Icon(
@@ -556,22 +558,22 @@
 }
 
 /**
- * A sample for a [LargeTopAppBar] that collapses when the content is scrolled up, and appears when
- * the content is completely scrolled back down, centered with subtitle.
+ * A sample for a [LargeFlexibleTopAppBar] that collapses when the content is scrolled up, and
+ * appears when the content is completely scrolled back down, centered with subtitle.
  */
 @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
 @Preview
 @Sampled
 @Composable
-fun ExitUntilCollapsedCenterAlignedLargeTopAppBarWithSubtitle() {
+fun ExitUntilCollapsedCenterAlignedLargeFlexibleTopAppBar() {
     val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
     Scaffold(
         modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
         topBar = {
-            LargeTopAppBar(
+            LargeFlexibleTopAppBar(
                 title = { Text("Large TopAppBar", maxLines = 1, overflow = TextOverflow.Ellipsis) },
                 subtitle = { Text("Subtitle", maxLines = 1, overflow = TextOverflow.Ellipsis) },
-                titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                titleHorizontalAlignment = Alignment.CenterHorizontally,
                 navigationIcon = {
                     IconButton(onClick = { /* doSomething() */ }) {
                         Icon(
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarScreenshotTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarScreenshotTest.kt
index 1ddb902..1a9d7b6 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarScreenshotTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarScreenshotTest.kt
@@ -33,8 +33,9 @@
 import androidx.compose.material.icons.filled.Menu
 import androidx.compose.material3.BottomAppBarDefaults.bottomAppBarFabColor
 import androidx.compose.material3.TopAppBarDefaults.enterAlwaysScrollBehavior
-import androidx.compose.material3.tokens.TopAppBarSmallTokens
+import androidx.compose.material3.tokens.AppBarSmallTokens
 import androidx.compose.testutils.assertAgainstGolden
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.platform.testTag
@@ -170,7 +171,7 @@
         composeTestRule.onNodeWithTag(TopAppBarTestTag).performTouchInput {
             // start from the bottom so we can drag enough
             down(bottomCenter - Offset(1f, 1f))
-            moveBy(Offset(0f, -((TopAppBarSmallTokens.ContainerHeight - 10.dp).toPx())))
+            moveBy(Offset(0f, -((AppBarSmallTokens.ContainerHeight - 10.dp).toPx())))
         }
 
         assertAppBarAgainstGolden(
@@ -245,7 +246,7 @@
                     },
                     title = { Text("Title") },
                     subtitle = { Text("Subtitle") },
-                    titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                    titleHorizontalAlignment = Alignment.CenterHorizontally,
                     actions = {
                         IconButton(onClick = { /* doSomething() */ }) {
                             Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
@@ -273,7 +274,7 @@
                     },
                     title = { Text("Title") },
                     subtitle = {},
-                    titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                    titleHorizontalAlignment = Alignment.CenterHorizontally,
                     actions = {
                         IconButton(onClick = { /* doSomething() */ }) {
                             Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
@@ -341,10 +342,10 @@
     }
 
     @Test
-    fun mediumAppBar_centerAligned_withSubtitle_lightTheme() {
+    fun mediumFlexibleAppBar_centerAligned_withSubtitle_lightTheme() {
         composeTestRule.setMaterialContent(lightColorScheme()) {
             Box(Modifier.testTag(TopAppBarTestTag)) {
-                MediumTopAppBar(
+                MediumFlexibleTopAppBar(
                     navigationIcon = {
                         IconButton(onClick = { /* doSomething() */ }) {
                             Icon(
@@ -355,7 +356,7 @@
                     },
                     title = { Text("Title") },
                     subtitle = { Text("Subtitle") },
-                    titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                    titleHorizontalAlignment = Alignment.CenterHorizontally,
                     actions = {
                         IconButton(onClick = { /* doSomething() */ }) {
                             Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
@@ -366,15 +367,15 @@
         }
 
         assertAppBarAgainstGolden(
-            goldenIdentifier = "mediumAppBar_centerAligned_withSubtitle_lightTheme"
+            goldenIdentifier = "mediumFlexibleAppBar_centerAligned_withSubtitle_lightTheme"
         )
     }
 
     @Test
-    fun mediumAppBar_centerAligned_withoutSubtitle_lightTheme() {
+    fun mediumFlexibleAppBar_centerAligned_withoutSubtitle_lightTheme() {
         composeTestRule.setMaterialContent(lightColorScheme()) {
             Box(Modifier.testTag(TopAppBarTestTag)) {
-                MediumTopAppBar(
+                MediumFlexibleTopAppBar(
                     navigationIcon = {
                         IconButton(onClick = { /* doSomething() */ }) {
                             Icon(
@@ -384,8 +385,7 @@
                         }
                     },
                     title = { Text("Title") },
-                    subtitle = null,
-                    titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                    titleHorizontalAlignment = Alignment.CenterHorizontally,
                     actions = {
                         IconButton(onClick = { /* doSomething() */ }) {
                             Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
@@ -396,15 +396,15 @@
         }
 
         assertAppBarAgainstGolden(
-            goldenIdentifier = "mediumAppBar_centerAligned_withoutSubtitle_lightTheme"
+            goldenIdentifier = "mediumFlexibleAppBar_centerAligned_withoutSubtitle_lightTheme"
         )
     }
 
     @Test
-    fun mediumAppBar_startAligned_withSubtitle_darkTheme() {
+    fun mediumFlexibleAppBar_startAligned_withSubtitle_darkTheme() {
         composeTestRule.setMaterialContent(darkColorScheme()) {
             Box(Modifier.testTag(TopAppBarTestTag)) {
-                MediumTopAppBar(
+                MediumFlexibleTopAppBar(
                     navigationIcon = {
                         IconButton(onClick = { /* doSomething() */ }) {
                             Icon(
@@ -425,7 +425,7 @@
         }
 
         assertAppBarAgainstGolden(
-            goldenIdentifier = "mediumAppBar_startAligned_withSubtitle_darkTheme"
+            goldenIdentifier = "mediumFlexibleAppBar_startAligned_withSubtitle_darkTheme"
         )
     }
 
@@ -482,10 +482,10 @@
     }
 
     @Test
-    fun largeAppBar_centerAligned_withSubtitle_lightTheme() {
+    fun largeFlexibleAppBar_centerAligned_withSubtitle_lightTheme() {
         composeTestRule.setMaterialContent(lightColorScheme()) {
             Box(Modifier.testTag(TopAppBarTestTag)) {
-                LargeTopAppBar(
+                LargeFlexibleTopAppBar(
                     navigationIcon = {
                         IconButton(onClick = { /* doSomething() */ }) {
                             Icon(
@@ -496,7 +496,7 @@
                     },
                     title = { Text("Title") },
                     subtitle = { Text("Subtitle") },
-                    titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                    titleHorizontalAlignment = Alignment.CenterHorizontally,
                     actions = {
                         IconButton(onClick = { /* doSomething() */ }) {
                             Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
@@ -507,15 +507,15 @@
         }
 
         assertAppBarAgainstGolden(
-            goldenIdentifier = "largeAppBar_centerAligned_withSubtitle_lightTheme"
+            goldenIdentifier = "largeFlexibleAppBar_centerAligned_withSubtitle_lightTheme"
         )
     }
 
     @Test
-    fun largeAppBar_centerAligned_withoutSubtitle_lightTheme() {
+    fun largeFlexibleAppBar_centerAligned_withoutSubtitle_lightTheme() {
         composeTestRule.setMaterialContent(lightColorScheme()) {
             Box(Modifier.testTag(TopAppBarTestTag)) {
-                LargeTopAppBar(
+                LargeFlexibleTopAppBar(
                     navigationIcon = {
                         IconButton(onClick = { /* doSomething() */ }) {
                             Icon(
@@ -525,8 +525,7 @@
                         }
                     },
                     title = { Text("Title") },
-                    subtitle = null,
-                    titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+                    titleHorizontalAlignment = Alignment.CenterHorizontally,
                     actions = {
                         IconButton(onClick = { /* doSomething() */ }) {
                             Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Like")
@@ -537,15 +536,15 @@
         }
 
         assertAppBarAgainstGolden(
-            goldenIdentifier = "largeAppBar_centerAligned_withoutSubtitle_lightTheme"
+            goldenIdentifier = "largeFlexibleAppBar_centerAligned_withoutSubtitle_lightTheme"
         )
     }
 
     @Test
-    fun largeAppBar_startAligned_withSubtitle_darkTheme() {
+    fun largeFlexibleAppBar_startAligned_withSubtitle_darkTheme() {
         composeTestRule.setMaterialContent(darkColorScheme()) {
             Box(Modifier.testTag(TopAppBarTestTag)) {
-                LargeTopAppBar(
+                LargeFlexibleTopAppBar(
                     navigationIcon = {
                         IconButton(onClick = { /* doSomething() */ }) {
                             Icon(
@@ -566,7 +565,7 @@
         }
 
         assertAppBarAgainstGolden(
-            goldenIdentifier = "largeAppBar_startAligned_withSubtitle_darkTheme"
+            goldenIdentifier = "largeFlexibleAppBar_startAligned_withSubtitle_darkTheme"
         )
     }
 
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarTest.kt
index 1beef40..ba662e3 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/AppBarTest.kt
@@ -39,11 +39,11 @@
 import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Add
+import androidx.compose.material3.tokens.AppBarLargeTokens
+import androidx.compose.material3.tokens.AppBarMediumTokens
+import androidx.compose.material3.tokens.AppBarSmallTokens
+import androidx.compose.material3.tokens.AppBarTokens
 import androidx.compose.material3.tokens.BottomAppBarTokens
-import androidx.compose.material3.tokens.TopAppBarLargeTokens
-import androidx.compose.material3.tokens.TopAppBarMediumTokens
-import androidx.compose.material3.tokens.TopAppBarSmallCenteredTokens
-import androidx.compose.material3.tokens.TopAppBarSmallTokens
 import androidx.compose.material3.tokens.TypographyKeyTokens
 import androidx.compose.runtime.Composable
 import androidx.compose.testutils.assertContainsColor
@@ -106,7 +106,7 @@
     fun smallTopAppBar_expandsToScreen() {
         rule
             .setMaterialContentForSizeAssertions { TopAppBar(title = { Text("Title") }) }
-            .assertHeightIsEqualTo(TopAppBarSmallTokens.ContainerHeight)
+            .assertHeightIsEqualTo(AppBarSmallTokens.ContainerHeight)
             .assertWidthIsEqualTo(rule.rootWidth())
     }
 
@@ -130,6 +130,27 @@
         rule.onNodeWithText(subtitle).assertIsDisplayed()
     }
 
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun smallTopAppBar_withSubtitleAndCustomColors() {
+        val subtitle = "Subtitle"
+        rule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.testTag(TopAppBarTestTag)) {
+                TopAppBar(
+                    title = { Text("Title", modifier = Modifier.testTag(TitleTestTag)) },
+                    subtitle = { Text(subtitle, modifier = Modifier.testTag(SubtitleTestTag)) },
+                    colors =
+                        TopAppBarDefaults.topAppBarColors(
+                            titleContentColor = Color.Red,
+                            subtitleContentColor = Color.Green
+                        )
+                )
+            }
+        }
+        rule.onNodeWithTag(TitleTestTag).captureToImage().assertContainsColor(Color.Red)
+        rule.onNodeWithTag(SubtitleTestTag).captureToImage().assertContainsColor(Color.Green)
+    }
+
     @Test
     fun smallTopAppBar_default_positioning() {
         rule.setMaterialContent(lightColorScheme()) {
@@ -166,7 +187,7 @@
                 title = {
                     Text("Title")
                     textStyle = LocalTextStyle.current
-                    expectedTextStyle = TopAppBarSmallTokens.HeadlineFont.value
+                    expectedTextStyle = AppBarSmallTokens.TitleFont.value
                 }
             )
         }
@@ -297,7 +318,7 @@
         rule.waitForIdle()
         rule
             .onNodeWithTag(TopAppBarTestTag)
-            .assertHeightIsEqualTo(TopAppBarSmallTokens.ContainerHeight - scrollHeightOffsetDp)
+            .assertHeightIsEqualTo(AppBarSmallTokens.ContainerHeight - scrollHeightOffsetDp)
     }
 
     @OptIn(ExperimentalMaterial3Api::class)
@@ -379,7 +400,7 @@
             .setMaterialContentForSizeAssertions {
                 CenterAlignedTopAppBar(title = { Text("Title") })
             }
-            .assertHeightIsEqualTo(TopAppBarSmallCenteredTokens.ContainerHeight)
+            .assertHeightIsEqualTo(AppBarSmallTokens.ContainerHeight)
             .assertWidthIsEqualTo(rule.rootWidth())
     }
 
@@ -516,7 +537,7 @@
                 title = {
                     Text("Title")
                     textStyle = LocalTextStyle.current
-                    expectedTextStyle = TopAppBarSmallCenteredTokens.HeadlineFont.value
+                    expectedTextStyle = AppBarSmallTokens.TitleFont.value
                 }
             )
         }
@@ -579,23 +600,22 @@
                     FakeIcon(Modifier.testTag(NavigationIconTestTag))
                     navigationIconColor = LocalContentColor.current
                     expectedNavigationIconColor =
-                        TopAppBarDefaults.centerAlignedTopAppBarColors().navigationIconContentColor
+                        TopAppBarDefaults.topAppBarColors().navigationIconContentColor
                     // fraction = 0f to indicate no scroll.
                     expectedContainerColor =
-                        TopAppBarDefaults.centerAlignedTopAppBarColors()
+                        TopAppBarDefaults.topAppBarColors()
                             .containerColor(colorTransitionFraction = 0f)
                 },
                 title = {
                     Text("Title", Modifier.testTag(TitleTestTag))
                     titleColor = LocalContentColor.current
-                    expectedTitleColor =
-                        TopAppBarDefaults.centerAlignedTopAppBarColors().titleContentColor
+                    expectedTitleColor = TopAppBarDefaults.topAppBarColors().titleContentColor
                 },
                 actions = {
                     FakeIcon(Modifier.testTag(ActionsTestTag))
                     actionsColor = LocalContentColor.current
                     expectedActionsColor =
-                        TopAppBarDefaults.centerAlignedTopAppBarColors().actionIconContentColor
+                        TopAppBarDefaults.topAppBarColors().actionIconContentColor
                 }
             )
         }
@@ -627,7 +647,7 @@
                     Text("Title", Modifier.testTag(TitleTestTag))
                     // fraction = 1f to indicate a scroll.
                     expectedScrolledContainerColor =
-                        TopAppBarDefaults.centerAlignedTopAppBarColors()
+                        TopAppBarDefaults.topAppBarColors()
                             .containerColor(colorTransitionFraction = 1f)
                 },
                 scrollBehavior = scrollBehavior
@@ -649,7 +669,7 @@
             .setMaterialContentForSizeAssertions {
                 MediumTopAppBar(title = { Text("Medium Title") })
             }
-            .assertHeightIsEqualTo(TopAppBarMediumTokens.ContainerHeight)
+            .assertHeightIsEqualTo(AppBarMediumTokens.ContainerHeight)
             .assertWidthIsEqualTo(rule.rootWidth())
     }
 
@@ -667,8 +687,8 @@
 
         // The bottom text baseline should be 24.dp from the bottom of the app bar.
         assertMediumOrLargeDefaultPositioning(
-            appBarCollapsedHeight = TopAppBarSmallTokens.ContainerHeight,
-            appBarExpandedHeight = TopAppBarMediumTokens.ContainerHeight,
+            appBarCollapsedHeight = AppBarSmallTokens.ContainerHeight,
+            appBarExpandedHeight = AppBarMediumTokens.ContainerHeight,
             bottomTextPadding = 24.dp
         )
     }
@@ -698,7 +718,7 @@
     }
 
     @Test
-    fun mediumTopAppBar_fitsTextIfHeightTooSmall_expanded() {
+    fun mediumFlexibleTopAppBar_fitsTextIfHeightTooSmall_expanded() {
         lateinit var scrollBehavior: TopAppBarScrollBehavior
         val collapsedHeightDp = TopAppBarDefaults.MediumAppBarCollapsedHeight
         val expandedHeightDp = TopAppBarDefaults.MediumAppBarCollapsedHeight
@@ -706,7 +726,7 @@
         rule.setMaterialContent(lightColorScheme()) {
             scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
             Box(Modifier.testTag(TopAppBarTestTag)) {
-                MediumTopAppBar(
+                MediumFlexibleTopAppBar(
                     navigationIcon = { FakeIcon(Modifier.testTag(NavigationIconTestTag)) },
                     title = { Text("Title", Modifier.testTag(TitleTestTag)) },
                     subtitle = { Text("Subtitle", Modifier.testTag(SubtitleTestTag)) },
@@ -728,17 +748,17 @@
     }
 
     @Test
-    fun mediumTopAppBar_fitsTextIfHeightTooSmall_collapsed() {
+    fun mediumFlexibleTopAppBar_fitsTextIfHeightTooSmall_collapsed() {
         lateinit var scrollBehavior: TopAppBarScrollBehavior
         val collapsedHeightDp = 0.dp
-        val expandedHeightDp = TopAppBarDefaults.MediumAppBarWithSubtitleExpandedHeight
+        val expandedHeightDp = TopAppBarDefaults.MediumFlexibleAppBarWithSubtitleExpandedHeight
         var expandedHeightPx = 0
 
         rule.setMaterialContent(lightColorScheme()) {
             scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
             expandedHeightPx = with(LocalDensity.current) { expandedHeightDp.roundToPx() }
             Box(Modifier.testTag(TopAppBarTestTag)) {
-                MediumTopAppBar(
+                MediumFlexibleTopAppBar(
                     navigationIcon = { FakeIcon(Modifier.testTag(NavigationIconTestTag)) },
                     title = { Text("Title", Modifier.testTag(TitleTestTag)) },
                     subtitle = { Text("Subtitle", Modifier.testTag(SubtitleTestTag)) },
@@ -781,8 +801,8 @@
                 }
             }
         assertMediumOrLargeScrolledHeight(
-            TopAppBarMediumTokens.ContainerHeight,
-            TopAppBarSmallTokens.ContainerHeight,
+            AppBarMediumTokens.ContainerHeight,
+            AppBarSmallTokens.ContainerHeight,
             windowInsets,
             content
         )
@@ -828,8 +848,8 @@
             }
 
         assertMediumOrLargeScrolledColors(
-            appBarMaxHeight = TopAppBarMediumTokens.ContainerHeight,
-            appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
+            appBarMaxHeight = AppBarMediumTokens.ContainerHeight,
+            appBarMinHeight = AppBarSmallTokens.ContainerHeight,
             titleContentColor = Color.Unspecified,
             subtitleContentColor = Color.Unspecified,
             content = content
@@ -850,8 +870,8 @@
                 )
             }
         assertMediumOrLargeScrolledColors(
-            appBarMaxHeight = TopAppBarMediumTokens.ContainerHeight,
-            appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
+            appBarMaxHeight = AppBarMediumTokens.ContainerHeight,
+            appBarMinHeight = AppBarSmallTokens.ContainerHeight,
             titleContentColor = Color.Green,
             subtitleContentColor = Color.Unspecified,
             content = content
@@ -860,10 +880,10 @@
 
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     @Test
-    fun mediumTopAppBar_scrolledColorsWithCustomTitleAndSubtitleTextColor() {
+    fun mediumFlexibleTopAppBar_scrolledColorsWithCustomTitleAndSubtitleTextColor() {
         val content =
             @Composable { scrollBehavior: TopAppBarScrollBehavior? ->
-                MediumTopAppBar(
+                MediumFlexibleTopAppBar(
                     modifier = Modifier.testTag(TopAppBarTestTag),
                     title = {
                         Text(text = "Title", Modifier.testTag(TitleTestTag), color = Color.Green)
@@ -879,8 +899,8 @@
                 )
             }
         assertMediumOrLargeScrolledColors(
-            appBarMaxHeight = TopAppBarDefaults.MediumAppBarWithSubtitleExpandedHeight,
-            appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
+            appBarMaxHeight = TopAppBarDefaults.MediumFlexibleAppBarWithSubtitleExpandedHeight,
+            appBarMinHeight = AppBarSmallTokens.ContainerHeight,
             titleContentColor = Color.Green,
             subtitleContentColor = Color.Green,
             content = content
@@ -889,10 +909,10 @@
 
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     @Test
-    fun mediumTopAppBar_scrolledColorsWithCustomTitleAndWithoutSubtitleTextColor() {
+    fun mediumFlexibleTopAppBar_scrolledColorsWithCustomTitleAndWithoutSubtitleTextColor() {
         val content =
             @Composable { scrollBehavior: TopAppBarScrollBehavior? ->
-                MediumTopAppBar(
+                MediumFlexibleTopAppBar(
                     modifier = Modifier.testTag(TopAppBarTestTag),
                     title = {
                         Text(text = "Title", Modifier.testTag(TitleTestTag), color = Color.Green)
@@ -902,8 +922,8 @@
                 )
             }
         assertMediumOrLargeScrolledColors(
-            appBarMaxHeight = TopAppBarDefaults.MediumAppBarWithoutSubtitleExpandedHeight,
-            appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
+            appBarMaxHeight = TopAppBarDefaults.MediumFlexibleAppBarWithoutSubtitleExpandedHeight,
+            appBarMinHeight = AppBarSmallTokens.ContainerHeight,
             titleContentColor = Color.Green,
             subtitleContentColor = Color.Unspecified,
             content = content
@@ -911,21 +931,23 @@
     }
 
     @Test
-    fun mediumTopAppBarColors_noNameParams() {
+    fun topAppBarColors_noNameParams() {
         rule.setContent {
             val colors =
-                TopAppBarDefaults.mediumTopAppBarColors(
+                TopAppBarDefaults.topAppBarColors(
                     Color.Blue,
                     Color.Green,
                     Color.Red,
                     Color.Yellow,
-                    Color.Cyan
+                    Color.Cyan,
+                    Color.Magenta
                 )
             assert(colors.containerColor == Color.Blue)
             assert(colors.scrolledContainerColor == Color.Green)
             assert(colors.navigationIconContentColor == Color.Red)
             assert(colors.titleContentColor == Color.Yellow)
             assert(colors.actionIconContentColor == Color.Cyan)
+            assert(colors.subtitleContentColor == Color.Magenta)
         }
     }
 
@@ -942,8 +964,8 @@
             }
 
         assertMediumOrLargeScrolledSemantics(
-            TopAppBarMediumTokens.ContainerHeight,
-            TopAppBarSmallTokens.ContainerHeight,
+            AppBarMediumTokens.ContainerHeight,
+            AppBarSmallTokens.ContainerHeight,
             content,
             withSubtitle = false
         )
@@ -951,10 +973,10 @@
 
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     @Test
-    fun mediumTopAppBar_withSubtitle_semantics() {
+    fun mediumFlexibleTopAppBar_withSubtitle_semantics() {
         val content =
             @Composable { scrollBehavior: TopAppBarScrollBehavior? ->
-                MediumTopAppBar(
+                MediumFlexibleTopAppBar(
                     modifier = Modifier.testTag(TopAppBarTestTag),
                     title = { Text("Title", Modifier.testTag(TitleTestTag)) },
                     subtitle = { Text("Subtitle", Modifier.testTag(SubtitleTestTag)) },
@@ -963,8 +985,8 @@
             }
 
         assertMediumOrLargeScrolledSemantics(
-            TopAppBarMediumTokens.ContainerHeight,
-            TopAppBarSmallTokens.ContainerHeight,
+            AppBarMediumTokens.ContainerHeight,
+            AppBarSmallTokens.ContainerHeight,
             content,
             withSubtitle = true
         )
@@ -982,8 +1004,8 @@
                 )
             }
         assertMediumOrLargeScrolledSemantics(
-            TopAppBarLargeTokens.ContainerHeight,
-            TopAppBarSmallTokens.ContainerHeight,
+            AppBarLargeTokens.ContainerHeight,
+            AppBarSmallTokens.ContainerHeight,
             content,
             withSubtitle = false
         )
@@ -991,10 +1013,10 @@
 
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     @Test
-    fun largeTopAppBar_withSubtitle_semantics() {
+    fun largeFlexibleTopAppBar_withSubtitle_semantics() {
         val content =
             @Composable { scrollBehavior: TopAppBarScrollBehavior? ->
-                LargeTopAppBar(
+                LargeFlexibleTopAppBar(
                     modifier = Modifier.testTag(TopAppBarTestTag),
                     title = { Text("Title", Modifier.testTag(TitleTestTag)) },
                     subtitle = { Text("Subtitle", Modifier.testTag(SubtitleTestTag)) },
@@ -1002,8 +1024,8 @@
                 )
             }
         assertMediumOrLargeScrolledSemantics(
-            TopAppBarLargeTokens.ContainerHeight,
-            TopAppBarSmallTokens.ContainerHeight,
+            AppBarLargeTokens.ContainerHeight,
+            AppBarSmallTokens.ContainerHeight,
             content,
             withSubtitle = true
         )
@@ -1013,7 +1035,7 @@
     fun largeTopAppBar_expandsToScreen() {
         rule
             .setMaterialContentForSizeAssertions { LargeTopAppBar(title = { Text("Large Title") }) }
-            .assertHeightIsEqualTo(TopAppBarLargeTokens.ContainerHeight)
+            .assertHeightIsEqualTo(AppBarLargeTokens.ContainerHeight)
             .assertWidthIsEqualTo(rule.rootWidth())
     }
 
@@ -1031,8 +1053,8 @@
 
         // The bottom text baseline should be 28.dp from the bottom of the app bar.
         assertMediumOrLargeDefaultPositioning(
-            appBarCollapsedHeight = TopAppBarSmallTokens.ContainerHeight,
-            appBarExpandedHeight = TopAppBarLargeTokens.ContainerHeight,
+            appBarCollapsedHeight = AppBarSmallTokens.ContainerHeight,
+            appBarExpandedHeight = AppBarLargeTokens.ContainerHeight,
             bottomTextPadding = 28.dp
         )
     }
@@ -1062,7 +1084,7 @@
     }
 
     @Test
-    fun largeTopAppBar_fitsTextIfHeightTooSmall_expanded() {
+    fun largeFlexibleTopAppBar_fitsTextIfHeightTooSmall_expanded() {
         lateinit var scrollBehavior: TopAppBarScrollBehavior
         val collapsedHeightDp = TopAppBarDefaults.LargeAppBarCollapsedHeight
         val expandedHeightDp = TopAppBarDefaults.LargeAppBarCollapsedHeight
@@ -1070,7 +1092,7 @@
         rule.setMaterialContent(lightColorScheme()) {
             scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
             Box(Modifier.testTag(TopAppBarTestTag)) {
-                LargeTopAppBar(
+                LargeFlexibleTopAppBar(
                     navigationIcon = { FakeIcon(Modifier.testTag(NavigationIconTestTag)) },
                     title = { Text("Title", Modifier.testTag(TitleTestTag)) },
                     subtitle = { Text("Subtitle", Modifier.testTag(SubtitleTestTag)) },
@@ -1092,17 +1114,17 @@
     }
 
     @Test
-    fun largeTopAppBar_fitsTextIfHeightTooSmall_collapsed() {
+    fun largeFlexibleTopAppBar_fitsTextIfHeightTooSmall_collapsed() {
         lateinit var scrollBehavior: TopAppBarScrollBehavior
         val collapsedHeightDp = 0.dp
-        val expandedHeightDp = TopAppBarDefaults.LargeAppBarWithSubtitleExpandedHeight
+        val expandedHeightDp = TopAppBarDefaults.LargeFlexibleAppBarWithSubtitleExpandedHeight
         var expandedHeightPx = 0
 
         rule.setMaterialContent(lightColorScheme()) {
             scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
             expandedHeightPx = with(LocalDensity.current) { expandedHeightDp.roundToPx() }
             Box(Modifier.testTag(TopAppBarTestTag)) {
-                LargeTopAppBar(
+                LargeFlexibleTopAppBar(
                     navigationIcon = { FakeIcon(Modifier.testTag(NavigationIconTestTag)) },
                     title = { Text("Title", Modifier.testTag(TitleTestTag)) },
                     subtitle = { Text("Subtitle", Modifier.testTag(SubtitleTestTag)) },
@@ -1145,8 +1167,8 @@
                 }
             }
         assertMediumOrLargeScrolledHeight(
-            TopAppBarLargeTokens.ContainerHeight,
-            TopAppBarSmallTokens.ContainerHeight,
+            AppBarLargeTokens.ContainerHeight,
+            AppBarSmallTokens.ContainerHeight,
             windowInsets,
             content
         )
@@ -1191,8 +1213,8 @@
                 )
             }
         assertMediumOrLargeScrolledColors(
-            appBarMaxHeight = TopAppBarLargeTokens.ContainerHeight,
-            appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
+            appBarMaxHeight = AppBarLargeTokens.ContainerHeight,
+            appBarMinHeight = AppBarSmallTokens.ContainerHeight,
             titleContentColor = Color.Unspecified,
             subtitleContentColor = Color.Unspecified,
             content = content
@@ -1213,8 +1235,8 @@
                 )
             }
         assertMediumOrLargeScrolledColors(
-            appBarMaxHeight = TopAppBarLargeTokens.ContainerHeight,
-            appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
+            appBarMaxHeight = AppBarLargeTokens.ContainerHeight,
+            appBarMinHeight = AppBarSmallTokens.ContainerHeight,
             titleContentColor = Color.Red,
             subtitleContentColor = Color.Unspecified,
             content = content
@@ -1223,10 +1245,10 @@
 
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     @Test
-    fun largeTopAppBar_scrolledColorsWithCustomTitleAndSubtitleTextColor() {
+    fun largeFlexibleTopAppBar_scrolledColorsWithCustomTitleAndSubtitleTextColor() {
         val content =
             @Composable { scrollBehavior: TopAppBarScrollBehavior? ->
-                LargeTopAppBar(
+                LargeFlexibleTopAppBar(
                     modifier = Modifier.testTag(TopAppBarTestTag),
                     title = {
                         Text(text = "Title", Modifier.testTag(TitleTestTag), color = Color.Red)
@@ -1242,8 +1264,8 @@
                 )
             }
         assertMediumOrLargeScrolledColors(
-            appBarMaxHeight = TopAppBarDefaults.LargeAppBarWithSubtitleExpandedHeight,
-            appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
+            appBarMaxHeight = TopAppBarDefaults.LargeFlexibleAppBarWithSubtitleExpandedHeight,
+            appBarMinHeight = AppBarSmallTokens.ContainerHeight,
             titleContentColor = Color.Red,
             subtitleContentColor = Color.Red,
             content = content
@@ -1252,21 +1274,20 @@
 
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     @Test
-    fun largeTopAppBar_scrolledColorsWithCustomTitleAndWithoutSubtitleTextColor() {
+    fun largeFlexibleTopAppBar_scrolledColorsWithCustomTitleAndWithoutSubtitleTextColor() {
         val content =
             @Composable { scrollBehavior: TopAppBarScrollBehavior? ->
-                LargeTopAppBar(
+                LargeFlexibleTopAppBar(
                     modifier = Modifier.testTag(TopAppBarTestTag),
                     title = {
                         Text(text = "Title", Modifier.testTag(TitleTestTag), color = Color.Red)
                     },
-                    subtitle = null,
                     scrollBehavior = scrollBehavior,
                 )
             }
         assertMediumOrLargeScrolledColors(
-            appBarMaxHeight = TopAppBarDefaults.LargeAppBarWithoutSubtitleExpandedHeight,
-            appBarMinHeight = TopAppBarSmallTokens.ContainerHeight,
+            appBarMaxHeight = TopAppBarDefaults.LargeFlexibleAppBarWithoutSubtitleExpandedHeight,
+            appBarMinHeight = AppBarSmallTokens.ContainerHeight,
             titleContentColor = Color.Red,
             subtitleContentColor = Color.Unspecified,
             content = content
@@ -1333,7 +1354,7 @@
 
         rule
             .onNodeWithTag(TopAppBarTestTag)
-            .assertHeightIsEqualTo(TopAppBarSmallTokens.ContainerHeight)
+            .assertHeightIsEqualTo(AppBarSmallTokens.ContainerHeight)
 
         // Drag the app bar up half its height.
         rule.onNodeWithTag(TopAppBarTestTag).performTouchInput {
@@ -1344,7 +1365,7 @@
         // Check that the app bar did not collapse.
         rule
             .onNodeWithTag(TopAppBarTestTag)
-            .assertHeightIsEqualTo(TopAppBarSmallTokens.ContainerHeight)
+            .assertHeightIsEqualTo(AppBarSmallTokens.ContainerHeight)
     }
 
     @Test
@@ -1359,7 +1380,7 @@
 
         rule
             .onNodeWithTag(TopAppBarTestTag)
-            .assertHeightIsEqualTo(TopAppBarMediumTokens.ContainerHeight)
+            .assertHeightIsEqualTo(AppBarMediumTokens.ContainerHeight)
 
         // Drag up the app bar.
         rule.onNodeWithTag(TopAppBarTestTag).performTouchInput {
@@ -1368,10 +1389,10 @@
         }
         rule.waitForIdle()
         // Check that the app bar collapsed to its small size constraints (i.e.
-        // TopAppBarSmallTokens.ContainerHeight).
+        // AppBarSmallTokens.ContainerHeight).
         rule
             .onNodeWithTag(TopAppBarTestTag)
-            .assertHeightIsEqualTo(TopAppBarSmallTokens.ContainerHeight)
+            .assertHeightIsEqualTo(AppBarSmallTokens.ContainerHeight)
     }
 
     @Test
@@ -1386,7 +1407,7 @@
 
         rule
             .onNodeWithTag(TopAppBarTestTag)
-            .assertHeightIsEqualTo(TopAppBarLargeTokens.ContainerHeight)
+            .assertHeightIsEqualTo(AppBarLargeTokens.ContainerHeight)
 
         // Slightly drag up the app bar.
         rule.onNodeWithTag(TopAppBarTestTag).performTouchInput {
@@ -1399,7 +1420,7 @@
         // Check that the app bar returned to its expanded size (i.e. fully expanded).
         rule
             .onNodeWithTag(TopAppBarTestTag)
-            .assertHeightIsEqualTo(TopAppBarLargeTokens.ContainerHeight)
+            .assertHeightIsEqualTo(AppBarLargeTokens.ContainerHeight)
 
         // Drag up the app bar to the point it should continue to collapse after.
         rule.onNodeWithTag(TopAppBarTestTag).performTouchInput {
@@ -1410,10 +1431,10 @@
         rule.waitForIdle()
 
         // Check that the app bar collapsed to its small size constraints (i.e.
-        // TopAppBarSmallTokens.ContainerHeight).
+        // AppBarSmallTokens.ContainerHeight).
         rule
             .onNodeWithTag(TopAppBarTestTag)
-            .assertHeightIsEqualTo(TopAppBarSmallTokens.ContainerHeight)
+            .assertHeightIsEqualTo(AppBarSmallTokens.ContainerHeight)
     }
 
     @Test
@@ -1429,7 +1450,7 @@
 
         // Check that the app bar stayed at its position (i.e. its bounds are with a smaller height)
         val boundsBefore = rule.onNodeWithTag(TopAppBarTestTag).getBoundsInRoot()
-        TopAppBarLargeTokens.ContainerHeight.assertIsEqualTo(
+        AppBarLargeTokens.ContainerHeight.assertIsEqualTo(
             expected = boundsBefore.height,
             subject = "container height"
         )
@@ -1444,8 +1465,8 @@
         // Check that the app bar did not snap back to its fully expanded height, or collapsed to
         // its collapsed height.
         val boundsAfter = rule.onNodeWithTag(TopAppBarTestTag).getBoundsInRoot()
-        assertThat(TopAppBarLargeTokens.ContainerHeight).isGreaterThan(boundsAfter.height)
-        assertThat(TopAppBarSmallTokens.ContainerHeight).isLessThan(boundsAfter.height)
+        assertThat(AppBarLargeTokens.ContainerHeight).isGreaterThan(boundsAfter.height)
+        assertThat(AppBarSmallTokens.ContainerHeight).isLessThan(boundsAfter.height)
     }
 
     @Test
@@ -1456,7 +1477,7 @@
         rule.setMaterialContentForSizeAssertions {
             scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
             state = rememberLazyListState()
-            appBarHeightPx = with(rule.density) { TopAppBarSmallTokens.ContainerHeight.toPx() }
+            appBarHeightPx = with(rule.density) { AppBarSmallTokens.ContainerHeight.toPx() }
             Scaffold(
                 modifier = Modifier.fillMaxSize().consumeWindowInsets(WindowInsets.systemBars),
                 topBar = { TopAppBar(title = { Text("Title") }, scrollBehavior = scrollBehavior) },
@@ -1502,7 +1523,7 @@
         rule
             .onNodeWithText("Item $trackedItemIndex")
             .assertTopPositionInRootIsEqualTo(
-                trackedItemTopBeforeExpansion + TopAppBarSmallTokens.ContainerHeight
+                trackedItemTopBeforeExpansion + AppBarSmallTokens.ContainerHeight
             )
     }
 
@@ -1515,7 +1536,7 @@
         rule.setMaterialContentForSizeAssertions {
             scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(reverseLayout = true)
             state = rememberLazyListState()
-            appBarHeightPx = with(rule.density) { TopAppBarSmallTokens.ContainerHeight.toPx() }
+            appBarHeightPx = with(rule.density) { AppBarSmallTokens.ContainerHeight.toPx() }
             Scaffold(
                 modifier = Modifier.fillMaxSize().consumeWindowInsets(WindowInsets.systemBars),
                 topBar = {
@@ -2151,7 +2172,8 @@
      *
      * @param appBarMaxHeight the max height of the app bar [content]
      * @param appBarMinHeight the min height of the app bar [content]
-     * @param content a Composable that adds a MediumTopAppBar or a LargeTopAppBar
+     * @param content a Composable that adds a MediumTopAppBar, a LargeTopAppBar, or their flexible
+     *   variations
      */
     @OptIn(ExperimentalMaterial3Api::class)
     private fun assertMediumOrLargeScrolledHeight(
@@ -2213,7 +2235,8 @@
      * @param appBarMinHeight the min height of the app bar [content]
      * @param titleContentColor text content color expected for the app bar's title.
      * @param subtitleContentColor text content color expected for the app bar's subtitle.
-     * @param content a Composable that adds a MediumTopAppBar or a LargeTopAppBar
+     * @param content a Composable that adds a MediumTopAppBar, a LargeTopAppBar, or their flexible
+     *   variations
      */
     @OptIn(ExperimentalMaterial3Api::class)
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
@@ -2235,20 +2258,19 @@
         lateinit var scrollBehavior: TopAppBarScrollBehavior
         rule.setMaterialContent(lightColorScheme()) {
             scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
-            // Using the mediumTopAppBarColors for both Medium and Large top app bars, as the
-            // current content color settings are the same.
-            expandedAppBarBackgroundColor = TopAppBarMediumTokens.ContainerColor.value
+            // Using the topAppBarColors for both Medium and Large top app bars, as the
+            // content color is the same.
+            expandedAppBarBackgroundColor = AppBarTokens.ContainerColor.value
             fullyCollapsedContainerColor =
-                TopAppBarDefaults.mediumTopAppBarColors()
-                    .containerColor(colorTransitionFraction = 1f)
+                TopAppBarDefaults.topAppBarColors().containerColor(colorTransitionFraction = 1f)
 
             // Resolve the title's content color. The default implementation returns the same color
             // regardless of the fraction, and the color is applied later with alpha.
             if (titleColor == Color.Unspecified) {
-                titleColor = TopAppBarDefaults.mediumTopAppBarColors().titleContentColor
+                titleColor = TopAppBarDefaults.topAppBarColors().titleContentColor
             }
             if (subtitleColor == Color.Unspecified) {
-                subtitleColor = TopAppBarDefaults.mediumTopAppBarColors().titleContentColor
+                subtitleColor = TopAppBarDefaults.topAppBarColors().subtitleContentColor
             }
 
             with(LocalDensity.current) {
@@ -2412,10 +2434,10 @@
 
     /**
      * Top and bottom padding for all the built-in app bars that have a top part (or only part) with
-     * a height of TopAppBarSmallTokens.ContainerHeight
+     * a height of AppBarSmallTokens.ContainerHeight
      */
     private val DefaultAppBarTopAndBottomPadding =
-        (TopAppBarSmallTokens.ContainerHeight - FakeIconSize) / 2
+        (AppBarSmallTokens.ContainerHeight - FakeIconSize) / 2
 
     private val LazyListTag = "lazyList"
     private val TopAppBarTestTag = "topAppBar"
diff --git a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/SearchBarTest.kt b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/SearchBarTest.kt
index dbba35d..8fd8939 100644
--- a/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/SearchBarTest.kt
+++ b/compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/SearchBarTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.material3
 
+import android.os.Build
 import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Box
@@ -28,6 +29,7 @@
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.windowInsetsPadding
 import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.text.input.TextFieldState
 import androidx.compose.foundation.text.input.rememberTextFieldState
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.MoreVert
@@ -66,8 +68,10 @@
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.dp
+import androidx.test.espresso.Espresso
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
 import com.google.common.truth.Truth.assertThat
 import kotlin.math.roundToInt
 import kotlinx.coroutines.launch
@@ -83,8 +87,11 @@
 
     private val SearchBarTestTag = "SearchBar"
     private val ScrollableContentTestTag = "Scrollable"
+    private val CollapsedInputFieldTestTag = "CollapsedInputField"
+    private val ExpandedInputFieldTestTag = "ExpandedInputField"
     private val IconTestTag = "Icon"
     private val BackTestTag = "Back"
+    private val ContentTestTag = "Content"
 
     @Test
     fun searchBar_becomesExpandedAndFocusedOnClick_andNotExpandedAndUnfocusedOnBack() {
@@ -549,6 +556,267 @@
 
     // Tests for new search bar APIs below this section
 
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    @Test
+    fun newSearchBar_becomesExpandedAndFocusedOnClick_andCollapsedAndUnfocusedOnBack() {
+        rule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.fillMaxSize()) {
+                val searchBarState = rememberSearchBarState()
+                val textFieldState = rememberTextFieldState("Query")
+
+                // Extra item for initial focus.
+                Box(Modifier.size(10.dp).focusable())
+
+                SearchBar(
+                    modifier = Modifier.testTag(SearchBarTestTag),
+                    state = searchBarState,
+                    inputField = {
+                        InputField(
+                            searchBarState = searchBarState,
+                            textFieldState = textFieldState,
+                            modifier = Modifier.testTag(CollapsedInputFieldTestTag),
+                        )
+                    },
+                )
+                ExpandedFullScreenSearchBar(
+                    state = searchBarState,
+                    inputField = {
+                        InputField(
+                            searchBarState = searchBarState,
+                            textFieldState = textFieldState,
+                            modifier = Modifier.testTag(ExpandedInputFieldTestTag),
+                        )
+                    },
+                ) {
+                    Text("Content", modifier = Modifier.testTag(ContentTestTag))
+                }
+            }
+        }
+
+        rule.onNodeWithTag(ContentTestTag).assertDoesNotExist()
+
+        rule.onNodeWithTag(SearchBarTestTag).performClick()
+        rule.waitForIdle()
+
+        rule.onNodeWithTag(ContentTestTag).assertIsDisplayed()
+        rule.onNodeWithTag(ExpandedInputFieldTestTag).assertIsFocused()
+
+        // first dismiss keyboard, then dismiss search bar
+        repeat(2) {
+            Espresso.pressBack()
+            rule.waitForIdle()
+        }
+
+        rule.onNodeWithTag(ContentTestTag).assertDoesNotExist()
+        rule.onNodeWithTag(ExpandedInputFieldTestTag).assertDoesNotExist()
+        rule.onNodeWithTag(CollapsedInputFieldTestTag).assertIsNotFocused()
+    }
+
+    @Test
+    fun newSearchBar_doesNotOverwriteFocusOfOtherComponents() {
+        val focusRequester = FocusRequester()
+        rule.setMaterialContent(lightColorScheme()) {
+            Column(Modifier.fillMaxSize()) {
+                val searchBarState = rememberSearchBarState()
+                val textFieldState = rememberTextFieldState("Query")
+                SearchBar(
+                    modifier = Modifier.testTag(SearchBarTestTag),
+                    state = searchBarState,
+                    inputField = {
+                        InputField(
+                            searchBarState = searchBarState,
+                            textFieldState = textFieldState,
+                            modifier = Modifier.testTag(CollapsedInputFieldTestTag),
+                        )
+                    },
+                )
+                ExpandedFullScreenSearchBar(
+                    state = searchBarState,
+                    inputField = {
+                        InputField(
+                            searchBarState = searchBarState,
+                            textFieldState = textFieldState,
+                            modifier = Modifier.testTag(ExpandedInputFieldTestTag),
+                        )
+                    },
+                    content = {}
+                )
+
+                TextField(
+                    value = "",
+                    onValueChange = {},
+                    modifier = Modifier.testTag("SIBLING").focusRequester(focusRequester)
+                )
+            }
+        }
+
+        rule.runOnIdle { focusRequester.requestFocus() }
+
+        rule.onNodeWithTag("SIBLING").assertIsFocused()
+
+        rule.onNodeWithTag(SearchBarTestTag).performClick()
+        rule.onNodeWithTag(ExpandedInputFieldTestTag).assertIsFocused()
+    }
+
+    @Test
+    fun newSearchBar_onImeAction_executesSearchCallback() {
+        var capturedSearchQuery = ""
+
+        rule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.fillMaxSize()) {
+                val searchBarState = rememberSearchBarState()
+                val textFieldState = rememberTextFieldState("Query")
+                SearchBar(
+                    modifier = Modifier.testTag(SearchBarTestTag),
+                    state = searchBarState,
+                    inputField = {
+                        InputField(
+                            searchBarState = searchBarState,
+                            textFieldState = textFieldState,
+                            onSearch = { capturedSearchQuery = it },
+                            modifier = Modifier.testTag(CollapsedInputFieldTestTag),
+                        )
+                    },
+                )
+                ExpandedFullScreenSearchBar(
+                    state = searchBarState,
+                    inputField = {
+                        InputField(
+                            searchBarState = searchBarState,
+                            textFieldState = textFieldState,
+                            onSearch = { capturedSearchQuery = it },
+                            modifier = Modifier.testTag(ExpandedInputFieldTestTag),
+                        )
+                    },
+                    content = { Text("Content") }
+                )
+            }
+        }
+        rule.onNodeWithTag(CollapsedInputFieldTestTag).performImeAction()
+        assertThat(capturedSearchQuery).isEqualTo("Query")
+
+        capturedSearchQuery = ""
+
+        rule.onNodeWithTag(SearchBarTestTag).performClick()
+        rule.onNodeWithTag(ExpandedInputFieldTestTag).performImeAction()
+        assertThat(capturedSearchQuery).isEqualTo("Query")
+    }
+
+    @Test
+    fun newSearchBar_collapsedSize() {
+        rule
+            .setMaterialContentForSizeAssertions {
+                val searchBarState = rememberSearchBarState()
+                val textFieldState = rememberTextFieldState("Query")
+                SearchBar(
+                    modifier = Modifier.testTag(SearchBarTestTag),
+                    state = searchBarState,
+                    inputField = {
+                        InputField(
+                            searchBarState = searchBarState,
+                            textFieldState = textFieldState,
+                            modifier = Modifier.testTag(CollapsedInputFieldTestTag),
+                        )
+                    },
+                )
+            }
+            .assertWidthIsEqualTo(SearchBarMinWidth)
+            .assertHeightIsEqualTo(SearchBarDefaults.InputFieldHeight)
+    }
+
+    @Test
+    fun newSearchBar_clickingIconButton_doesNotExpandSearchBarItself() {
+        var iconClicked = false
+
+        rule.setMaterialContent(lightColorScheme()) {
+            Box(Modifier.fillMaxSize()) {
+                val searchBarState = rememberSearchBarState()
+                val textFieldState = rememberTextFieldState("Query")
+                SearchBar(
+                    modifier = Modifier.testTag(SearchBarTestTag),
+                    state = searchBarState,
+                    inputField = {
+                        InputField(
+                            searchBarState = searchBarState,
+                            textFieldState = textFieldState,
+                            modifier = Modifier.testTag(CollapsedInputFieldTestTag),
+                            trailingIcon = {
+                                IconButton(
+                                    onClick = { iconClicked = true },
+                                    modifier = Modifier.testTag(IconTestTag)
+                                ) {
+                                    Icon(Icons.Default.MoreVert, null)
+                                }
+                            },
+                        )
+                    },
+                )
+                ExpandedFullScreenSearchBar(
+                    state = searchBarState,
+                    inputField = {
+                        InputField(
+                            searchBarState = searchBarState,
+                            textFieldState = textFieldState,
+                            modifier = Modifier.testTag(ExpandedInputFieldTestTag),
+                            // don't need a trailing icon since the search bar should never expand
+                        )
+                    },
+                    content = { Text("Content", modifier = Modifier.testTag(ContentTestTag)) }
+                )
+            }
+        }
+
+        rule.onNodeWithTag(ContentTestTag).assertDoesNotExist()
+
+        // Click icon, not search bar
+        rule.onNodeWithTag(IconTestTag).performClick()
+        assertThat(iconClicked).isTrue()
+        rule.onNodeWithTag(ContentTestTag).assertDoesNotExist()
+    }
+
+    @Test
+    fun topSearchBar_usesAndConsumesWindowInsets() {
+        val parentTopInset = 10
+        val searchBarTopInset = 25
+
+        val searchBarPosition = Ref<Offset>()
+        val inputFieldPosition = Ref<Offset>()
+        lateinit var density: Density
+        lateinit var childConsumedInsets: WindowInsets
+
+        rule.setMaterialContent(lightColorScheme()) {
+            density = LocalDensity.current
+            val searchBarState = rememberSearchBarState()
+            Box(Modifier.windowInsetsPadding(WindowInsets(top = parentTopInset))) {
+                TopSearchBar(
+                    state = searchBarState,
+                    modifier =
+                        Modifier.onGloballyPositioned {
+                            searchBarPosition.value = it.positionInRoot()
+                        },
+                    windowInsets = WindowInsets(top = searchBarTopInset),
+                    inputField = {
+                        InputField(
+                            searchBarState = searchBarState,
+                            textFieldState = rememberTextFieldState(),
+                            modifier =
+                                Modifier.onGloballyPositioned {
+                                    inputFieldPosition.value = it.positionInRoot()
+                                },
+                        )
+
+                        Box(Modifier.onConsumedWindowInsetsChanged { childConsumedInsets = it })
+                    },
+                )
+            }
+        }
+
+        assertThat(searchBarPosition.value!!.y.roundToInt()).isEqualTo(parentTopInset)
+        assertThat(inputFieldPosition.value!!.y.roundToInt())
+            .isEqualTo(searchBarTopInset + with(density) { SearchBarAsTopBarPadding.roundToPx() })
+        assertThat(childConsumedInsets.getTop(density)).isEqualTo(searchBarTopInset)
+    }
+
     @Test
     fun topSearchBar_scrollBehavior_showsAndHidesWithVerticalScroll() {
         rule.setMaterialContent(lightColorScheme()) { SearchBarWithScrollableContent() }
@@ -665,6 +933,24 @@
     }
 
     @Composable
+    private fun InputField(
+        searchBarState: SearchBarState,
+        textFieldState: TextFieldState,
+        modifier: Modifier = Modifier,
+        onSearch: (String) -> Unit = {},
+        trailingIcon: (@Composable () -> Unit)? = null,
+    ) {
+        SearchBarDefaults.InputField(
+            searchBarState = searchBarState,
+            textFieldState = textFieldState,
+            onSearch = onSearch,
+            modifier = modifier,
+            placeholder = { Text("Search") },
+            trailingIcon = trailingIcon,
+        )
+    }
+
+    @Composable
     private fun SearchBarWithScrollableContent(
         searchBarScrollBehavior: SearchBarScrollBehavior =
             SearchBarDefaults.enterAlwaysSearchBarScrollBehavior(),
@@ -681,14 +967,12 @@
                     scrollBehavior = searchBarScrollBehavior,
                     state = searchBarState,
                     inputField = {
-                        SearchBarDefaults.InputField(
+                        InputField(
                             searchBarState = searchBarState,
                             textFieldState = textFieldState,
                             onSearch = { scope.launch { searchBarState.animateToCollapsed() } },
-                            placeholder = { Text("Search") },
                         )
                     },
-                    content = {},
                 )
             }
         ) { innerPadding ->
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AppBar.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AppBar.kt
index f86190b..05287c9 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AppBar.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AppBar.kt
@@ -42,17 +42,20 @@
 import androidx.compose.foundation.layout.only
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.windowInsetsPadding
+import androidx.compose.material3.BottomAppBarState.Companion.Saver
+import androidx.compose.material3.TopAppBarState.Companion.Saver
 import androidx.compose.material3.internal.FloatProducer
 import androidx.compose.material3.internal.ProvideContentColorTextStyle
 import androidx.compose.material3.internal.systemBarsForVisualComponents
+import androidx.compose.material3.tokens.AppBarLargeFlexibleTokens
+import androidx.compose.material3.tokens.AppBarLargeTokens
+import androidx.compose.material3.tokens.AppBarMediumFlexibleTokens
+import androidx.compose.material3.tokens.AppBarMediumTokens
+import androidx.compose.material3.tokens.AppBarSmallTokens
+import androidx.compose.material3.tokens.AppBarTokens
 import androidx.compose.material3.tokens.BottomAppBarTokens
 import androidx.compose.material3.tokens.FabSecondaryContainerTokens
 import androidx.compose.material3.tokens.MotionSchemeKeyTokens
-import androidx.compose.material3.tokens.TopAppBarLargeTokens
-import androidx.compose.material3.tokens.TopAppBarMediumTokens
-import androidx.compose.material3.tokens.TopAppBarSmallCenteredTokens
-import androidx.compose.material3.tokens.TopAppBarSmallTokens
-import androidx.compose.material3.tokens.TypographyKeyTokens
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.Stable
@@ -103,7 +106,6 @@
 import androidx.compose.ui.util.fastFirst
 import androidx.compose.ui.util.fastMaxOfOrNull
 import androidx.compose.ui.util.fastSumBy
-import kotlin.jvm.JvmInline
 import kotlin.math.abs
 import kotlin.math.max
 import kotlin.math.roundToInt
@@ -218,10 +220,10 @@
     SingleRowTopAppBar(
         modifier = modifier,
         title = title,
-        titleTextStyle = TopAppBarSmallTokens.HeadlineFont.value,
+        titleTextStyle = AppBarSmallTokens.TitleFont.value,
         subtitle = null,
         subtitleTextStyle = TextStyle.Default,
-        titleHorizontalAlignment = TopAppBarTitleAlignment.Start,
+        titleHorizontalAlignment = Alignment.Start,
         navigationIcon = navigationIcon,
         actions = actions,
         expandedHeight =
@@ -260,7 +262,7 @@
  *   [IconButton]s. The default layout here is a [Row], so icons inside will be placed horizontally.
  * @param windowInsets a window insets that app bar will respect.
  * @param colors [TopAppBarColors] that will be used to resolve the colors used for this top app bar
- *   in different states. See [TopAppBarDefaults.centerAlignedTopAppBarColors].
+ *   in different states. See [TopAppBarDefaults.topAppBarColors].
  * @param scrollBehavior a [TopAppBarScrollBehavior] which holds various offset values that will be
  *   applied by this top app bar to set up its height and colors. A scroll behavior is designed to
  *   work in conjunction with a scrolled content to change the top app bar appearance as the content
@@ -278,7 +280,7 @@
     navigationIcon: @Composable () -> Unit = {},
     actions: @Composable RowScope.() -> Unit = {},
     windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
-    colors: TopAppBarColors = TopAppBarDefaults.centerAlignedTopAppBarColors(),
+    colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
     scrollBehavior: TopAppBarScrollBehavior? = null
 ) =
     CenterAlignedTopAppBar(
@@ -321,7 +323,7 @@
  *   replaced with [TopAppBarDefaults.TopAppBarExpandedHeight].
  * @param windowInsets a window insets that app bar will respect.
  * @param colors [TopAppBarColors] that will be used to resolve the colors used for this top app bar
- *   in different states. See [TopAppBarDefaults.centerAlignedTopAppBarColors].
+ *   in different states. See [TopAppBarDefaults.topAppBarColors].
  * @param scrollBehavior a [TopAppBarScrollBehavior] which holds various offset values that will be
  *   applied by this top app bar to set up its height and colors. A scroll behavior is designed to
  *   work in conjunction with a scrolled content to change the top app bar appearance as the content
@@ -337,16 +339,16 @@
     actions: @Composable RowScope.() -> Unit = {},
     expandedHeight: Dp = TopAppBarDefaults.TopAppBarExpandedHeight,
     windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
-    colors: TopAppBarColors = TopAppBarDefaults.centerAlignedTopAppBarColors(),
+    colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
     scrollBehavior: TopAppBarScrollBehavior? = null
 ) =
     SingleRowTopAppBar(
         modifier = modifier,
         title = title,
-        titleTextStyle = TopAppBarSmallTokens.HeadlineFont.value,
+        titleTextStyle = AppBarSmallTokens.TitleFont.value,
         subtitle = null,
         subtitleTextStyle = TextStyle.Default,
-        titleHorizontalAlignment = TopAppBarTitleAlignment.Center,
+        titleHorizontalAlignment = Alignment.CenterHorizontally,
         navigationIcon = navigationIcon,
         actions = actions,
         expandedHeight =
@@ -405,7 +407,7 @@
     modifier: Modifier = Modifier,
     navigationIcon: @Composable () -> Unit = {},
     actions: @Composable RowScope.() -> Unit = {},
-    titleHorizontalAlignment: TopAppBarTitleAlignment = TopAppBarTitleAlignment.Start,
+    titleHorizontalAlignment: Alignment.Horizontal = Alignment.Start,
     expandedHeight: Dp = TopAppBarDefaults.TopAppBarExpandedHeight,
     windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
     colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
@@ -414,9 +416,9 @@
     SingleRowTopAppBar(
         modifier = modifier,
         title = title,
-        titleTextStyle = TopAppBarSmallTokens.HeadlineFont.value,
+        titleTextStyle = AppBarSmallTokens.TitleFont.value,
         subtitle = subtitle,
-        subtitleTextStyle = TypographyKeyTokens.LabelMedium.value, // TODO tokens
+        subtitleTextStyle = AppBarSmallTokens.SubtitleFont.value,
         titleHorizontalAlignment = titleHorizontalAlignment,
         navigationIcon = navigationIcon,
         actions = actions,
@@ -457,7 +459,7 @@
  *   [IconButton]s. The default layout here is a [Row], so icons inside will be placed horizontally.
  * @param windowInsets a window insets that app bar will respect.
  * @param colors [TopAppBarColors] that will be used to resolve the colors used for this top app bar
- *   in different states. See [TopAppBarDefaults.mediumTopAppBarColors].
+ *   in different states. See [TopAppBarDefaults.topAppBarColors].
  * @param scrollBehavior a [TopAppBarScrollBehavior] which holds various offset values that will be
  *   applied by this top app bar to set up its height and colors. A scroll behavior is designed to
  *   work in conjunction with a scrolled content to change the top app bar appearance as the content
@@ -477,7 +479,7 @@
     navigationIcon: @Composable () -> Unit = {},
     actions: @Composable RowScope.() -> Unit = {},
     windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
-    colors: TopAppBarColors = TopAppBarDefaults.mediumTopAppBarColors(),
+    colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
     scrollBehavior: TopAppBarScrollBehavior? = null
 ) =
     MediumTopAppBar(
@@ -527,7 +529,7 @@
  *   [TopAppBarDefaults.MediumAppBarExpandedHeight].
  * @param windowInsets a window insets that app bar will respect.
  * @param colors [TopAppBarColors] that will be used to resolve the colors used for this top app bar
- *   in different states. See [TopAppBarDefaults.mediumTopAppBarColors].
+ *   in different states. See [TopAppBarDefaults.topAppBarColors].
  * @param scrollBehavior a [TopAppBarScrollBehavior] which holds various offset values that will be
  *   applied by this top app bar to set up its height and colors. A scroll behavior is designed to
  *   work in conjunction with a scrolled content to change the top app bar appearance as the content
@@ -546,21 +548,21 @@
     collapsedHeight: Dp = TopAppBarDefaults.MediumAppBarCollapsedHeight,
     expandedHeight: Dp = TopAppBarDefaults.MediumAppBarExpandedHeight,
     windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
-    colors: TopAppBarColors = TopAppBarDefaults.mediumTopAppBarColors(),
+    colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
     scrollBehavior: TopAppBarScrollBehavior? = null
 ) =
     TwoRowsTopAppBar(
         modifier = modifier,
         title = title,
-        titleTextStyle = TopAppBarMediumTokens.HeadlineFont.value,
-        smallTitleTextStyle = TopAppBarSmallTokens.HeadlineFont.value,
+        titleTextStyle = AppBarMediumTokens.TitleFont.value,
+        smallTitleTextStyle = AppBarSmallTokens.TitleFont.value,
         titleBottomPadding = MediumTitleBottomPadding,
         smallTitle = title,
         subtitle = null,
         subtitleTextStyle = TextStyle.Default,
         smallSubtitle = null,
         smallSubtitleTextStyle = TextStyle.Default,
-        titleHorizontalAlignment = TopAppBarTitleAlignment.Start,
+        titleHorizontalAlignment = Alignment.Start,
         navigationIcon = navigationIcon,
         actions = actions,
         collapsedHeight =
@@ -582,27 +584,27 @@
 
 /**
  * <a href="https://m3.material.io/components/top-app-bar/overview" class="external"
- * target="_blank">Material Design medium top app bar</a>.
+ * target="_blank">Material Design medium flexible top app bar</a>.
  *
  * Top app bars display information and actions at the top of a screen.
  *
  * ![Medium top app bar
  * image](https://developer.android.com/images/reference/androidx/compose/material3/medium-top-app-bar.png)
  *
- * This MediumTopAppBar has slots for a title, subtitle, navigation icon, and actions. In its
- * default expanded state, the title and subtitle are displayed in a second row under the navigation
- * and actions.
+ * This `MediumFlexibleTopAppBar` has slots for a title, subtitle, navigation icon, and actions. In
+ * its default expanded state, the title and subtitle are displayed in a second row under the
+ * navigation and actions.
  *
- * A medium top app bar that uses a [scrollBehavior] to customize its nested scrolling behavior when
- * working in conjunction with scrolling content looks like:
+ * A medium flexible top app bar that uses a [scrollBehavior] to customize its nested scrolling
+ * behavior when working in conjunction with scrolling content looks like:
  *
- * @sample androidx.compose.material3.samples.ExitUntilCollapsedCenterAlignedMediumTopAppBarWithSubtitle
+ * @sample androidx.compose.material3.samples.ExitUntilCollapsedCenterAlignedMediumFlexibleTopAppBar
  * @param title the title to be displayed in the top app bar. This title will be used in the app
  *   bar's expanded and collapsed states, although in its collapsed state it will be composed with a
  *   smaller sized [TextStyle]
- * @param subtitle the subtitle to be displayed in the top app bar. This subtitle will be used in
- *   the app bar's expanded and collapsed states
  * @param modifier the [Modifier] to be applied to this top app bar
+ * @param subtitle optional subtitle to be displayed in the top app bar. This subtitle will be used
+ *   in the app bar's expanded and collapsed states
  * @param navigationIcon the navigation icon displayed at the start of the top app bar. This should
  *   typically be an [IconButton] or [IconToggleButton].
  * @param actions the actions displayed at the end of the top app bar. This should typically be
@@ -619,7 +621,7 @@
  *   [TopAppBarDefaults.MediumAppBarExpandedHeight].
  * @param windowInsets a window insets that app bar will respect.
  * @param colors [TopAppBarColors] that will be used to resolve the colors used for this top app bar
- *   in different states. See [TopAppBarDefaults.mediumTopAppBarColors].
+ *   in different states. See [TopAppBarDefaults.topAppBarColors].
  * @param scrollBehavior a [TopAppBarScrollBehavior] which holds various offset values that will be
  *   applied by this top app bar to set up its height and colors. A scroll behavior is designed to
  *   work in conjunction with a scrolled content to change the top app bar appearance as the content
@@ -630,35 +632,35 @@
 @OptIn(ExperimentalMaterial3Api::class)
 @ExperimentalMaterial3ExpressiveApi
 @Composable
-fun MediumTopAppBar(
+fun MediumFlexibleTopAppBar(
     title: @Composable () -> Unit,
-    subtitle: (@Composable () -> Unit)?,
     modifier: Modifier = Modifier,
+    subtitle: (@Composable () -> Unit)? = null,
     navigationIcon: @Composable () -> Unit = {},
     actions: @Composable RowScope.() -> Unit = {},
-    titleHorizontalAlignment: TopAppBarTitleAlignment = TopAppBarTitleAlignment.Start,
+    titleHorizontalAlignment: Alignment.Horizontal = Alignment.Start,
     collapsedHeight: Dp = TopAppBarDefaults.MediumAppBarCollapsedHeight,
     expandedHeight: Dp =
         if (subtitle != null) {
-            TopAppBarDefaults.MediumAppBarWithSubtitleExpandedHeight
+            TopAppBarDefaults.MediumFlexibleAppBarWithSubtitleExpandedHeight
         } else {
-            TopAppBarDefaults.MediumAppBarWithoutSubtitleExpandedHeight
+            TopAppBarDefaults.MediumFlexibleAppBarWithoutSubtitleExpandedHeight
         },
     windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
-    colors: TopAppBarColors = TopAppBarDefaults.mediumTopAppBarColors(),
+    colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
     scrollBehavior: TopAppBarScrollBehavior? = null
 ) =
     TwoRowsTopAppBar(
         modifier = modifier,
         title = title,
-        titleTextStyle = TypographyKeyTokens.HeadlineMedium.value, // TODO tokens
-        smallTitleTextStyle = TopAppBarSmallTokens.HeadlineFont.value,
+        titleTextStyle = AppBarMediumFlexibleTokens.TitleFont.value,
+        smallTitleTextStyle = AppBarSmallTokens.TitleFont.value,
         titleBottomPadding = MediumTitleBottomPadding,
         smallTitle = title,
         subtitle = subtitle ?: {},
-        subtitleTextStyle = TypographyKeyTokens.LabelLarge.value, // TODO tokens
+        subtitleTextStyle = AppBarMediumFlexibleTokens.SubtitleFont.value,
         smallSubtitle = subtitle ?: {},
-        smallSubtitleTextStyle = TypographyKeyTokens.LabelMedium.value, // TODO tokens
+        smallSubtitleTextStyle = AppBarSmallTokens.SubtitleFont.value,
         titleHorizontalAlignment = titleHorizontalAlignment,
         navigationIcon = navigationIcon,
         actions = actions,
@@ -671,9 +673,9 @@
         expandedHeight =
             if (expandedHeight == Dp.Unspecified || expandedHeight == Dp.Infinity) {
                 if (subtitle != null) {
-                    TopAppBarDefaults.MediumAppBarWithSubtitleExpandedHeight
+                    TopAppBarDefaults.MediumFlexibleAppBarWithSubtitleExpandedHeight
                 } else {
-                    TopAppBarDefaults.MediumAppBarWithoutSubtitleExpandedHeight
+                    TopAppBarDefaults.MediumFlexibleAppBarWithoutSubtitleExpandedHeight
                 }
             } else {
                 expandedHeight
@@ -709,7 +711,7 @@
  *   [IconButton]s. The default layout here is a [Row], so icons inside will be placed horizontally.
  * @param windowInsets a window insets that app bar will respect.
  * @param colors [TopAppBarColors] that will be used to resolve the colors used for this top app bar
- *   in different states. See [TopAppBarDefaults.largeTopAppBarColors].
+ *   in different states. See [TopAppBarDefaults.topAppBarColors].
  * @param scrollBehavior a [TopAppBarScrollBehavior] which holds various offset values that will be
  *   applied by this top app bar to set up its height and colors. A scroll behavior is designed to
  *   work in conjunction with a scrolled content to change the top app bar appearance as the content
@@ -729,7 +731,7 @@
     navigationIcon: @Composable () -> Unit = {},
     actions: @Composable RowScope.() -> Unit = {},
     windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
-    colors: TopAppBarColors = TopAppBarDefaults.largeTopAppBarColors(),
+    colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
     scrollBehavior: TopAppBarScrollBehavior? = null
 ) =
     LargeTopAppBar(
@@ -779,7 +781,7 @@
  *   [TopAppBarDefaults.LargeAppBarExpandedHeight].
  * @param windowInsets a window insets that app bar will respect.
  * @param colors [TopAppBarColors] that will be used to resolve the colors used for this top app bar
- *   in different states. See [TopAppBarDefaults.largeTopAppBarColors].
+ *   in different states. See [TopAppBarDefaults.topAppBarColors].
  * @param scrollBehavior a [TopAppBarScrollBehavior] which holds various offset values that will be
  *   applied by this top app bar to set up its height and colors. A scroll behavior is designed to
  *   work in conjunction with a scrolled content to change the top app bar appearance as the content
@@ -798,13 +800,13 @@
     collapsedHeight: Dp = TopAppBarDefaults.LargeAppBarCollapsedHeight,
     expandedHeight: Dp = TopAppBarDefaults.LargeAppBarExpandedHeight,
     windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
-    colors: TopAppBarColors = TopAppBarDefaults.largeTopAppBarColors(),
+    colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
     scrollBehavior: TopAppBarScrollBehavior? = null
 ) =
     TwoRowsTopAppBar(
         title = title,
-        titleTextStyle = TopAppBarLargeTokens.HeadlineFont.value,
-        smallTitleTextStyle = TopAppBarSmallTokens.HeadlineFont.value,
+        titleTextStyle = AppBarLargeTokens.TitleFont.value,
+        smallTitleTextStyle = AppBarSmallTokens.TitleFont.value,
         titleBottomPadding = LargeTitleBottomPadding,
         smallTitle = title,
         modifier = modifier,
@@ -812,7 +814,7 @@
         subtitleTextStyle = TextStyle.Default,
         smallSubtitle = null,
         smallSubtitleTextStyle = TextStyle.Default,
-        titleHorizontalAlignment = TopAppBarTitleAlignment.Start,
+        titleHorizontalAlignment = Alignment.Start,
         navigationIcon = navigationIcon,
         actions = actions,
         collapsedHeight =
@@ -834,27 +836,27 @@
 
 /**
  * <a href="https://m3.material.io/components/top-app-bar/overview" class="external"
- * target="_blank">Material Design large top app bar</a>.
+ * target="_blank">Material Design large flexible top app bar</a>.
  *
  * Top app bars display information and actions at the top of a screen.
  *
  * ![Large top app bar
  * image](https://developer.android.com/images/reference/androidx/compose/material3/large-top-app-bar.png)
  *
- * This LargeTopAppBar has slots for a title, subtitle, navigation icon, and actions. In its default
- * expanded state, the title and subtitle are displayed in a second row under the navigation and
- * actions.
+ * This `LargeFlexibleTopAppBar` has slots for a title, subtitle, navigation icon, and actions. In
+ * its default expanded state, the title and subtitle are displayed in a second row under the
+ * navigation and actions.
  *
- * A large top app bar that uses a [scrollBehavior] to customize its nested scrolling behavior when
- * working in conjunction with scrolling content looks like:
+ * A large flexible top app bar that uses a [scrollBehavior] to customize its nested scrolling
+ * behavior when working in conjunction with scrolling content looks like:
  *
- * @sample androidx.compose.material3.samples.ExitUntilCollapsedCenterAlignedLargeTopAppBarWithSubtitle
+ * @sample androidx.compose.material3.samples.ExitUntilCollapsedCenterAlignedLargeFlexibleTopAppBar
  * @param title the title to be displayed in the top app bar. This title will be used in the app
  *   bar's expanded and collapsed states, although in its collapsed state it will be composed with a
  *   smaller sized [TextStyle]
- * @param subtitle the subtitle to be displayed in the top app bar. This subtitle will be used in
- *   the app bar's expanded and collapsed states
  * @param modifier the [Modifier] to be applied to this top app bar
+ * @param subtitle an optional subtitle to be displayed in the top app bar. This subtitle will be
+ *   used in the app bar's expanded and collapsed states.
  * @param navigationIcon the navigation icon displayed at the start of the top app bar. This should
  *   typically be an [IconButton] or [IconToggleButton].
  * @param actions the actions displayed at the end of the top app bar. This should typically be
@@ -871,7 +873,7 @@
  *   [TopAppBarDefaults.LargeAppBarExpandedHeight].
  * @param windowInsets a window insets that app bar will respect.
  * @param colors [TopAppBarColors] that will be used to resolve the colors used for this top app bar
- *   in different states. See [TopAppBarDefaults.largeTopAppBarColors].
+ *   in different states. See [TopAppBarDefaults.topAppBarColors].
  * @param scrollBehavior a [TopAppBarScrollBehavior] which holds various offset values that will be
  *   applied by this top app bar to set up its height and colors. A scroll behavior is designed to
  *   work in conjunction with a scrolled content to change the top app bar appearance as the content
@@ -882,35 +884,35 @@
 @OptIn(ExperimentalMaterial3Api::class)
 @ExperimentalMaterial3ExpressiveApi
 @Composable
-fun LargeTopAppBar(
+fun LargeFlexibleTopAppBar(
     title: @Composable () -> Unit,
-    subtitle: (@Composable () -> Unit)?,
     modifier: Modifier = Modifier,
+    subtitle: (@Composable () -> Unit)? = null,
     navigationIcon: @Composable () -> Unit = {},
     actions: @Composable RowScope.() -> Unit = {},
-    titleHorizontalAlignment: TopAppBarTitleAlignment = TopAppBarTitleAlignment.Start,
+    titleHorizontalAlignment: Alignment.Horizontal = Alignment.Start,
     collapsedHeight: Dp = TopAppBarDefaults.LargeAppBarCollapsedHeight,
     expandedHeight: Dp =
         if (subtitle != null) {
-            TopAppBarDefaults.LargeAppBarWithSubtitleExpandedHeight
+            TopAppBarDefaults.LargeFlexibleAppBarWithSubtitleExpandedHeight
         } else {
-            TopAppBarDefaults.LargeAppBarWithoutSubtitleExpandedHeight
+            TopAppBarDefaults.LargeFlexibleAppBarWithoutSubtitleExpandedHeight
         },
     windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
-    colors: TopAppBarColors = TopAppBarDefaults.largeTopAppBarColors(),
+    colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
     scrollBehavior: TopAppBarScrollBehavior? = null
 ) =
     TwoRowsTopAppBar(
         title = title,
-        titleTextStyle = TypographyKeyTokens.DisplaySmall.value, // TODO tokens
-        smallTitleTextStyle = TopAppBarSmallTokens.HeadlineFont.value,
+        titleTextStyle = AppBarLargeFlexibleTokens.TitleFont.value,
+        smallTitleTextStyle = AppBarSmallTokens.TitleFont.value,
         titleBottomPadding = LargeTitleBottomPadding,
         smallTitle = title,
         modifier = modifier,
         subtitle = subtitle ?: {},
-        subtitleTextStyle = TypographyKeyTokens.TitleMedium.value, // TODO tokens
+        subtitleTextStyle = AppBarLargeFlexibleTokens.SubtitleFont.value,
         smallSubtitle = subtitle ?: {},
-        smallSubtitleTextStyle = TypographyKeyTokens.LabelMedium.value, // TODO tokens
+        smallSubtitleTextStyle = AppBarSmallTokens.SubtitleFont.value,
         titleHorizontalAlignment = titleHorizontalAlignment,
         navigationIcon = navigationIcon,
         actions = actions,
@@ -923,9 +925,9 @@
         expandedHeight =
             if (expandedHeight == Dp.Unspecified || expandedHeight == Dp.Infinity) {
                 if (subtitle != null) {
-                    TopAppBarDefaults.LargeAppBarWithSubtitleExpandedHeight
+                    TopAppBarDefaults.LargeFlexibleAppBarWithSubtitleExpandedHeight
                 } else {
-                    TopAppBarDefaults.LargeAppBarWithoutSubtitleExpandedHeight
+                    TopAppBarDefaults.LargeFlexibleAppBarWithoutSubtitleExpandedHeight
                 }
             } else {
                 expandedHeight
@@ -1376,6 +1378,7 @@
      * @param navigationIconContentColor the content color used for the navigation icon
      * @param titleContentColor the content color used for the title
      * @param actionIconContentColor the content color used for actions
+     * @param subtitleContentColor the content color used for the subtitle
      * @return the resulting [TopAppBarColors] used for the top app bar
      */
     @Composable
@@ -1385,26 +1388,59 @@
         navigationIconContentColor: Color = Color.Unspecified,
         titleContentColor: Color = Color.Unspecified,
         actionIconContentColor: Color = Color.Unspecified,
+        subtitleContentColor: Color = Color.Unspecified,
     ): TopAppBarColors =
         MaterialTheme.colorScheme.defaultTopAppBarColors.copy(
             containerColor,
             scrolledContainerColor,
             navigationIconContentColor,
             titleContentColor,
-            actionIconContentColor
+            actionIconContentColor,
+            subtitleContentColor
+        )
+
+    /**
+     * Creates a [TopAppBarColors] for small [TopAppBar]. The default implementation animates
+     * between the provided colors according to the Material Design specification.
+     *
+     * @param containerColor the container color
+     * @param scrolledContainerColor the container color when content is scrolled behind it
+     * @param navigationIconContentColor the content color used for the navigation icon
+     * @param titleContentColor the content color used for the title
+     * @param actionIconContentColor the content color used for actions
+     * @return the resulting [TopAppBarColors] used for the top app bar
+     */
+    @Deprecated(
+        "Maintained for binary compatibility in favor of topAppBarColors with subtitleContentColor",
+        level = DeprecationLevel.HIDDEN
+    )
+    @Composable
+    fun topAppBarColors(
+        containerColor: Color = Color.Unspecified,
+        scrolledContainerColor: Color = Color.Unspecified,
+        navigationIconContentColor: Color = Color.Unspecified,
+        titleContentColor: Color = Color.Unspecified,
+        actionIconContentColor: Color = Color.Unspecified,
+    ): TopAppBarColors =
+        topAppBarColors(
+            containerColor = containerColor,
+            scrolledContainerColor = scrolledContainerColor,
+            navigationIconContentColor = navigationIconContentColor,
+            titleContentColor = titleContentColor,
+            actionIconContentColor = actionIconContentColor,
+            subtitleContentColor = titleContentColor
         )
 
     internal val ColorScheme.defaultTopAppBarColors: TopAppBarColors
         get() {
             return defaultTopAppBarColorsCached
                 ?: TopAppBarColors(
-                        containerColor = fromToken(TopAppBarSmallTokens.ContainerColor),
-                        scrolledContainerColor =
-                            fromToken(TopAppBarSmallTokens.OnScrollContainerColor),
-                        navigationIconContentColor =
-                            fromToken(TopAppBarSmallTokens.LeadingIconColor),
-                        titleContentColor = fromToken(TopAppBarSmallTokens.HeadlineColor),
-                        actionIconContentColor = fromToken(TopAppBarSmallTokens.TrailingIconColor),
+                        containerColor = fromToken(AppBarTokens.ContainerColor),
+                        scrolledContainerColor = fromToken(AppBarTokens.OnScrollContainerColor),
+                        navigationIconContentColor = fromToken(AppBarTokens.LeadingIconColor),
+                        titleContentColor = fromToken(AppBarTokens.TitleColor),
+                        actionIconContentColor = fromToken(AppBarTokens.TrailingIconColor),
+                        subtitleContentColor = fromToken(AppBarTokens.SubtitleColor),
                     )
                     .also { defaultTopAppBarColorsCached = it }
         }
@@ -1421,9 +1457,13 @@
      * Creates a [TopAppBarColors] for [CenterAlignedTopAppBar]s. The default implementation
      * animates between the provided colors according to the Material Design specification.
      */
+    @Deprecated(
+        "Use topAppBarColors instead",
+        replaceWith = ReplaceWith("topAppBarColors()"),
+        DeprecationLevel.WARNING
+    )
     @Composable
-    fun centerAlignedTopAppBarColors() =
-        MaterialTheme.colorScheme.defaultCenterAlignedTopAppBarColors
+    fun centerAlignedTopAppBarColors() = MaterialTheme.colorScheme.defaultTopAppBarColors
 
     /**
      * Creates a [TopAppBarColors] for [CenterAlignedTopAppBar]s. The default implementation
@@ -1436,6 +1476,15 @@
      * @param actionIconContentColor the content color used for actions
      * @return the resulting [TopAppBarColors] used for the top app bar
      */
+    @Deprecated(
+        "Use topAppBarColors instead",
+        replaceWith =
+            ReplaceWith(
+                "topAppBarColors(containerColor, scrolledContainerColor, " +
+                    "navigationIconContentColor, titleContentColor, actionIconContentColor)"
+            ),
+        DeprecationLevel.WARNING
+    )
     @Composable
     fun centerAlignedTopAppBarColors(
         containerColor: Color = Color.Unspecified,
@@ -1444,7 +1493,7 @@
         titleContentColor: Color = Color.Unspecified,
         actionIconContentColor: Color = Color.Unspecified,
     ): TopAppBarColors =
-        MaterialTheme.colorScheme.defaultCenterAlignedTopAppBarColors.copy(
+        MaterialTheme.colorScheme.defaultTopAppBarColors.copy(
             containerColor,
             scrolledContainerColor,
             navigationIconContentColor,
@@ -1452,28 +1501,18 @@
             actionIconContentColor
         )
 
-    internal val ColorScheme.defaultCenterAlignedTopAppBarColors: TopAppBarColors
-        get() {
-            return defaultCenterAlignedTopAppBarColorsCached
-                ?: TopAppBarColors(
-                        containerColor = fromToken(TopAppBarSmallCenteredTokens.ContainerColor),
-                        scrolledContainerColor =
-                            fromToken(TopAppBarSmallCenteredTokens.OnScrollContainerColor),
-                        navigationIconContentColor =
-                            fromToken(TopAppBarSmallCenteredTokens.LeadingIconColor),
-                        titleContentColor = fromToken(TopAppBarSmallCenteredTokens.HeadlineColor),
-                        actionIconContentColor =
-                            fromToken(TopAppBarSmallCenteredTokens.TrailingIconColor),
-                    )
-                    .also { defaultCenterAlignedTopAppBarColorsCached = it }
-        }
-
     /**
      * Creates a [TopAppBarColors] for [MediumTopAppBar]s. The default implementation interpolates
      * between the provided colors as the top app bar scrolls according to the Material Design
      * specification.
      */
-    @Composable fun mediumTopAppBarColors() = MaterialTheme.colorScheme.defaultMediumTopAppBarColors
+    @Deprecated(
+        "Use topAppBarColors instead",
+        replaceWith = ReplaceWith("topAppBarColors()"),
+        DeprecationLevel.WARNING
+    )
+    @Composable
+    fun mediumTopAppBarColors() = MaterialTheme.colorScheme.defaultTopAppBarColors
 
     /**
      * Creates a [TopAppBarColors] for [MediumTopAppBar]s. The default implementation interpolates
@@ -1487,6 +1526,15 @@
      * @param actionIconContentColor the content color used for actions
      * @return the resulting [TopAppBarColors] used for the top app bar
      */
+    @Deprecated(
+        "Use topAppBarColors instead",
+        replaceWith =
+            ReplaceWith(
+                "topAppBarColors(containerColor, scrolledContainerColor, " +
+                    "navigationIconContentColor, titleContentColor, actionIconContentColor)"
+            ),
+        DeprecationLevel.WARNING
+    )
     @Composable
     fun mediumTopAppBarColors(
         containerColor: Color = Color.Unspecified,
@@ -1495,7 +1543,7 @@
         titleContentColor: Color = Color.Unspecified,
         actionIconContentColor: Color = Color.Unspecified,
     ): TopAppBarColors =
-        MaterialTheme.colorScheme.defaultMediumTopAppBarColors.copy(
+        MaterialTheme.colorScheme.defaultTopAppBarColors.copy(
             containerColor,
             scrolledContainerColor,
             navigationIconContentColor,
@@ -1503,27 +1551,18 @@
             actionIconContentColor
         )
 
-    internal val ColorScheme.defaultMediumTopAppBarColors: TopAppBarColors
-        get() {
-            return defaultMediumTopAppBarColorsCached
-                ?: TopAppBarColors(
-                        containerColor = fromToken(TopAppBarMediumTokens.ContainerColor),
-                        scrolledContainerColor =
-                            fromToken(TopAppBarSmallTokens.OnScrollContainerColor),
-                        navigationIconContentColor =
-                            fromToken(TopAppBarMediumTokens.LeadingIconColor),
-                        titleContentColor = fromToken(TopAppBarMediumTokens.HeadlineColor),
-                        actionIconContentColor = fromToken(TopAppBarMediumTokens.TrailingIconColor),
-                    )
-                    .also { defaultMediumTopAppBarColorsCached = it }
-        }
-
     /**
      * Creates a [TopAppBarColors] for [LargeTopAppBar]s. The default implementation interpolates
      * between the provided colors as the top app bar scrolls according to the Material Design
      * specification.
      */
-    @Composable fun largeTopAppBarColors() = MaterialTheme.colorScheme.defaultLargeTopAppBarColors
+    @Deprecated(
+        "Use topAppBarColors instead",
+        replaceWith = ReplaceWith("topAppBarColors()"),
+        DeprecationLevel.WARNING
+    )
+    @Composable
+    fun largeTopAppBarColors() = MaterialTheme.colorScheme.defaultTopAppBarColors
 
     /**
      * Creates a [TopAppBarColors] for [LargeTopAppBar]s. The default implementation interpolates
@@ -1537,6 +1576,15 @@
      * @param actionIconContentColor the content color used for actions
      * @return the resulting [TopAppBarColors] used for the top app bar
      */
+    @Deprecated(
+        "Use topAppBarColors instead",
+        replaceWith =
+            ReplaceWith(
+                "topAppBarColors(containerColor, scrolledContainerColor, " +
+                    "navigationIconContentColor, titleContentColor, actionIconContentColor)"
+            ),
+        DeprecationLevel.WARNING
+    )
     @Composable
     fun largeTopAppBarColors(
         containerColor: Color = Color.Unspecified,
@@ -1545,7 +1593,7 @@
         titleContentColor: Color = Color.Unspecified,
         actionIconContentColor: Color = Color.Unspecified,
     ): TopAppBarColors =
-        MaterialTheme.colorScheme.defaultLargeTopAppBarColors.copy(
+        MaterialTheme.colorScheme.defaultTopAppBarColors.copy(
             containerColor,
             scrolledContainerColor,
             navigationIconContentColor,
@@ -1553,21 +1601,6 @@
             actionIconContentColor
         )
 
-    internal val ColorScheme.defaultLargeTopAppBarColors: TopAppBarColors
-        get() {
-            return defaultLargeTopAppBarColorsCached
-                ?: TopAppBarColors(
-                        containerColor = fromToken(TopAppBarLargeTokens.ContainerColor),
-                        scrolledContainerColor =
-                            fromToken(TopAppBarSmallTokens.OnScrollContainerColor),
-                        navigationIconContentColor =
-                            fromToken(TopAppBarLargeTokens.LeadingIconColor),
-                        titleContentColor = fromToken(TopAppBarLargeTokens.HeadlineColor),
-                        actionIconContentColor = fromToken(TopAppBarLargeTokens.TrailingIconColor),
-                    )
-                    .also { defaultLargeTopAppBarColorsCached = it }
-        }
-
     /**
      * Returns a pinned [TopAppBarScrollBehavior] that tracks nested-scroll callbacks and updates
      * its [TopAppBarState.contentOffset] accordingly.
@@ -1701,31 +1734,35 @@
         }
 
     /** The default expanded height of a [TopAppBar] and the [CenterAlignedTopAppBar]. */
-    val TopAppBarExpandedHeight: Dp = TopAppBarSmallTokens.ContainerHeight
+    val TopAppBarExpandedHeight: Dp = AppBarSmallTokens.ContainerHeight
 
     /** The default height of a [MediumTopAppBar] when collapsed by a [TopAppBarScrollBehavior]. */
-    val MediumAppBarCollapsedHeight: Dp = TopAppBarSmallTokens.ContainerHeight
+    val MediumAppBarCollapsedHeight: Dp = AppBarSmallTokens.ContainerHeight
 
     /** The default expanded height of a [MediumTopAppBar]. */
-    val MediumAppBarExpandedHeight: Dp = TopAppBarMediumTokens.ContainerHeight
+    val MediumAppBarExpandedHeight: Dp = AppBarMediumTokens.ContainerHeight
 
-    /** The default expanded height of a [MediumTopAppBar] without subtitle. */
-    val MediumAppBarWithoutSubtitleExpandedHeight: Dp = 104.dp // TODO tokens
+    /** The default expanded height of a [MediumFlexibleTopAppBar] without subtitle. */
+    val MediumFlexibleAppBarWithoutSubtitleExpandedHeight: Dp =
+        AppBarMediumFlexibleTokens.ContainerHeight
 
-    /** The default expanded height of a [MediumTopAppBar] with subtitle. */
-    val MediumAppBarWithSubtitleExpandedHeight: Dp = 124.dp // TODO tokens
+    /** The default expanded height of a [MediumFlexibleTopAppBar] with subtitle. */
+    val MediumFlexibleAppBarWithSubtitleExpandedHeight: Dp =
+        AppBarMediumFlexibleTokens.LargeContainerHeight
 
     /** The default height of a [LargeTopAppBar] when collapsed by a [TopAppBarScrollBehavior]. */
-    val LargeAppBarCollapsedHeight: Dp = TopAppBarSmallTokens.ContainerHeight
+    val LargeAppBarCollapsedHeight: Dp = AppBarSmallTokens.ContainerHeight
 
     /** The default expanded height of a [LargeTopAppBar]. */
-    val LargeAppBarExpandedHeight: Dp = TopAppBarLargeTokens.ContainerHeight
+    val LargeAppBarExpandedHeight: Dp = AppBarLargeTokens.ContainerHeight
 
-    /** The default expanded height of a [LargeTopAppBar] without subtitle. */
-    val LargeAppBarWithoutSubtitleExpandedHeight: Dp = 120.dp // TODO tokens
+    /** The default expanded height of a [LargeFlexibleTopAppBar] without subtitle. */
+    val LargeFlexibleAppBarWithoutSubtitleExpandedHeight: Dp =
+        AppBarLargeFlexibleTokens.ContainerHeight
 
-    /** The default expanded height of a [LargeTopAppBar] with subtitle. */
-    val LargeAppBarWithSubtitleExpandedHeight: Dp = 144.dp // TODO tokens
+    /** The default expanded height of a [LargeFlexibleTopAppBar] with subtitle. */
+    val LargeFlexibleAppBarWithSubtitleExpandedHeight: Dp =
+        AppBarLargeFlexibleTokens.LargeContainerHeight
 }
 
 /**
@@ -1863,19 +1900,45 @@
  * @param navigationIconContentColor the content color used for the navigation icon
  * @param titleContentColor the content color used for the title
  * @param actionIconContentColor the content color used for actions
+ * @param subtitleContentColor the content color used for a subtitle
  * @constructor create an instance with arbitrary colors, see [TopAppBarColors] for a factory method
  *   using the default material3 spec
  */
 @ExperimentalMaterial3Api
 @Stable
-class TopAppBarColors
-constructor(
+class TopAppBarColors(
     val containerColor: Color,
     val scrolledContainerColor: Color,
     val navigationIconContentColor: Color,
     val titleContentColor: Color,
     val actionIconContentColor: Color,
+    val subtitleContentColor: Color
 ) {
+    @Deprecated(
+        "Use the TopAppBarColors constructor with subtitleContentColor",
+        replaceWith =
+            ReplaceWith(
+                "TopAppBarColors(containerColor, scrolledContainerColor," +
+                    "navigationIconContentColor, titleContentColor, actionIconContentColor, " +
+                    "subtitleContentColor)"
+            ),
+        DeprecationLevel.WARNING
+    )
+    constructor(
+        containerColor: Color,
+        scrolledContainerColor: Color,
+        navigationIconContentColor: Color,
+        titleContentColor: Color,
+        actionIconContentColor: Color
+    ) : this(
+        containerColor = containerColor,
+        scrolledContainerColor = scrolledContainerColor,
+        navigationIconContentColor = navigationIconContentColor,
+        titleContentColor = titleContentColor,
+        actionIconContentColor = actionIconContentColor,
+        subtitleContentColor = titleContentColor
+    )
+
     /**
      * Returns a copy of this TopAppBarColors, optionally overriding some of the values. This uses
      * the Color.Unspecified to mean “use the value from the source”
@@ -1886,6 +1949,7 @@
         navigationIconContentColor: Color = this.navigationIconContentColor,
         titleContentColor: Color = this.titleContentColor,
         actionIconContentColor: Color = this.actionIconContentColor,
+        subtitleContentColor: Color = this.subtitleContentColor,
     ) =
         TopAppBarColors(
             containerColor.takeOrElse { this.containerColor },
@@ -1893,6 +1957,7 @@
             navigationIconContentColor.takeOrElse { this.navigationIconContentColor },
             titleContentColor.takeOrElse { this.titleContentColor },
             actionIconContentColor.takeOrElse { this.actionIconContentColor },
+            subtitleContentColor.takeOrElse { this.subtitleContentColor },
         )
 
     /**
@@ -1923,6 +1988,7 @@
         if (navigationIconContentColor != other.navigationIconContentColor) return false
         if (titleContentColor != other.titleContentColor) return false
         if (actionIconContentColor != other.actionIconContentColor) return false
+        if (subtitleContentColor != other.subtitleContentColor) return false
 
         return true
     }
@@ -1933,27 +1999,12 @@
         result = 31 * result + navigationIconContentColor.hashCode()
         result = 31 * result + titleContentColor.hashCode()
         result = 31 * result + actionIconContentColor.hashCode()
+        result = 31 * result + subtitleContentColor.hashCode()
 
         return result
     }
 }
 
-/** This class defines ways title and subtitle can be aligned along a TopAppBar's main axis. */
-@ExperimentalMaterial3ExpressiveApi
-@JvmInline
-value class TopAppBarTitleAlignment private constructor(internal val value: Int) {
-    companion object {
-        /** Start align the title and subtitle if present */
-        val Start = TopAppBarTitleAlignment(-1)
-
-        /** Center align the title and subtitle if present */
-        val Center = TopAppBarTitleAlignment(0)
-
-        /** End align the title and subtitle if present */
-        val End = TopAppBarTitleAlignment(1)
-    }
-}
-
 /**
  * A BottomAppBarScrollBehavior defines how a bottom app bar should behave when the content under it
  * is scrolled.
@@ -2335,7 +2386,7 @@
     titleTextStyle: TextStyle,
     subtitle: (@Composable () -> Unit)?,
     subtitleTextStyle: TextStyle,
-    titleHorizontalAlignment: TopAppBarTitleAlignment,
+    titleHorizontalAlignment: Alignment.Horizontal,
     navigationIcon: @Composable () -> Unit,
     actions: @Composable RowScope.() -> Unit,
     expandedHeight: Dp,
@@ -2423,6 +2474,7 @@
             navigationIconContentColor = colors.navigationIconContentColor,
             titleContentColor = colors.titleContentColor,
             actionIconContentColor = colors.actionIconContentColor,
+            subtitleContentColor = colors.subtitleContentColor,
             title = title,
             titleTextStyle = titleTextStyle,
             subtitle = subtitle,
@@ -2456,7 +2508,7 @@
     subtitleTextStyle: TextStyle,
     smallSubtitle: (@Composable () -> Unit)?,
     smallSubtitleTextStyle: TextStyle,
-    titleHorizontalAlignment: TopAppBarTitleAlignment,
+    titleHorizontalAlignment: Alignment.Horizontal,
     navigationIcon: @Composable () -> Unit,
     actions: @Composable RowScope.() -> Unit,
     collapsedHeight: Dp,
@@ -2540,6 +2592,7 @@
                 navigationIconContentColor = colors.navigationIconContentColor,
                 titleContentColor = colors.titleContentColor,
                 actionIconContentColor = colors.actionIconContentColor,
+                subtitleContentColor = colors.subtitleContentColor,
                 title = smallTitle,
                 titleTextStyle = smallTitleTextStyle,
                 subtitle = smallSubtitle,
@@ -2566,6 +2619,7 @@
                 navigationIconContentColor = colors.navigationIconContentColor,
                 titleContentColor = colors.titleContentColor,
                 actionIconContentColor = colors.actionIconContentColor,
+                subtitleContentColor = colors.subtitleContentColor,
                 title = title,
                 titleTextStyle = titleTextStyle,
                 subtitle = subtitle,
@@ -2604,6 +2658,8 @@
  *   [LocalContentColor] when composing the navigation icon
  * @param titleContentColor the color that will be applied via a [LocalContentColor] when composing
  *   the title
+ * @param subtitleContentColor the color that will be applied via a [LocalContentColor] when
+ *   composing the subtitle
  * @param actionIconContentColor the content color that will be applied via a [LocalContentColor]
  *   when composing the action icons
  * @param title the top app bar title (header)
@@ -2627,6 +2683,7 @@
     scrolledOffset: FloatProducer,
     navigationIconContentColor: Color,
     titleContentColor: Color,
+    subtitleContentColor: Color,
     actionIconContentColor: Color,
     title: @Composable () -> Unit,
     titleTextStyle: TextStyle,
@@ -2634,7 +2691,7 @@
     subtitleTextStyle: TextStyle,
     titleAlpha: () -> Float,
     titleVerticalArrangement: Arrangement.Vertical,
-    titleHorizontalAlignment: TopAppBarTitleAlignment,
+    titleHorizontalAlignment: Alignment.Horizontal,
     titleBottomPadding: Int,
     hideTitleSemantics: Boolean,
     navigationIcon: @Composable () -> Unit,
@@ -2659,20 +2716,18 @@
                                 else Modifier
                             )
                             .graphicsLayer { alpha = titleAlpha() },
-                    horizontalAlignment =
-                        when (titleHorizontalAlignment) {
-                            TopAppBarTitleAlignment.Start -> Alignment.Start
-                            TopAppBarTitleAlignment.Center -> Alignment.CenterHorizontally
-                            else -> Alignment.End
-                        }
+                    horizontalAlignment = titleHorizontalAlignment
                 ) {
                     ProvideContentColorTextStyle(
                         contentColor = titleContentColor,
-                        textStyle = titleTextStyle
-                    ) {
-                        title()
-                        ProvideTextStyle(value = subtitleTextStyle, content = subtitle)
-                    }
+                        textStyle = titleTextStyle,
+                        content = title
+                    )
+                    ProvideContentColorTextStyle(
+                        contentColor = subtitleContentColor,
+                        textStyle = subtitleTextStyle,
+                        content = subtitle
+                    )
                 }
             } else { // TODO(b/352770398): Workaround to maintain compatibility
                 Box(
@@ -2723,7 +2778,7 @@
 private class TopAppBarMeasurePolicy(
     val scrolledOffset: FloatProducer,
     val titleVerticalArrangement: Arrangement.Vertical,
-    val titleHorizontalAlignment: TopAppBarTitleAlignment,
+    val titleHorizontalAlignment: Alignment.Horizontal,
     val titleBottomPadding: Int,
     val expandedHeight: Dp
 ) : MeasurePolicy {
@@ -2834,7 +2889,7 @@
             titlePlaceable.placeRelative(
                 x =
                     when (titleHorizontalAlignment) {
-                        TopAppBarTitleAlignment.Center -> {
+                        Alignment.CenterHorizontally -> {
                             var baseX = (constraints.maxWidth - titlePlaceable.width) / 2
                             if (baseX < navigationIconPlaceable.width) {
                                 // May happen if the navigation is wider than the actions and the
@@ -2853,10 +2908,10 @@
                             }
                             baseX
                         }
-                        TopAppBarTitleAlignment.End ->
+                        Alignment.End ->
                             constraints.maxWidth - titlePlaceable.width - actionIconsPlaceable.width
-                        // TopAppBarTitleAlignment.Start
-                        // An TopAppBarTitleInset will make sure the title is offset in case the
+                        // Fallback to Alignment.Start.
+                        // A TopAppBarTitleInset will make sure the title is offset in case the
                         // navigation icon is missing.
                         else -> max(TopAppBarTitleInset.roundToPx(), navigationIconPlaceable.width)
                     },
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ColorScheme.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ColorScheme.kt
index f5d79e0..7970794 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ColorScheme.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ColorScheme.kt
@@ -479,12 +479,6 @@
 
     @OptIn(ExperimentalMaterial3Api::class)
     internal var defaultTopAppBarColorsCached: TopAppBarColors? = null
-    @OptIn(ExperimentalMaterial3Api::class)
-    internal var defaultCenterAlignedTopAppBarColorsCached: TopAppBarColors? = null
-    @OptIn(ExperimentalMaterial3Api::class)
-    internal var defaultMediumTopAppBarColorsCached: TopAppBarColors? = null
-    @OptIn(ExperimentalMaterial3Api::class)
-    internal var defaultLargeTopAppBarColorsCached: TopAppBarColors? = null
 
     internal var defaultCheckboxColorsCached: CheckboxColors? = null
 
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButton.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButton.kt
index 5c5f840..394c6a4 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButton.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButton.kt
@@ -29,38 +29,20 @@
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material3.internal.childSemantics
 import androidx.compose.material3.internal.rememberAnimatedShape
-import androidx.compose.material3.tokens.FilledIconButtonTokens
-import androidx.compose.material3.tokens.FilledTonalIconButtonTokens
-import androidx.compose.material3.tokens.LargeIconButtonTokens
-import androidx.compose.material3.tokens.MediumIconButtonTokens
 import androidx.compose.material3.tokens.MotionSchemeKeyTokens
-import androidx.compose.material3.tokens.OutlinedIconButtonTokens
-import androidx.compose.material3.tokens.SmallIconButtonTokens
-import androidx.compose.material3.tokens.StandardIconButtonTokens
-import androidx.compose.material3.tokens.XLargeIconButtonTokens
-import androidx.compose.material3.tokens.XSmallIconButtonTokens
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.Immutable
-import androidx.compose.runtime.Stable
-import androidx.compose.runtime.State
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.key
 import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberUpdatedState
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
-import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.graphics.takeOrElse
 import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.semantics.role
 import androidx.compose.ui.semantics.semantics
-import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.DpSize
 import androidx.compose.ui.unit.dp
-import kotlin.jvm.JvmInline
 
 /**
  * <a href="https://m3.material.io/components/icon-button/overview" class="external"
@@ -1071,1339 +1053,6 @@
     return shapeByInteraction(shapes, pressed, checked, defaultAnimationSpec)
 }
 
-/** Contains the default values for all four icon and icon toggle button types. */
-object IconButtonDefaults {
-    /**
-     * Contains the default values used by [IconButton]. [LocalContentColor] will be applied to the
-     * icon and down the UI tree.
-     *
-     * See [iconButtonVibrantColors] for default values that applies the recommended high contrast
-     * colors.
-     */
-    @Composable
-    fun iconButtonColors(): IconButtonColors {
-        val contentColor = LocalContentColor.current
-        val colors = MaterialTheme.colorScheme.defaultIconButtonColors(contentColor)
-        return if (colors.contentColor == contentColor) {
-            colors
-        } else {
-            colors.copy(
-                contentColor = contentColor,
-                disabledContentColor =
-                    contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity)
-            )
-        }
-    }
-
-    /**
-     * Creates a [IconButtonColors] that represents the default colors used in a [IconButton].
-     * [LocalContentColor] will be applied to the icon and down the UI tree unless a custom
-     * [contentColor] is provided.
-     *
-     * See [iconButtonVibrantColors] for default values that applies the recommended high contrast
-     * colors.
-     *
-     * @param containerColor the container color of this icon button when enabled.
-     * @param contentColor the content color of this icon button when enabled. By default, this will
-     *   use the current LocalContentColor value.
-     * @param disabledContainerColor the container color of this icon button when not enabled.
-     * @param disabledContentColor the content color of this icon button when not enabled.
-     */
-    @Composable
-    fun iconButtonColors(
-        containerColor: Color = Color.Unspecified,
-        contentColor: Color = LocalContentColor.current,
-        disabledContainerColor: Color = Color.Unspecified,
-        disabledContentColor: Color =
-            contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity)
-    ): IconButtonColors =
-        MaterialTheme.colorScheme
-            .defaultIconButtonColors(LocalContentColor.current)
-            .copy(
-                containerColor = containerColor,
-                contentColor = contentColor,
-                disabledContainerColor = disabledContainerColor,
-                disabledContentColor = disabledContentColor,
-            )
-
-    internal fun ColorScheme.defaultIconButtonColors(localContentColor: Color): IconButtonColors {
-        return defaultIconButtonColorsCached
-            ?: run {
-                IconButtonColors(
-                        containerColor = Color.Transparent,
-                        contentColor = localContentColor,
-                        disabledContainerColor = Color.Transparent,
-                        disabledContentColor =
-                            localContentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity)
-                    )
-                    .also { defaultIconButtonColorsCached = it }
-            }
-    }
-
-    /**
-     * Creates a [IconButtonColors] that represents the recommended high contrast colors used in an
-     * [IconButton].
-     *
-     * See [iconButtonColors] for default values that applies [LocalContentColor] to the icon and
-     * down the UI tree.
-     */
-    @Composable
-    fun iconButtonVibrantColors(): IconButtonColors =
-        MaterialTheme.colorScheme.defaultIconButtonVibrantColors()
-
-    /**
-     * Creates a [IconButtonColors] that represents the recommended high contrast colors used in an
-     * [IconButton].
-     *
-     * See [iconButtonColors] for default values that applies [LocalContentColor] to the icon and
-     * down the UI tree.
-     *
-     * @param containerColor the container color of this icon button when enabled.
-     * @param contentColor the content color of this icon button when enabled.
-     * @param disabledContainerColor the container color of this icon button when not enabled.
-     * @param disabledContentColor the content color of this icon button when not enabled.
-     */
-    @Composable
-    fun iconButtonVibrantColors(
-        containerColor: Color = Color.Unspecified,
-        contentColor: Color = Color.Unspecified,
-        disabledContainerColor: Color = Color.Unspecified,
-        disabledContentColor: Color =
-            contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity)
-    ): IconButtonColors =
-        MaterialTheme.colorScheme
-            .defaultIconButtonVibrantColors()
-            .copy(
-                containerColor = containerColor,
-                contentColor = contentColor,
-                disabledContainerColor = disabledContainerColor,
-                disabledContentColor = disabledContentColor,
-            )
-
-    internal fun ColorScheme.defaultIconButtonVibrantColors(): IconButtonColors {
-        return defaultIconButtonVibrantColorsCached
-            ?: run {
-                IconButtonColors(
-                        containerColor = Color.Transparent,
-                        contentColor = fromToken(StandardIconButtonTokens.Color),
-                        disabledContainerColor = Color.Transparent,
-                        disabledContentColor =
-                            fromToken(StandardIconButtonTokens.DisabledColor)
-                                .copy(alpha = StandardIconButtonTokens.DisabledOpacity)
-                    )
-                    .also { defaultIconButtonVibrantColorsCached = it }
-            }
-    }
-
-    /**
-     * Creates a [IconToggleButtonColors] that represents the default colors used in a
-     * [IconToggleButton]. [LocalContentColor] will be applied to the icon and down the UI tree.
-     *
-     * See [iconToggleButtonVibrantColors] for default values that applies the recommended high
-     * contrast colors.
-     */
-    @Composable
-    fun iconToggleButtonColors(): IconToggleButtonColors {
-        val contentColor = LocalContentColor.current
-        val colors = MaterialTheme.colorScheme.defaultIconToggleButtonColors(contentColor)
-        if (colors.contentColor == contentColor) {
-            return colors
-        } else {
-            return colors.copy(
-                contentColor = contentColor,
-                disabledContentColor =
-                    contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity)
-            )
-        }
-    }
-
-    /**
-     * Creates a [IconToggleButtonColors] that represents the default colors used in a
-     * [IconToggleButton]. [LocalContentColor] will be applied to the icon and down the UI tree
-     * unless a custom [contentColor] is provided.
-     *
-     * See [iconToggleButtonVibrantColors] for default values that applies the recommended high
-     * contrast colors.
-     *
-     * @param containerColor the container color of this icon button when enabled.
-     * @param contentColor the content color of this icon button when enabled.
-     * @param disabledContainerColor the container color of this icon button when not enabled.
-     * @param disabledContentColor the content color of this icon button when not enabled.
-     * @param checkedContainerColor the container color of this icon button when checked.
-     * @param checkedContentColor the content color of this icon button when checked.
-     */
-    @Composable
-    fun iconToggleButtonColors(
-        containerColor: Color = Color.Unspecified,
-        contentColor: Color = LocalContentColor.current,
-        disabledContainerColor: Color = Color.Unspecified,
-        disabledContentColor: Color =
-            contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity),
-        checkedContainerColor: Color = Color.Unspecified,
-        checkedContentColor: Color = Color.Unspecified
-    ): IconToggleButtonColors =
-        MaterialTheme.colorScheme
-            .defaultIconToggleButtonColors(LocalContentColor.current)
-            .copy(
-                containerColor = containerColor,
-                contentColor = contentColor,
-                disabledContainerColor = disabledContainerColor,
-                disabledContentColor = disabledContentColor,
-                checkedContainerColor = checkedContainerColor,
-                checkedContentColor = checkedContentColor,
-            )
-
-    internal fun ColorScheme.defaultIconToggleButtonColors(
-        localContentColor: Color
-    ): IconToggleButtonColors {
-        return defaultIconToggleButtonColorsCached
-            ?: run {
-                IconToggleButtonColors(
-                        containerColor = Color.Transparent,
-                        contentColor = localContentColor,
-                        disabledContainerColor = Color.Transparent,
-                        disabledContentColor =
-                            localContentColor.copy(
-                                alpha = StandardIconButtonTokens.DisabledOpacity
-                            ),
-                        checkedContainerColor = Color.Transparent,
-                        checkedContentColor = fromToken(StandardIconButtonTokens.SelectedColor)
-                    )
-                    .also { defaultIconToggleButtonColorsCached = it }
-            }
-    }
-
-    /**
-     * Creates a [IconToggleButtonColors] that represents the recommended high contrast colors used
-     * in a [IconToggleButton]. See [iconToggleButtonColors] for default values that applies
-     * [LocalContentColor] to the icon and down the UI tree.
-     */
-    @Composable
-    fun iconToggleButtonVibrantColors(): IconToggleButtonColors =
-        MaterialTheme.colorScheme.defaultIconToggleButtonVibrantColors()
-
-    /**
-     * Creates a [IconToggleButtonColors] that represents the recommended high contrast colors used
-     * in a [IconToggleButton].
-     *
-     * See [iconToggleButtonColors] for default values that applies [LocalContentColor] to the icon
-     * and down the UI tree.
-     *
-     * @param containerColor the container color of this icon button when enabled.
-     * @param contentColor the content color of this icon button when enabled.
-     * @param disabledContainerColor the container color of this icon button when not enabled.
-     * @param disabledContentColor the content color of this icon button when not enabled.
-     * @param checkedContainerColor the container color of this icon button when checked.
-     * @param checkedContentColor the content color of this icon button when checked.
-     */
-    @Composable
-    fun iconToggleButtonVibrantColors(
-        containerColor: Color = Color.Unspecified,
-        contentColor: Color = Color.Unspecified,
-        disabledContainerColor: Color = Color.Unspecified,
-        disabledContentColor: Color =
-            contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity),
-        checkedContainerColor: Color = Color.Unspecified,
-        checkedContentColor: Color = Color.Unspecified
-    ): IconToggleButtonColors =
-        MaterialTheme.colorScheme
-            .defaultIconToggleButtonVibrantColors()
-            .copy(
-                containerColor = containerColor,
-                contentColor = contentColor,
-                disabledContainerColor = disabledContainerColor,
-                disabledContentColor = disabledContentColor,
-                checkedContainerColor = checkedContainerColor,
-                checkedContentColor = checkedContentColor,
-            )
-
-    internal fun ColorScheme.defaultIconToggleButtonVibrantColors(): IconToggleButtonColors {
-        return defaultIconToggleButtonVibrantColorsCached
-            ?: run {
-                IconToggleButtonColors(
-                        containerColor = Color.Transparent,
-                        contentColor = fromToken(StandardIconButtonTokens.UnselectedColor),
-                        disabledContainerColor = Color.Transparent,
-                        disabledContentColor =
-                            fromToken(StandardIconButtonTokens.DisabledColor)
-                                .copy(alpha = StandardIconButtonTokens.DisabledOpacity),
-                        checkedContainerColor = Color.Transparent,
-                        checkedContentColor = fromToken(StandardIconButtonTokens.SelectedColor)
-                    )
-                    .also { defaultIconToggleButtonVibrantColorsCached = it }
-            }
-    }
-
-    /**
-     * Creates a [IconButtonColors] that represents the default colors used in a [FilledIconButton].
-     */
-    @Composable
-    fun filledIconButtonColors(): IconButtonColors =
-        MaterialTheme.colorScheme.defaultFilledIconButtonColors
-
-    /**
-     * Creates a [IconButtonColors] that represents the default colors used in a [FilledIconButton].
-     *
-     * @param containerColor the container color of this icon button when enabled.
-     * @param contentColor the content color of this icon button when enabled.
-     * @param disabledContainerColor the container color of this icon button when not enabled.
-     * @param disabledContentColor the content color of this icon button when not enabled.
-     */
-    @Composable
-    fun filledIconButtonColors(
-        containerColor: Color = Color.Unspecified,
-        contentColor: Color = contentColorFor(containerColor),
-        disabledContainerColor: Color = Color.Unspecified,
-        disabledContentColor: Color = Color.Unspecified
-    ): IconButtonColors =
-        MaterialTheme.colorScheme.defaultFilledIconButtonColors.copy(
-            containerColor = containerColor,
-            contentColor = contentColor,
-            disabledContainerColor = disabledContainerColor,
-            disabledContentColor = disabledContentColor,
-        )
-
-    internal val ColorScheme.defaultFilledIconButtonColors: IconButtonColors
-        get() {
-            return defaultFilledIconButtonColorsCached
-                ?: IconButtonColors(
-                        containerColor = fromToken(FilledIconButtonTokens.ContainerColor),
-                        contentColor = fromToken(FilledIconButtonTokens.Color),
-                        disabledContainerColor =
-                            fromToken(FilledIconButtonTokens.DisabledContainerColor)
-                                .copy(alpha = FilledIconButtonTokens.DisabledContainerOpacity),
-                        disabledContentColor =
-                            fromToken(FilledIconButtonTokens.DisabledColor)
-                                .copy(alpha = FilledIconButtonTokens.DisabledOpacity)
-                    )
-                    .also { defaultFilledIconButtonColorsCached = it }
-        }
-
-    /**
-     * Creates a [IconToggleButtonColors] that represents the default colors used in a
-     * [FilledIconToggleButton].
-     */
-    @Composable
-    fun filledIconToggleButtonColors(): IconToggleButtonColors =
-        MaterialTheme.colorScheme.defaultFilledIconToggleButtonColors
-
-    /**
-     * Creates a [IconToggleButtonColors] that represents the default colors used in a
-     * [FilledIconToggleButton].
-     *
-     * @param containerColor the container color of this icon button when enabled.
-     * @param contentColor the content color of this icon button when enabled.
-     * @param disabledContainerColor the container color of this icon button when not enabled.
-     * @param disabledContentColor the content color of this icon button when not enabled.
-     * @param checkedContainerColor the container color of this icon button when checked.
-     * @param checkedContentColor the content color of this icon button when checked.
-     */
-    @Composable
-    fun filledIconToggleButtonColors(
-        containerColor: Color = Color.Unspecified,
-        // TODO(b/228455081): Using contentColorFor here will return OnSurfaceVariant,
-        //  while the token value is Primary.
-        contentColor: Color = Color.Unspecified,
-        disabledContainerColor: Color = Color.Unspecified,
-        disabledContentColor: Color = Color.Unspecified,
-        checkedContainerColor: Color = Color.Unspecified,
-        checkedContentColor: Color = contentColorFor(checkedContainerColor)
-    ): IconToggleButtonColors =
-        MaterialTheme.colorScheme.defaultFilledIconToggleButtonColors.copy(
-            containerColor = containerColor,
-            contentColor = contentColor,
-            disabledContainerColor = disabledContainerColor,
-            disabledContentColor = disabledContentColor,
-            checkedContainerColor = checkedContainerColor,
-            checkedContentColor = checkedContentColor,
-        )
-
-    internal val ColorScheme.defaultFilledIconToggleButtonColors: IconToggleButtonColors
-        get() {
-            return defaultFilledIconToggleButtonColorsCached
-                ?: IconToggleButtonColors(
-                        containerColor = fromToken(FilledIconButtonTokens.UnselectedContainerColor),
-                        // TODO(b/228455081): Using contentColorFor here will return
-                        // OnSurfaceVariant,
-                        //  while the token value is Primary.
-                        contentColor = fromToken(FilledIconButtonTokens.UnselectedColor),
-                        disabledContainerColor =
-                            fromToken(FilledIconButtonTokens.DisabledContainerColor)
-                                .copy(alpha = FilledIconButtonTokens.DisabledContainerOpacity),
-                        disabledContentColor =
-                            fromToken(FilledIconButtonTokens.DisabledColor)
-                                .copy(alpha = FilledIconButtonTokens.DisabledOpacity),
-                        checkedContainerColor =
-                            fromToken(FilledIconButtonTokens.SelectedContainerColor),
-                        checkedContentColor = fromToken(FilledIconButtonTokens.SelectedColor)
-                    )
-                    .also { defaultFilledIconToggleButtonColorsCached = it }
-        }
-
-    /**
-     * Creates a [IconButtonColors] that represents the default colors used in a
-     * [FilledTonalIconButton].
-     */
-    @Composable
-    fun filledTonalIconButtonColors(): IconButtonColors =
-        MaterialTheme.colorScheme.defaultFilledTonalIconButtonColors
-
-    /**
-     * Creates a [IconButtonColors] that represents the default colors used in a
-     * [FilledTonalIconButton].
-     *
-     * @param containerColor the container color of this icon button when enabled.
-     * @param contentColor the content color of this icon button when enabled.
-     * @param disabledContainerColor the container color of this icon button when not enabled.
-     * @param disabledContentColor the content color of this icon button when not enabled.
-     */
-    @Composable
-    fun filledTonalIconButtonColors(
-        containerColor: Color = Color.Unspecified,
-        contentColor: Color = contentColorFor(containerColor),
-        disabledContainerColor: Color = Color.Unspecified,
-        disabledContentColor: Color = Color.Unspecified
-    ): IconButtonColors =
-        MaterialTheme.colorScheme.defaultFilledTonalIconButtonColors.copy(
-            containerColor = containerColor,
-            contentColor = contentColor,
-            disabledContainerColor = disabledContainerColor,
-            disabledContentColor = disabledContentColor,
-        )
-
-    internal val ColorScheme.defaultFilledTonalIconButtonColors: IconButtonColors
-        get() {
-            return defaultFilledTonalIconButtonColorsCached
-                ?: IconButtonColors(
-                        containerColor = fromToken(FilledTonalIconButtonTokens.ContainerColor),
-                        contentColor = fromToken(FilledTonalIconButtonTokens.Color),
-                        disabledContainerColor =
-                            fromToken(FilledTonalIconButtonTokens.DisabledContainerColor)
-                                .copy(alpha = FilledTonalIconButtonTokens.DisabledContainerOpacity),
-                        disabledContentColor =
-                            fromToken(FilledTonalIconButtonTokens.DisabledColor)
-                                .copy(alpha = FilledTonalIconButtonTokens.DisabledOpacity)
-                    )
-                    .also { defaultFilledTonalIconButtonColorsCached = it }
-        }
-
-    /**
-     * Creates a [IconToggleButtonColors] that represents the default colors used in a
-     * [FilledTonalIconToggleButton].
-     */
-    @Composable
-    fun filledTonalIconToggleButtonColors(): IconToggleButtonColors =
-        MaterialTheme.colorScheme.defaultFilledTonalIconToggleButtonColors
-
-    /**
-     * Creates a [IconToggleButtonColors] that represents the default colors used in a
-     * [FilledTonalIconToggleButton].
-     *
-     * @param containerColor the container color of this icon button when enabled.
-     * @param contentColor the content color of this icon button when enabled.
-     * @param disabledContainerColor the container color of this icon button when not enabled.
-     * @param disabledContentColor the content color of this icon button when not enabled.
-     * @param checkedContainerColor the container color of this icon button when checked.
-     * @param checkedContentColor the content color of this icon button when checked.
-     */
-    @Composable
-    fun filledTonalIconToggleButtonColors(
-        containerColor: Color = Color.Unspecified,
-        contentColor: Color = contentColorFor(containerColor),
-        disabledContainerColor: Color = Color.Unspecified,
-        disabledContentColor: Color = Color.Unspecified,
-        checkedContainerColor: Color = Color.Unspecified,
-        checkedContentColor: Color = contentColorFor(checkedContainerColor)
-    ): IconToggleButtonColors =
-        MaterialTheme.colorScheme.defaultFilledTonalIconToggleButtonColors.copy(
-            containerColor = containerColor,
-            contentColor = contentColor,
-            disabledContainerColor = disabledContainerColor,
-            disabledContentColor = disabledContentColor,
-            checkedContainerColor = checkedContainerColor,
-            checkedContentColor = checkedContentColor,
-        )
-
-    internal val ColorScheme.defaultFilledTonalIconToggleButtonColors: IconToggleButtonColors
-        get() {
-            return defaultFilledTonalIconToggleButtonColorsCached
-                ?: IconToggleButtonColors(
-                        containerColor =
-                            fromToken(FilledTonalIconButtonTokens.UnselectedContainerColor),
-                        contentColor = fromToken(FilledTonalIconButtonTokens.UnselectedColor),
-                        disabledContainerColor =
-                            fromToken(FilledTonalIconButtonTokens.DisabledContainerColor)
-                                .copy(alpha = FilledTonalIconButtonTokens.DisabledContainerOpacity),
-                        disabledContentColor =
-                            fromToken(FilledTonalIconButtonTokens.DisabledColor)
-                                .copy(alpha = FilledTonalIconButtonTokens.DisabledOpacity),
-                        checkedContainerColor =
-                            fromToken(FilledTonalIconButtonTokens.SelectedContainerColor),
-                        checkedContentColor = fromToken(FilledTonalIconButtonTokens.SelectedColor)
-                    )
-                    .also { defaultFilledTonalIconToggleButtonColorsCached = it }
-        }
-
-    /**
-     * Creates a [IconButtonColors] that represents the default colors used in a
-     * [OutlinedIconButton]. [LocalContentColor] will be applied to the icon and down the UI tree.
-     *
-     * See [outlinedIconButtonVibrantColors] for default values that applies the recommended high
-     * contrast colors.
-     */
-    @Composable
-    fun outlinedIconButtonColors(): IconButtonColors {
-        val contentColor = LocalContentColor.current
-        val colors = MaterialTheme.colorScheme.defaultOutlinedIconButtonColors(contentColor)
-        if (colors.contentColor == contentColor) {
-            return colors
-        } else {
-            return colors.copy(
-                contentColor = contentColor,
-                disabledContentColor =
-                    contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity)
-            )
-        }
-    }
-
-    /**
-     * Creates a [IconButtonColors] that represents the default colors used in a
-     * [OutlinedIconButton].
-     *
-     * See [outlinedIconButtonVibrantColors] for default values that applies the recommended high
-     * contrast colors.
-     *
-     * @param containerColor the container color of this icon button when enabled.
-     * @param contentColor the content color of this icon button when enabled.
-     * @param disabledContainerColor the container color of this icon button when not enabled.
-     * @param disabledContentColor the content color of this icon button when not enabled.
-     */
-    @Composable
-    fun outlinedIconButtonColors(
-        containerColor: Color = Color.Unspecified,
-        contentColor: Color = LocalContentColor.current,
-        disabledContainerColor: Color = Color.Unspecified,
-        disabledContentColor: Color =
-            contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity)
-    ): IconButtonColors =
-        MaterialTheme.colorScheme
-            .defaultOutlinedIconButtonColors(LocalContentColor.current)
-            .copy(
-                containerColor = containerColor,
-                contentColor = contentColor,
-                disabledContainerColor = disabledContainerColor,
-                disabledContentColor = disabledContentColor,
-            )
-
-    internal fun ColorScheme.defaultOutlinedIconButtonColors(
-        localContentColor: Color
-    ): IconButtonColors {
-        return defaultOutlinedIconButtonColorsCached
-            ?: run {
-                IconButtonColors(
-                        containerColor = Color.Transparent,
-                        contentColor = localContentColor,
-                        disabledContainerColor = Color.Transparent,
-                        disabledContentColor =
-                            localContentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity)
-                    )
-                    .also { defaultOutlinedIconButtonColorsCached = it }
-            }
-    }
-
-    /**
-     * Creates a [IconButtonColors] that represents the default colors used in a
-     * [OutlinedIconButton].
-     *
-     * See [outlinedIconButtonColors] for default values that applies [LocalContentColor] to the
-     * icon and down the UI tree.
-     */
-    @Composable
-    fun outlinedIconButtonVibrantColors(): IconButtonColors =
-        MaterialTheme.colorScheme.defaultOutlinedIconButtonVibrantColors()
-
-    /**
-     * Creates a [IconButtonColors] that represents the default colors used in a
-     * [OutlinedIconButton].
-     *
-     * See [outlinedIconButtonColors] for default values that applies [LocalContentColor] to the
-     * icon and down the UI tree.
-     *
-     * @param containerColor the container color of this icon button when enabled.
-     * @param contentColor the content color of this icon button when enabled.
-     * @param disabledContainerColor the container color of this icon button when not enabled.
-     * @param disabledContentColor the content color of this icon button when not enabled.
-     */
-    @Composable
-    fun outlinedIconButtonVibrantColors(
-        containerColor: Color = Color.Unspecified,
-        contentColor: Color = Color.Unspecified,
-        disabledContainerColor: Color = Color.Unspecified,
-        disabledContentColor: Color =
-            contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity)
-    ): IconButtonColors =
-        MaterialTheme.colorScheme
-            .defaultOutlinedIconButtonVibrantColors()
-            .copy(
-                containerColor = containerColor,
-                contentColor = contentColor,
-                disabledContainerColor = disabledContainerColor,
-                disabledContentColor = disabledContentColor,
-            )
-
-    internal fun ColorScheme.defaultOutlinedIconButtonVibrantColors(): IconButtonColors {
-        return defaultOutlinedIconButtonVibrantColorsCached
-            ?: run {
-                IconButtonColors(
-                        containerColor = Color.Transparent,
-                        contentColor = fromToken(OutlinedIconButtonTokens.Color),
-                        disabledContainerColor = Color.Transparent,
-                        disabledContentColor =
-                            fromToken(OutlinedIconButtonTokens.DisabledColor)
-                                .copy(alpha = OutlinedIconButtonTokens.DisabledOpacity)
-                    )
-                    .also { defaultOutlinedIconButtonVibrantColorsCached = it }
-            }
-    }
-
-    /**
-     * Creates a [IconToggleButtonColors] that represents the default colors used in a
-     * [OutlinedIconToggleButton]. [LocalContentColor] will be applied to the icon and down the UI
-     * tree.
-     *
-     * See [outlinedIconButtonVibrantColors] for default values that applies the recommended high
-     * contrast colors.
-     */
-    @Composable
-    fun outlinedIconToggleButtonColors(): IconToggleButtonColors {
-        val contentColor = LocalContentColor.current
-        val colors = MaterialTheme.colorScheme.defaultOutlinedIconToggleButtonColors(contentColor)
-        if (colors.contentColor == contentColor) {
-            return colors
-        } else {
-            return colors.copy(
-                contentColor = contentColor,
-                disabledContentColor =
-                    contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity)
-            )
-        }
-    }
-
-    /**
-     * Creates a [IconToggleButtonColors] that represents the default colors used in a
-     * [OutlinedIconToggleButton]. [LocalContentColor] will be applied to the icon and down the UI
-     * tree.
-     *
-     * See [outlinedIconButtonVibrantColors] for default values that applies the recommended high
-     * contrast colors.
-     *
-     * @param containerColor the container color of this icon button when enabled.
-     * @param contentColor the content color of this icon button when enabled.
-     * @param disabledContainerColor the container color of this icon button when not enabled.
-     * @param disabledContentColor the content color of this icon button when not enabled.
-     * @param checkedContainerColor the container color of this icon button when checked.
-     * @param checkedContentColor the content color of this icon button when checked.
-     */
-    @Composable
-    fun outlinedIconToggleButtonColors(
-        containerColor: Color = Color.Unspecified,
-        contentColor: Color = LocalContentColor.current,
-        disabledContainerColor: Color = Color.Unspecified,
-        disabledContentColor: Color =
-            contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity),
-        checkedContainerColor: Color = Color.Unspecified,
-        checkedContentColor: Color = contentColorFor(checkedContainerColor)
-    ): IconToggleButtonColors =
-        MaterialTheme.colorScheme
-            .defaultOutlinedIconToggleButtonColors(LocalContentColor.current)
-            .copy(
-                containerColor = containerColor,
-                contentColor = contentColor,
-                disabledContainerColor = disabledContainerColor,
-                disabledContentColor = disabledContentColor,
-                checkedContainerColor = checkedContainerColor,
-                checkedContentColor = checkedContentColor,
-            )
-
-    internal fun ColorScheme.defaultOutlinedIconToggleButtonColors(
-        localContentColor: Color
-    ): IconToggleButtonColors {
-        return defaultIconToggleButtonColorsCached
-            ?: run {
-                IconToggleButtonColors(
-                        containerColor = Color.Transparent,
-                        contentColor = localContentColor,
-                        disabledContainerColor = Color.Transparent,
-                        disabledContentColor =
-                            localContentColor.copy(
-                                alpha = OutlinedIconButtonTokens.DisabledOpacity
-                            ),
-                        checkedContainerColor =
-                            fromToken(OutlinedIconButtonTokens.SelectedContainerColor),
-                        checkedContentColor =
-                            contentColorFor(
-                                fromToken(OutlinedIconButtonTokens.SelectedContainerColor)
-                            )
-                    )
-                    .also { defaultOutlinedIconToggleButtonColorsCached = it }
-            }
-    }
-
-    /**
-     * Creates a [IconToggleButtonColors] that represents the default colors used in a
-     * [OutlinedIconToggleButton].
-     *
-     * See [outlinedIconToggleButtonColors] for default values that applies [LocalContentColor] to
-     * the icon and down the UI tree.
-     */
-    @Composable
-    fun outlinedIconToggleButtonVibrantColors(): IconToggleButtonColors =
-        MaterialTheme.colorScheme.defaultOutlinedIconToggleButtonVibrantColors()
-
-    /**
-     * Creates a [IconToggleButtonColors] that represents the default colors used in a
-     * [OutlinedIconToggleButton].
-     *
-     * See [outlinedIconToggleButtonColors] for default values that applies [LocalContentColor] to
-     * the icon and down the UI tree.
-     *
-     * @param containerColor the container color of this icon button when enabled.
-     * @param contentColor the content color of this icon button when enabled.
-     * @param disabledContainerColor the container color of this icon button when not enabled.
-     * @param disabledContentColor the content color of this icon button when not enabled.
-     * @param checkedContainerColor the container color of this icon button when checked.
-     * @param checkedContentColor the content color of this icon button when checked.
-     */
-    @Composable
-    fun outlinedIconToggleButtonVibrantColors(
-        containerColor: Color = Color.Unspecified,
-        contentColor: Color = Color.Unspecified,
-        disabledContainerColor: Color = Color.Unspecified,
-        disabledContentColor: Color =
-            contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity),
-        checkedContainerColor: Color = Color.Unspecified,
-        checkedContentColor: Color = contentColorFor(checkedContainerColor)
-    ): IconToggleButtonColors =
-        MaterialTheme.colorScheme
-            .defaultOutlinedIconToggleButtonVibrantColors()
-            .copy(
-                containerColor = containerColor,
-                contentColor = contentColor,
-                disabledContainerColor = disabledContainerColor,
-                disabledContentColor = disabledContentColor,
-                checkedContainerColor = checkedContainerColor,
-                checkedContentColor = checkedContentColor,
-            )
-
-    internal fun ColorScheme.defaultOutlinedIconToggleButtonVibrantColors():
-        IconToggleButtonColors {
-        return defaultOutlinedIconToggleButtonVibrantColorsCached
-            ?: run {
-                IconToggleButtonColors(
-                        containerColor = Color.Transparent,
-                        contentColor = fromToken(OutlinedIconButtonTokens.UnselectedColor),
-                        disabledContainerColor = Color.Transparent,
-                        disabledContentColor =
-                            fromToken(OutlinedIconButtonTokens.DisabledColor)
-                                .copy(alpha = OutlinedIconButtonTokens.DisabledOpacity),
-                        checkedContainerColor =
-                            fromToken(OutlinedIconButtonTokens.SelectedContainerColor),
-                        checkedContentColor = fromToken(OutlinedIconButtonTokens.SelectedColor)
-                    )
-                    .also { defaultOutlinedIconToggleButtonColorsCached = it }
-            }
-    }
-
-    /**
-     * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] and
-     * [checked] state. [LocalContentColor] will be used as the border color.
-     *
-     * See [outlinedIconToggleButtonVibrantBorder] for a [BorderStroke] that uses the spec
-     * recommended color as the border color.
-     *
-     * @param enabled whether the icon button is enabled
-     * @param checked whether the icon button is checked
-     */
-    @Composable
-    fun outlinedIconToggleButtonBorder(enabled: Boolean, checked: Boolean): BorderStroke? {
-        if (checked) {
-            return null
-        }
-        return outlinedIconButtonBorder(enabled)
-    }
-
-    /**
-     * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] and
-     * [checked] state. The spec recommended color will be used as the border color.
-     *
-     * @param enabled whether the icon button is enabled
-     * @param checked whether the icon button is checked
-     */
-    @Composable
-    fun outlinedIconToggleButtonVibrantBorder(enabled: Boolean, checked: Boolean): BorderStroke? {
-        if (checked) {
-            return null
-        }
-        return outlinedIconButtonVibrantBorder(enabled)
-    }
-
-    /**
-     * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] state.
-     * [LocalContentColor] will be used as the border color.
-     *
-     * See [outlinedIconToggleButtonVibrantBorder] for a [BorderStroke] that uses the spec
-     * recommended color as the border color.
-     *
-     * @param enabled whether the icon button is enabled
-     */
-    @Composable
-    fun outlinedIconButtonBorder(enabled: Boolean): BorderStroke {
-        val outlineColor = LocalContentColor.current
-        val color: Color =
-            if (enabled) {
-                outlineColor
-            } else {
-                outlineColor.copy(alpha = OutlinedIconButtonTokens.DisabledContainerOpacity)
-            }
-        return remember(color) { BorderStroke(SmallIconButtonTokens.OutlinedOutlineWidth, color) }
-    }
-
-    /**
-     * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] state.
-     * The spec recommended color will be used as the border color.
-     *
-     * @param enabled whether the icon button is enabled
-     */
-    @Composable
-    fun outlinedIconButtonVibrantBorder(enabled: Boolean): BorderStroke {
-        val outlineColor = OutlinedIconButtonTokens.OutlineColor.value
-        val color: Color =
-            if (enabled) {
-                outlineColor
-            } else {
-                outlineColor.copy(alpha = OutlinedIconButtonTokens.DisabledContainerOpacity)
-            }
-        return remember(color) { BorderStroke(SmallIconButtonTokens.OutlinedOutlineWidth, color) }
-    }
-
-    /** Default ripple shape for a standard icon button. */
-    val standardShape: Shape
-        @Composable get() = SmallIconButtonTokens.ContainerShapeRound.value
-
-    /** Default shape for a filled icon button. */
-    val filledShape: Shape
-        @Composable get() = SmallIconButtonTokens.ContainerShapeRound.value
-
-    /** Default shape for an outlined icon button. */
-    val outlinedShape: Shape
-        @Composable get() = SmallIconButtonTokens.ContainerShapeRound.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default round shape for any extra small icon button. */
-    val xSmallRoundShape: Shape
-        @Composable get() = XSmallIconButtonTokens.ContainerShapeRound.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default square shape for any extra small icon button. */
-    val xSmallSquareShape: Shape
-        @Composable get() = XSmallIconButtonTokens.ContainerShapeSquare.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default pressed shape for any extra small icon button. */
-    val xSmallPressedShape: Shape
-        @Composable get() = XSmallIconButtonTokens.PressedContainerShape.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default shape for any small icon button. */
-    val smallRoundShape: Shape
-        @Composable get() = SmallIconButtonTokens.ContainerShapeRound.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default shape for any small icon button. */
-    val smallSquareShape: Shape
-        @Composable get() = SmallIconButtonTokens.ContainerShapeSquare.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default pressed shape for any small icon button. */
-    val smallPressedShape: Shape
-        @Composable get() = SmallIconButtonTokens.PressedContainerShape.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default shape for any medium icon button. */
-    val mediumRoundShape: Shape
-        @Composable get() = MediumIconButtonTokens.ContainerShapeRound.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default shape for any medium icon button. */
-    val mediumSquareShape: Shape
-        @Composable get() = MediumIconButtonTokens.ContainerShapeSquare.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default pressed shape for any medium icon button. */
-    val mediumPressedShape: Shape
-        @Composable get() = MediumIconButtonTokens.PressedContainerShape.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default shape for any large icon button. */
-    val largeRoundShape: Shape
-        @Composable get() = LargeIconButtonTokens.ContainerShapeRound.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default shape for any large icon button. */
-    val largeSquareShape: Shape
-        @Composable get() = LargeIconButtonTokens.ContainerShapeSquare.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default pressed shape for any large icon button. */
-    val largePressedShape: Shape
-        @Composable get() = LargeIconButtonTokens.PressedContainerShape.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default shape for any xlarge icon button. */
-    val xLargeRoundShape: Shape
-        @Composable get() = XLargeIconButtonTokens.ContainerShapeRound.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default shape for any xlarge icon button. */
-    val xLargeSquareShape: Shape
-        @Composable get() = XLargeIconButtonTokens.ContainerShapeSquare.value
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default pressed shape for any extra large icon button. */
-    val xLargePressedShape: Shape
-        @Composable get() = XLargeIconButtonTokens.PressedContainerShape.value
-
-    /**
-     * Creates a [ButtonShapes] that correspond to the shapes in the default, pressed, and checked
-     * states. Toggle button will morph between these shapes as long as the shapes are all
-     * [CornerBasedShape]s.
-     *
-     * @param shape the unchecked shape for [ButtonShapes]
-     * @param pressedShape the unchecked shape for [ButtonShapes]
-     * @param checkedShape the unchecked shape for [ButtonShapes]
-     */
-    @ExperimentalMaterial3ExpressiveApi
-    @Composable
-    fun shapes(shape: Shape, pressedShape: Shape, checkedShape: Shape): IconButtonShapes =
-        remember(shape, pressedShape, checkedShape) {
-            IconButtonShapes(shape, pressedShape, checkedShape)
-        }
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default container for any extra small icon button. */
-    val xSmallIconSize: Dp = XSmallIconButtonTokens.IconSize
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default size for any small icon button. */
-    val smallIconSize: Dp = SmallIconButtonTokens.IconSize
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default container size for any medium icon button. */
-    val mediumIconSize: Dp = MediumIconButtonTokens.IconSize
-
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    /** Default size for any large icon button. */
-    val largeIconSize: Dp = LargeIconButtonTokens.IconSize
-
-    /** Default size for any xlarge icon button. */
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalMaterial3ExpressiveApi
-    @ExperimentalMaterial3ExpressiveApi
-    val xLargeIconSize: Dp = XLargeIconButtonTokens.IconSize
-
-    /**
-     * Default container size for any extra small icon button.
-     *
-     * @param widthOption the width of the container
-     */
-    @ExperimentalMaterial3ExpressiveApi
-    fun xSmallContainerSize(
-        widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform
-    ): DpSize {
-        val horizontalSpace =
-            when (widthOption) {
-                IconButtonWidthOption.Narrow ->
-                    XSmallIconButtonTokens.NarrowLeadingSpace +
-                        XSmallIconButtonTokens.NarrowTrailingSpace
-                IconButtonWidthOption.Uniform ->
-                    XSmallIconButtonTokens.UniformLeadingSpace +
-                        XSmallIconButtonTokens.UniformLeadingSpace
-                IconButtonWidthOption.Wide ->
-                    XSmallIconButtonTokens.WideLeadingSpace +
-                        XSmallIconButtonTokens.WideTrailingSpace
-                else -> 0.dp
-            }
-        return DpSize(
-            XSmallIconButtonTokens.IconSize + horizontalSpace,
-            XSmallIconButtonTokens.ContainerHeight
-        )
-    }
-
-    /**
-     * Default container size for any small icon button.
-     *
-     * @param widthOption the width of the container
-     */
-    @ExperimentalMaterial3ExpressiveApi
-    fun smallContainerSize(
-        widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform
-    ): DpSize {
-        val horizontalSpace =
-            when (widthOption) {
-                IconButtonWidthOption.Narrow ->
-                    SmallIconButtonTokens.NarrowLeadingSpace +
-                        SmallIconButtonTokens.NarrowTrailingSpace
-                IconButtonWidthOption.Uniform ->
-                    SmallIconButtonTokens.UniformLeadingSpace +
-                        SmallIconButtonTokens.UniformLeadingSpace
-                IconButtonWidthOption.Wide ->
-                    SmallIconButtonTokens.WideLeadingSpace + SmallIconButtonTokens.WideTrailingSpace
-                else -> 0.dp
-            }
-        return DpSize(
-            SmallIconButtonTokens.IconSize + horizontalSpace,
-            SmallIconButtonTokens.ContainerHeight
-        )
-    }
-
-    /**
-     * Default container size for any medium icon button.
-     *
-     * @param widthOption the width of the container
-     */
-    @ExperimentalMaterial3ExpressiveApi
-    fun mediumContainerSize(
-        widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform
-    ): DpSize {
-        val horizontalSpace =
-            when (widthOption) {
-                IconButtonWidthOption.Narrow ->
-                    MediumIconButtonTokens.NarrowLeadingSpace +
-                        MediumIconButtonTokens.NarrowTrailingSpace
-                IconButtonWidthOption.Uniform ->
-                    MediumIconButtonTokens.UniformLeadingSpace +
-                        MediumIconButtonTokens.UniformLeadingSpace
-                IconButtonWidthOption.Wide ->
-                    MediumIconButtonTokens.WideLeadingSpace +
-                        MediumIconButtonTokens.WideTrailingSpace
-                else -> 0.dp
-            }
-        return DpSize(
-            MediumIconButtonTokens.IconSize + horizontalSpace,
-            MediumIconButtonTokens.ContainerHeight
-        )
-    }
-
-    /**
-     * Default container size for any large icon button.
-     *
-     * @param widthOption the width of the container
-     */
-    @ExperimentalMaterial3ExpressiveApi
-    fun largeContainerSize(
-        widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform
-    ): DpSize {
-        val horizontalSpace =
-            when (widthOption) {
-                IconButtonWidthOption.Narrow ->
-                    LargeIconButtonTokens.NarrowLeadingSpace +
-                        LargeIconButtonTokens.NarrowTrailingSpace
-                IconButtonWidthOption.Uniform ->
-                    LargeIconButtonTokens.UniformLeadingSpace +
-                        LargeIconButtonTokens.UniformLeadingSpace
-                IconButtonWidthOption.Wide ->
-                    LargeIconButtonTokens.WideLeadingSpace + LargeIconButtonTokens.WideTrailingSpace
-                else -> 0.dp
-            }
-        return DpSize(
-            LargeIconButtonTokens.IconSize + horizontalSpace,
-            LargeIconButtonTokens.ContainerHeight
-        )
-    }
-
-    /**
-     * Default container size for any extra large icon button.
-     *
-     * @param widthOption the width of the container
-     */
-    @ExperimentalMaterial3ExpressiveApi
-    fun xLargeContainerSize(
-        widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform
-    ): DpSize {
-        val horizontalSpace =
-            when (widthOption) {
-                IconButtonWidthOption.Narrow ->
-                    XLargeIconButtonTokens.NarrowLeadingSpace +
-                        XLargeIconButtonTokens.NarrowTrailingSpace
-                IconButtonWidthOption.Uniform ->
-                    XLargeIconButtonTokens.UniformLeadingSpace +
-                        XLargeIconButtonTokens.UniformLeadingSpace
-                IconButtonWidthOption.Wide ->
-                    XLargeIconButtonTokens.WideLeadingSpace +
-                        XLargeIconButtonTokens.WideTrailingSpace
-                else -> 0.dp
-            }
-        return DpSize(
-            XLargeIconButtonTokens.IconSize + horizontalSpace,
-            XLargeIconButtonTokens.ContainerHeight
-        )
-    }
-
-    /** Class that describes the different supported widths of the [IconButton]. */
-    @JvmInline
-    value class IconButtonWidthOption private constructor(private val value: Int) {
-        companion object {
-            // TODO(b/342666275): update this kdoc with spec guidance
-            /*
-             * This configuration is recommended for small screens.
-             */
-            val Narrow = IconButtonWidthOption(0)
-
-            /*
-             * This configuration is recommended for medium width screens.
-             */
-            val Uniform = IconButtonWidthOption(1)
-
-            /*
-             * This configuration is recommended for wide screens.
-             */
-            val Wide = IconButtonWidthOption(2)
-        }
-
-        override fun toString() =
-            when (this) {
-                Narrow -> "Narrow"
-                Uniform -> "Uniform"
-                Wide -> "Wide"
-                else -> "Unknown"
-            }
-    }
-}
-
-/**
- * Represents the container and content colors used in an icon button in different states.
- *
- * @param containerColor the container color of this icon button when enabled.
- * @param contentColor the content color of this icon button when enabled.
- * @param disabledContainerColor the container color of this icon button when not enabled.
- * @param disabledContentColor the content color of this icon button when not enabled.
- * @constructor create an instance with arbitrary colors.
- * - See [IconButtonDefaults.filledIconButtonColors] and
- *   [IconButtonDefaults.filledTonalIconButtonColors] for the default colors used in a
- *   [FilledIconButton].
- * - See [IconButtonDefaults.outlinedIconButtonVibrantColors] for the default colors used in an
- *   [OutlinedIconButton].
- */
-@Immutable
-class IconButtonColors(
-    val containerColor: Color,
-    val contentColor: Color,
-    val disabledContainerColor: Color,
-    val disabledContentColor: Color,
-) {
-
-    /**
-     * Returns a copy of this IconButtonColors, optionally overriding some of the values. This uses
-     * the Color.Unspecified to mean “use the value from the source”
-     */
-    fun copy(
-        containerColor: Color = this.containerColor,
-        contentColor: Color = this.contentColor,
-        disabledContainerColor: Color = this.disabledContainerColor,
-        disabledContentColor: Color = this.disabledContentColor,
-    ) =
-        IconButtonColors(
-            containerColor.takeOrElse { this.containerColor },
-            contentColor.takeOrElse { this.contentColor },
-            disabledContainerColor.takeOrElse { this.disabledContainerColor },
-            disabledContentColor.takeOrElse { this.disabledContentColor },
-        )
-
-    /**
-     * Represents the container color for this icon button, depending on [enabled].
-     *
-     * @param enabled whether the icon button is enabled
-     */
-    @Stable
-    internal fun containerColor(enabled: Boolean): Color =
-        if (enabled) containerColor else disabledContainerColor
-
-    /**
-     * Represents the content color for this icon button, depending on [enabled].
-     *
-     * @param enabled whether the icon button is enabled
-     */
-    @Stable
-    internal fun contentColor(enabled: Boolean): Color =
-        if (enabled) contentColor else disabledContentColor
-
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other == null || other !is IconButtonColors) return false
-
-        if (containerColor != other.containerColor) return false
-        if (contentColor != other.contentColor) return false
-        if (disabledContainerColor != other.disabledContainerColor) return false
-        if (disabledContentColor != other.disabledContentColor) return false
-
-        return true
-    }
-
-    override fun hashCode(): Int {
-        var result = containerColor.hashCode()
-        result = 31 * result + contentColor.hashCode()
-        result = 31 * result + disabledContainerColor.hashCode()
-        result = 31 * result + disabledContentColor.hashCode()
-
-        return result
-    }
-}
-
-/**
- * Represents the container and content colors used in a toggleable icon button in different states.
- *
- * @param containerColor the container color of this icon button when enabled.
- * @param contentColor the content color of this icon button when enabled.
- * @param disabledContainerColor the container color of this icon button when not enabled.
- * @param disabledContentColor the content color of this icon button when not enabled.
- * @param checkedContainerColor the container color of this icon button when checked.
- * @param checkedContentColor the content color of this icon button when checked.
- * @constructor create an instance with arbitrary colors.
- * - See [IconButtonDefaults.filledIconToggleButtonColors] and
- *   [IconButtonDefaults.filledTonalIconToggleButtonColors] for the default colors used in a
- *   [FilledIconButton].
- * - See [IconButtonDefaults.outlinedIconToggleButtonVibrantColors] for the default colors used in a
- *   toggleable [OutlinedIconButton].
- */
-@Immutable
-class IconToggleButtonColors(
-    val containerColor: Color,
-    val contentColor: Color,
-    val disabledContainerColor: Color,
-    val disabledContentColor: Color,
-    val checkedContainerColor: Color,
-    val checkedContentColor: Color,
-) {
-
-    /**
-     * Returns a copy of this IconToggleButtonColors, optionally overriding some of the values. This
-     * uses the Color.Unspecified to mean “use the value from the source”
-     */
-    fun copy(
-        containerColor: Color = this.containerColor,
-        contentColor: Color = this.contentColor,
-        disabledContainerColor: Color = this.disabledContainerColor,
-        disabledContentColor: Color = this.disabledContentColor,
-        checkedContainerColor: Color = this.checkedContainerColor,
-        checkedContentColor: Color = this.checkedContentColor
-    ) =
-        IconToggleButtonColors(
-            containerColor.takeOrElse { this.containerColor },
-            contentColor.takeOrElse { this.contentColor },
-            disabledContainerColor.takeOrElse { this.disabledContainerColor },
-            disabledContentColor.takeOrElse { this.disabledContentColor },
-            checkedContainerColor.takeOrElse { this.checkedContainerColor },
-            checkedContentColor.takeOrElse { this.checkedContentColor }
-        )
-
-    /**
-     * Represents the container color for this icon button, depending on [enabled] and [checked].
-     *
-     * @param enabled whether the icon button is enabled
-     * @param checked whether the icon button is checked
-     */
-    @Composable
-    internal fun containerColor(enabled: Boolean, checked: Boolean): State<Color> {
-        val target =
-            when {
-                !enabled -> disabledContainerColor
-                !checked -> containerColor
-                else -> checkedContainerColor
-            }
-        return rememberUpdatedState(target)
-    }
-
-    /**
-     * Represents the content color for this icon button, depending on [enabled] and [checked].
-     *
-     * @param enabled whether the icon button is enabled
-     * @param checked whether the icon button is checked
-     */
-    @Composable
-    internal fun contentColor(enabled: Boolean, checked: Boolean): State<Color> {
-        val target =
-            when {
-                !enabled -> disabledContentColor
-                !checked -> contentColor
-                else -> checkedContentColor
-            }
-        return rememberUpdatedState(target)
-    }
-
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other == null || other !is IconToggleButtonColors) return false
-
-        if (containerColor != other.containerColor) return false
-        if (contentColor != other.contentColor) return false
-        if (disabledContainerColor != other.disabledContainerColor) return false
-        if (disabledContentColor != other.disabledContentColor) return false
-        if (checkedContainerColor != other.checkedContainerColor) return false
-        if (checkedContentColor != other.checkedContentColor) return false
-
-        return true
-    }
-
-    override fun hashCode(): Int {
-        var result = containerColor.hashCode()
-        result = 31 * result + contentColor.hashCode()
-        result = 31 * result + disabledContainerColor.hashCode()
-        result = 31 * result + disabledContentColor.hashCode()
-        result = 31 * result + checkedContainerColor.hashCode()
-        result = 31 * result + checkedContentColor.hashCode()
-
-        return result
-    }
-}
-
 /**
  * The shapes that will be used in toggle buttons. Toggle button will morph between these three
  * shapes depending on the interaction of the toggle button, assuming all of the shapes are
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButtonDefaults.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButtonDefaults.kt
new file mode 100644
index 0000000..6bf4ad9
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/IconButtonDefaults.kt
@@ -0,0 +1,1375 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3
+
+import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.shape.CornerBasedShape
+import androidx.compose.material3.tokens.FilledIconButtonTokens
+import androidx.compose.material3.tokens.FilledTonalIconButtonTokens
+import androidx.compose.material3.tokens.LargeIconButtonTokens
+import androidx.compose.material3.tokens.MediumIconButtonTokens
+import androidx.compose.material3.tokens.OutlinedIconButtonTokens
+import androidx.compose.material3.tokens.SmallIconButtonTokens
+import androidx.compose.material3.tokens.StandardIconButtonTokens
+import androidx.compose.material3.tokens.XLargeIconButtonTokens
+import androidx.compose.material3.tokens.XSmallIconButtonTokens
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.runtime.Stable
+import androidx.compose.runtime.State
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.takeOrElse
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.DpSize
+import androidx.compose.ui.unit.dp
+import kotlin.jvm.JvmInline
+
+/** Contains the default values for all four icon and icon toggle button types. */
+object IconButtonDefaults {
+    /**
+     * Contains the default values used by [IconButton]. [LocalContentColor] will be applied to the
+     * icon and down the UI tree.
+     *
+     * See [iconButtonVibrantColors] for default values that applies the recommended high contrast
+     * colors.
+     */
+    @Composable
+    fun iconButtonColors(): IconButtonColors {
+        val contentColor = LocalContentColor.current
+        val colors = MaterialTheme.colorScheme.defaultIconButtonColors(contentColor)
+        return if (colors.contentColor == contentColor) {
+            colors
+        } else {
+            colors.copy(
+                contentColor = contentColor,
+                disabledContentColor =
+                    contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity)
+            )
+        }
+    }
+
+    /**
+     * Creates a [IconButtonColors] that represents the default colors used in a [IconButton].
+     * [LocalContentColor] will be applied to the icon and down the UI tree unless a custom
+     * [contentColor] is provided.
+     *
+     * See [iconButtonVibrantColors] for default values that applies the recommended high contrast
+     * colors.
+     *
+     * @param containerColor the container color of this icon button when enabled.
+     * @param contentColor the content color of this icon button when enabled. By default, this will
+     *   use the current LocalContentColor value.
+     * @param disabledContainerColor the container color of this icon button when not enabled.
+     * @param disabledContentColor the content color of this icon button when not enabled.
+     */
+    @Composable
+    fun iconButtonColors(
+        containerColor: Color = Color.Unspecified,
+        contentColor: Color = LocalContentColor.current,
+        disabledContainerColor: Color = Color.Unspecified,
+        disabledContentColor: Color =
+            contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity)
+    ): IconButtonColors =
+        MaterialTheme.colorScheme
+            .defaultIconButtonColors(LocalContentColor.current)
+            .copy(
+                containerColor = containerColor,
+                contentColor = contentColor,
+                disabledContainerColor = disabledContainerColor,
+                disabledContentColor = disabledContentColor,
+            )
+
+    internal fun ColorScheme.defaultIconButtonColors(localContentColor: Color): IconButtonColors {
+        return defaultIconButtonColorsCached
+            ?: run {
+                IconButtonColors(
+                        containerColor = Color.Transparent,
+                        contentColor = localContentColor,
+                        disabledContainerColor = Color.Transparent,
+                        disabledContentColor =
+                            localContentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity)
+                    )
+                    .also { defaultIconButtonColorsCached = it }
+            }
+    }
+
+    /**
+     * Creates a [IconButtonColors] that represents the recommended high contrast colors used in an
+     * [IconButton].
+     *
+     * See [iconButtonColors] for default values that applies [LocalContentColor] to the icon and
+     * down the UI tree.
+     */
+    @Composable
+    fun iconButtonVibrantColors(): IconButtonColors =
+        MaterialTheme.colorScheme.defaultIconButtonVibrantColors()
+
+    /**
+     * Creates a [IconButtonColors] that represents the recommended high contrast colors used in an
+     * [IconButton].
+     *
+     * See [iconButtonColors] for default values that applies [LocalContentColor] to the icon and
+     * down the UI tree.
+     *
+     * @param containerColor the container color of this icon button when enabled.
+     * @param contentColor the content color of this icon button when enabled.
+     * @param disabledContainerColor the container color of this icon button when not enabled.
+     * @param disabledContentColor the content color of this icon button when not enabled.
+     */
+    @Composable
+    fun iconButtonVibrantColors(
+        containerColor: Color = Color.Unspecified,
+        contentColor: Color = Color.Unspecified,
+        disabledContainerColor: Color = Color.Unspecified,
+        disabledContentColor: Color =
+            contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity)
+    ): IconButtonColors =
+        MaterialTheme.colorScheme
+            .defaultIconButtonVibrantColors()
+            .copy(
+                containerColor = containerColor,
+                contentColor = contentColor,
+                disabledContainerColor = disabledContainerColor,
+                disabledContentColor = disabledContentColor,
+            )
+
+    internal fun ColorScheme.defaultIconButtonVibrantColors(): IconButtonColors {
+        return defaultIconButtonVibrantColorsCached
+            ?: run {
+                IconButtonColors(
+                        containerColor = Color.Transparent,
+                        contentColor = fromToken(StandardIconButtonTokens.Color),
+                        disabledContainerColor = Color.Transparent,
+                        disabledContentColor =
+                            fromToken(StandardIconButtonTokens.DisabledColor)
+                                .copy(alpha = StandardIconButtonTokens.DisabledOpacity)
+                    )
+                    .also { defaultIconButtonVibrantColorsCached = it }
+            }
+    }
+
+    /**
+     * Creates a [IconToggleButtonColors] that represents the default colors used in a
+     * [IconToggleButton]. [LocalContentColor] will be applied to the icon and down the UI tree.
+     *
+     * See [iconToggleButtonVibrantColors] for default values that applies the recommended high
+     * contrast colors.
+     */
+    @Composable
+    fun iconToggleButtonColors(): IconToggleButtonColors {
+        val contentColor = LocalContentColor.current
+        val colors = MaterialTheme.colorScheme.defaultIconToggleButtonColors(contentColor)
+        if (colors.contentColor == contentColor) {
+            return colors
+        } else {
+            return colors.copy(
+                contentColor = contentColor,
+                disabledContentColor =
+                    contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity)
+            )
+        }
+    }
+
+    /**
+     * Creates a [IconToggleButtonColors] that represents the default colors used in a
+     * [IconToggleButton]. [LocalContentColor] will be applied to the icon and down the UI tree
+     * unless a custom [contentColor] is provided.
+     *
+     * See [iconToggleButtonVibrantColors] for default values that applies the recommended high
+     * contrast colors.
+     *
+     * @param containerColor the container color of this icon button when enabled.
+     * @param contentColor the content color of this icon button when enabled.
+     * @param disabledContainerColor the container color of this icon button when not enabled.
+     * @param disabledContentColor the content color of this icon button when not enabled.
+     * @param checkedContainerColor the container color of this icon button when checked.
+     * @param checkedContentColor the content color of this icon button when checked.
+     */
+    @Composable
+    fun iconToggleButtonColors(
+        containerColor: Color = Color.Unspecified,
+        contentColor: Color = LocalContentColor.current,
+        disabledContainerColor: Color = Color.Unspecified,
+        disabledContentColor: Color =
+            contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity),
+        checkedContainerColor: Color = Color.Unspecified,
+        checkedContentColor: Color = Color.Unspecified
+    ): IconToggleButtonColors =
+        MaterialTheme.colorScheme
+            .defaultIconToggleButtonColors(LocalContentColor.current)
+            .copy(
+                containerColor = containerColor,
+                contentColor = contentColor,
+                disabledContainerColor = disabledContainerColor,
+                disabledContentColor = disabledContentColor,
+                checkedContainerColor = checkedContainerColor,
+                checkedContentColor = checkedContentColor,
+            )
+
+    internal fun ColorScheme.defaultIconToggleButtonColors(
+        localContentColor: Color
+    ): IconToggleButtonColors {
+        return defaultIconToggleButtonColorsCached
+            ?: run {
+                IconToggleButtonColors(
+                        containerColor = Color.Transparent,
+                        contentColor = localContentColor,
+                        disabledContainerColor = Color.Transparent,
+                        disabledContentColor =
+                            localContentColor.copy(
+                                alpha = StandardIconButtonTokens.DisabledOpacity
+                            ),
+                        checkedContainerColor = Color.Transparent,
+                        checkedContentColor = fromToken(StandardIconButtonTokens.SelectedColor)
+                    )
+                    .also { defaultIconToggleButtonColorsCached = it }
+            }
+    }
+
+    /**
+     * Creates a [IconToggleButtonColors] that represents the recommended high contrast colors used
+     * in a [IconToggleButton]. See [iconToggleButtonColors] for default values that applies
+     * [LocalContentColor] to the icon and down the UI tree.
+     */
+    @Composable
+    fun iconToggleButtonVibrantColors(): IconToggleButtonColors =
+        MaterialTheme.colorScheme.defaultIconToggleButtonVibrantColors()
+
+    /**
+     * Creates a [IconToggleButtonColors] that represents the recommended high contrast colors used
+     * in a [IconToggleButton].
+     *
+     * See [iconToggleButtonColors] for default values that applies [LocalContentColor] to the icon
+     * and down the UI tree.
+     *
+     * @param containerColor the container color of this icon button when enabled.
+     * @param contentColor the content color of this icon button when enabled.
+     * @param disabledContainerColor the container color of this icon button when not enabled.
+     * @param disabledContentColor the content color of this icon button when not enabled.
+     * @param checkedContainerColor the container color of this icon button when checked.
+     * @param checkedContentColor the content color of this icon button when checked.
+     */
+    @Composable
+    fun iconToggleButtonVibrantColors(
+        containerColor: Color = Color.Unspecified,
+        contentColor: Color = Color.Unspecified,
+        disabledContainerColor: Color = Color.Unspecified,
+        disabledContentColor: Color =
+            contentColor.copy(alpha = StandardIconButtonTokens.DisabledOpacity),
+        checkedContainerColor: Color = Color.Unspecified,
+        checkedContentColor: Color = Color.Unspecified
+    ): IconToggleButtonColors =
+        MaterialTheme.colorScheme
+            .defaultIconToggleButtonVibrantColors()
+            .copy(
+                containerColor = containerColor,
+                contentColor = contentColor,
+                disabledContainerColor = disabledContainerColor,
+                disabledContentColor = disabledContentColor,
+                checkedContainerColor = checkedContainerColor,
+                checkedContentColor = checkedContentColor,
+            )
+
+    internal fun ColorScheme.defaultIconToggleButtonVibrantColors(): IconToggleButtonColors {
+        return defaultIconToggleButtonVibrantColorsCached
+            ?: run {
+                IconToggleButtonColors(
+                        containerColor = Color.Transparent,
+                        contentColor = fromToken(StandardIconButtonTokens.UnselectedColor),
+                        disabledContainerColor = Color.Transparent,
+                        disabledContentColor =
+                            fromToken(StandardIconButtonTokens.DisabledColor)
+                                .copy(alpha = StandardIconButtonTokens.DisabledOpacity),
+                        checkedContainerColor = Color.Transparent,
+                        checkedContentColor = fromToken(StandardIconButtonTokens.SelectedColor)
+                    )
+                    .also { defaultIconToggleButtonVibrantColorsCached = it }
+            }
+    }
+
+    /**
+     * Creates a [IconButtonColors] that represents the default colors used in a [FilledIconButton].
+     */
+    @Composable
+    fun filledIconButtonColors(): IconButtonColors =
+        MaterialTheme.colorScheme.defaultFilledIconButtonColors
+
+    /**
+     * Creates a [IconButtonColors] that represents the default colors used in a [FilledIconButton].
+     *
+     * @param containerColor the container color of this icon button when enabled.
+     * @param contentColor the content color of this icon button when enabled.
+     * @param disabledContainerColor the container color of this icon button when not enabled.
+     * @param disabledContentColor the content color of this icon button when not enabled.
+     */
+    @Composable
+    fun filledIconButtonColors(
+        containerColor: Color = Color.Unspecified,
+        contentColor: Color = contentColorFor(containerColor),
+        disabledContainerColor: Color = Color.Unspecified,
+        disabledContentColor: Color = Color.Unspecified
+    ): IconButtonColors =
+        MaterialTheme.colorScheme.defaultFilledIconButtonColors.copy(
+            containerColor = containerColor,
+            contentColor = contentColor,
+            disabledContainerColor = disabledContainerColor,
+            disabledContentColor = disabledContentColor,
+        )
+
+    internal val ColorScheme.defaultFilledIconButtonColors: IconButtonColors
+        get() {
+            return defaultFilledIconButtonColorsCached
+                ?: IconButtonColors(
+                        containerColor = fromToken(FilledIconButtonTokens.ContainerColor),
+                        contentColor = fromToken(FilledIconButtonTokens.Color),
+                        disabledContainerColor =
+                            fromToken(FilledIconButtonTokens.DisabledContainerColor)
+                                .copy(alpha = FilledIconButtonTokens.DisabledContainerOpacity),
+                        disabledContentColor =
+                            fromToken(FilledIconButtonTokens.DisabledColor)
+                                .copy(alpha = FilledIconButtonTokens.DisabledOpacity)
+                    )
+                    .also { defaultFilledIconButtonColorsCached = it }
+        }
+
+    /**
+     * Creates a [IconToggleButtonColors] that represents the default colors used in a
+     * [FilledIconToggleButton].
+     */
+    @Composable
+    fun filledIconToggleButtonColors(): IconToggleButtonColors =
+        MaterialTheme.colorScheme.defaultFilledIconToggleButtonColors
+
+    /**
+     * Creates a [IconToggleButtonColors] that represents the default colors used in a
+     * [FilledIconToggleButton].
+     *
+     * @param containerColor the container color of this icon button when enabled.
+     * @param contentColor the content color of this icon button when enabled.
+     * @param disabledContainerColor the container color of this icon button when not enabled.
+     * @param disabledContentColor the content color of this icon button when not enabled.
+     * @param checkedContainerColor the container color of this icon button when checked.
+     * @param checkedContentColor the content color of this icon button when checked.
+     */
+    @Composable
+    fun filledIconToggleButtonColors(
+        containerColor: Color = Color.Unspecified,
+        // TODO(b/228455081): Using contentColorFor here will return OnSurfaceVariant,
+        //  while the token value is Primary.
+        contentColor: Color = Color.Unspecified,
+        disabledContainerColor: Color = Color.Unspecified,
+        disabledContentColor: Color = Color.Unspecified,
+        checkedContainerColor: Color = Color.Unspecified,
+        checkedContentColor: Color = contentColorFor(checkedContainerColor)
+    ): IconToggleButtonColors =
+        MaterialTheme.colorScheme.defaultFilledIconToggleButtonColors.copy(
+            containerColor = containerColor,
+            contentColor = contentColor,
+            disabledContainerColor = disabledContainerColor,
+            disabledContentColor = disabledContentColor,
+            checkedContainerColor = checkedContainerColor,
+            checkedContentColor = checkedContentColor,
+        )
+
+    internal val ColorScheme.defaultFilledIconToggleButtonColors: IconToggleButtonColors
+        get() {
+            return defaultFilledIconToggleButtonColorsCached
+                ?: IconToggleButtonColors(
+                        containerColor = fromToken(FilledIconButtonTokens.UnselectedContainerColor),
+                        // TODO(b/228455081): Using contentColorFor here will return
+                        // OnSurfaceVariant,
+                        //  while the token value is Primary.
+                        contentColor = fromToken(FilledIconButtonTokens.UnselectedColor),
+                        disabledContainerColor =
+                            fromToken(FilledIconButtonTokens.DisabledContainerColor)
+                                .copy(alpha = FilledIconButtonTokens.DisabledContainerOpacity),
+                        disabledContentColor =
+                            fromToken(FilledIconButtonTokens.DisabledColor)
+                                .copy(alpha = FilledIconButtonTokens.DisabledOpacity),
+                        checkedContainerColor =
+                            fromToken(FilledIconButtonTokens.SelectedContainerColor),
+                        checkedContentColor = fromToken(FilledIconButtonTokens.SelectedColor)
+                    )
+                    .also { defaultFilledIconToggleButtonColorsCached = it }
+        }
+
+    /**
+     * Creates a [IconButtonColors] that represents the default colors used in a
+     * [FilledTonalIconButton].
+     */
+    @Composable
+    fun filledTonalIconButtonColors(): IconButtonColors =
+        MaterialTheme.colorScheme.defaultFilledTonalIconButtonColors
+
+    /**
+     * Creates a [IconButtonColors] that represents the default colors used in a
+     * [FilledTonalIconButton].
+     *
+     * @param containerColor the container color of this icon button when enabled.
+     * @param contentColor the content color of this icon button when enabled.
+     * @param disabledContainerColor the container color of this icon button when not enabled.
+     * @param disabledContentColor the content color of this icon button when not enabled.
+     */
+    @Composable
+    fun filledTonalIconButtonColors(
+        containerColor: Color = Color.Unspecified,
+        contentColor: Color = contentColorFor(containerColor),
+        disabledContainerColor: Color = Color.Unspecified,
+        disabledContentColor: Color = Color.Unspecified
+    ): IconButtonColors =
+        MaterialTheme.colorScheme.defaultFilledTonalIconButtonColors.copy(
+            containerColor = containerColor,
+            contentColor = contentColor,
+            disabledContainerColor = disabledContainerColor,
+            disabledContentColor = disabledContentColor,
+        )
+
+    internal val ColorScheme.defaultFilledTonalIconButtonColors: IconButtonColors
+        get() {
+            return defaultFilledTonalIconButtonColorsCached
+                ?: IconButtonColors(
+                        containerColor = fromToken(FilledTonalIconButtonTokens.ContainerColor),
+                        contentColor = fromToken(FilledTonalIconButtonTokens.Color),
+                        disabledContainerColor =
+                            fromToken(FilledTonalIconButtonTokens.DisabledContainerColor)
+                                .copy(alpha = FilledTonalIconButtonTokens.DisabledContainerOpacity),
+                        disabledContentColor =
+                            fromToken(FilledTonalIconButtonTokens.DisabledColor)
+                                .copy(alpha = FilledTonalIconButtonTokens.DisabledOpacity)
+                    )
+                    .also { defaultFilledTonalIconButtonColorsCached = it }
+        }
+
+    /**
+     * Creates a [IconToggleButtonColors] that represents the default colors used in a
+     * [FilledTonalIconToggleButton].
+     */
+    @Composable
+    fun filledTonalIconToggleButtonColors(): IconToggleButtonColors =
+        MaterialTheme.colorScheme.defaultFilledTonalIconToggleButtonColors
+
+    /**
+     * Creates a [IconToggleButtonColors] that represents the default colors used in a
+     * [FilledTonalIconToggleButton].
+     *
+     * @param containerColor the container color of this icon button when enabled.
+     * @param contentColor the content color of this icon button when enabled.
+     * @param disabledContainerColor the container color of this icon button when not enabled.
+     * @param disabledContentColor the content color of this icon button when not enabled.
+     * @param checkedContainerColor the container color of this icon button when checked.
+     * @param checkedContentColor the content color of this icon button when checked.
+     */
+    @Composable
+    fun filledTonalIconToggleButtonColors(
+        containerColor: Color = Color.Unspecified,
+        contentColor: Color = contentColorFor(containerColor),
+        disabledContainerColor: Color = Color.Unspecified,
+        disabledContentColor: Color = Color.Unspecified,
+        checkedContainerColor: Color = Color.Unspecified,
+        checkedContentColor: Color = contentColorFor(checkedContainerColor)
+    ): IconToggleButtonColors =
+        MaterialTheme.colorScheme.defaultFilledTonalIconToggleButtonColors.copy(
+            containerColor = containerColor,
+            contentColor = contentColor,
+            disabledContainerColor = disabledContainerColor,
+            disabledContentColor = disabledContentColor,
+            checkedContainerColor = checkedContainerColor,
+            checkedContentColor = checkedContentColor,
+        )
+
+    internal val ColorScheme.defaultFilledTonalIconToggleButtonColors: IconToggleButtonColors
+        get() {
+            return defaultFilledTonalIconToggleButtonColorsCached
+                ?: IconToggleButtonColors(
+                        containerColor =
+                            fromToken(FilledTonalIconButtonTokens.UnselectedContainerColor),
+                        contentColor = fromToken(FilledTonalIconButtonTokens.UnselectedColor),
+                        disabledContainerColor =
+                            fromToken(FilledTonalIconButtonTokens.DisabledContainerColor)
+                                .copy(alpha = FilledTonalIconButtonTokens.DisabledContainerOpacity),
+                        disabledContentColor =
+                            fromToken(FilledTonalIconButtonTokens.DisabledColor)
+                                .copy(alpha = FilledTonalIconButtonTokens.DisabledOpacity),
+                        checkedContainerColor =
+                            fromToken(FilledTonalIconButtonTokens.SelectedContainerColor),
+                        checkedContentColor = fromToken(FilledTonalIconButtonTokens.SelectedColor)
+                    )
+                    .also { defaultFilledTonalIconToggleButtonColorsCached = it }
+        }
+
+    /**
+     * Creates a [IconButtonColors] that represents the default colors used in a
+     * [OutlinedIconButton]. [LocalContentColor] will be applied to the icon and down the UI tree.
+     *
+     * See [outlinedIconButtonVibrantColors] for default values that applies the recommended high
+     * contrast colors.
+     */
+    @Composable
+    fun outlinedIconButtonColors(): IconButtonColors {
+        val contentColor = LocalContentColor.current
+        val colors = MaterialTheme.colorScheme.defaultOutlinedIconButtonColors(contentColor)
+        if (colors.contentColor == contentColor) {
+            return colors
+        } else {
+            return colors.copy(
+                contentColor = contentColor,
+                disabledContentColor =
+                    contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity)
+            )
+        }
+    }
+
+    /**
+     * Creates a [IconButtonColors] that represents the default colors used in a
+     * [OutlinedIconButton].
+     *
+     * See [outlinedIconButtonVibrantColors] for default values that applies the recommended high
+     * contrast colors.
+     *
+     * @param containerColor the container color of this icon button when enabled.
+     * @param contentColor the content color of this icon button when enabled.
+     * @param disabledContainerColor the container color of this icon button when not enabled.
+     * @param disabledContentColor the content color of this icon button when not enabled.
+     */
+    @Composable
+    fun outlinedIconButtonColors(
+        containerColor: Color = Color.Unspecified,
+        contentColor: Color = LocalContentColor.current,
+        disabledContainerColor: Color = Color.Unspecified,
+        disabledContentColor: Color =
+            contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity)
+    ): IconButtonColors =
+        MaterialTheme.colorScheme
+            .defaultOutlinedIconButtonColors(LocalContentColor.current)
+            .copy(
+                containerColor = containerColor,
+                contentColor = contentColor,
+                disabledContainerColor = disabledContainerColor,
+                disabledContentColor = disabledContentColor,
+            )
+
+    internal fun ColorScheme.defaultOutlinedIconButtonColors(
+        localContentColor: Color
+    ): IconButtonColors {
+        return defaultOutlinedIconButtonColorsCached
+            ?: run {
+                IconButtonColors(
+                        containerColor = Color.Transparent,
+                        contentColor = localContentColor,
+                        disabledContainerColor = Color.Transparent,
+                        disabledContentColor =
+                            localContentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity)
+                    )
+                    .also { defaultOutlinedIconButtonColorsCached = it }
+            }
+    }
+
+    /**
+     * Creates a [IconButtonColors] that represents the default colors used in a
+     * [OutlinedIconButton].
+     *
+     * See [outlinedIconButtonColors] for default values that applies [LocalContentColor] to the
+     * icon and down the UI tree.
+     */
+    @Composable
+    fun outlinedIconButtonVibrantColors(): IconButtonColors =
+        MaterialTheme.colorScheme.defaultOutlinedIconButtonVibrantColors()
+
+    /**
+     * Creates a [IconButtonColors] that represents the default colors used in a
+     * [OutlinedIconButton].
+     *
+     * See [outlinedIconButtonColors] for default values that applies [LocalContentColor] to the
+     * icon and down the UI tree.
+     *
+     * @param containerColor the container color of this icon button when enabled.
+     * @param contentColor the content color of this icon button when enabled.
+     * @param disabledContainerColor the container color of this icon button when not enabled.
+     * @param disabledContentColor the content color of this icon button when not enabled.
+     */
+    @Composable
+    fun outlinedIconButtonVibrantColors(
+        containerColor: Color = Color.Unspecified,
+        contentColor: Color = Color.Unspecified,
+        disabledContainerColor: Color = Color.Unspecified,
+        disabledContentColor: Color =
+            contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity)
+    ): IconButtonColors =
+        MaterialTheme.colorScheme
+            .defaultOutlinedIconButtonVibrantColors()
+            .copy(
+                containerColor = containerColor,
+                contentColor = contentColor,
+                disabledContainerColor = disabledContainerColor,
+                disabledContentColor = disabledContentColor,
+            )
+
+    internal fun ColorScheme.defaultOutlinedIconButtonVibrantColors(): IconButtonColors {
+        return defaultOutlinedIconButtonVibrantColorsCached
+            ?: run {
+                IconButtonColors(
+                        containerColor = Color.Transparent,
+                        contentColor = fromToken(OutlinedIconButtonTokens.Color),
+                        disabledContainerColor = Color.Transparent,
+                        disabledContentColor =
+                            fromToken(OutlinedIconButtonTokens.DisabledColor)
+                                .copy(alpha = OutlinedIconButtonTokens.DisabledOpacity)
+                    )
+                    .also { defaultOutlinedIconButtonVibrantColorsCached = it }
+            }
+    }
+
+    /**
+     * Creates a [IconToggleButtonColors] that represents the default colors used in a
+     * [OutlinedIconToggleButton]. [LocalContentColor] will be applied to the icon and down the UI
+     * tree.
+     *
+     * See [outlinedIconButtonVibrantColors] for default values that applies the recommended high
+     * contrast colors.
+     */
+    @Composable
+    fun outlinedIconToggleButtonColors(): IconToggleButtonColors {
+        val contentColor = LocalContentColor.current
+        val colors = MaterialTheme.colorScheme.defaultOutlinedIconToggleButtonColors(contentColor)
+        if (colors.contentColor == contentColor) {
+            return colors
+        } else {
+            return colors.copy(
+                contentColor = contentColor,
+                disabledContentColor =
+                    contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity)
+            )
+        }
+    }
+
+    /**
+     * Creates a [IconToggleButtonColors] that represents the default colors used in a
+     * [OutlinedIconToggleButton]. [LocalContentColor] will be applied to the icon and down the UI
+     * tree.
+     *
+     * See [outlinedIconButtonVibrantColors] for default values that applies the recommended high
+     * contrast colors.
+     *
+     * @param containerColor the container color of this icon button when enabled.
+     * @param contentColor the content color of this icon button when enabled.
+     * @param disabledContainerColor the container color of this icon button when not enabled.
+     * @param disabledContentColor the content color of this icon button when not enabled.
+     * @param checkedContainerColor the container color of this icon button when checked.
+     * @param checkedContentColor the content color of this icon button when checked.
+     */
+    @Composable
+    fun outlinedIconToggleButtonColors(
+        containerColor: Color = Color.Unspecified,
+        contentColor: Color = LocalContentColor.current,
+        disabledContainerColor: Color = Color.Unspecified,
+        disabledContentColor: Color =
+            contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity),
+        checkedContainerColor: Color = Color.Unspecified,
+        checkedContentColor: Color = contentColorFor(checkedContainerColor)
+    ): IconToggleButtonColors =
+        MaterialTheme.colorScheme
+            .defaultOutlinedIconToggleButtonColors(LocalContentColor.current)
+            .copy(
+                containerColor = containerColor,
+                contentColor = contentColor,
+                disabledContainerColor = disabledContainerColor,
+                disabledContentColor = disabledContentColor,
+                checkedContainerColor = checkedContainerColor,
+                checkedContentColor = checkedContentColor,
+            )
+
+    internal fun ColorScheme.defaultOutlinedIconToggleButtonColors(
+        localContentColor: Color
+    ): IconToggleButtonColors {
+        return defaultIconToggleButtonColorsCached
+            ?: run {
+                IconToggleButtonColors(
+                        containerColor = Color.Transparent,
+                        contentColor = localContentColor,
+                        disabledContainerColor = Color.Transparent,
+                        disabledContentColor =
+                            localContentColor.copy(
+                                alpha = OutlinedIconButtonTokens.DisabledOpacity
+                            ),
+                        checkedContainerColor =
+                            fromToken(OutlinedIconButtonTokens.SelectedContainerColor),
+                        checkedContentColor =
+                            contentColorFor(
+                                fromToken(OutlinedIconButtonTokens.SelectedContainerColor)
+                            )
+                    )
+                    .also { defaultOutlinedIconToggleButtonColorsCached = it }
+            }
+    }
+
+    /**
+     * Creates a [IconToggleButtonColors] that represents the default colors used in a
+     * [OutlinedIconToggleButton].
+     *
+     * See [outlinedIconToggleButtonColors] for default values that applies [LocalContentColor] to
+     * the icon and down the UI tree.
+     */
+    @Composable
+    fun outlinedIconToggleButtonVibrantColors(): IconToggleButtonColors =
+        MaterialTheme.colorScheme.defaultOutlinedIconToggleButtonVibrantColors()
+
+    /**
+     * Creates a [IconToggleButtonColors] that represents the default colors used in a
+     * [OutlinedIconToggleButton].
+     *
+     * See [outlinedIconToggleButtonColors] for default values that applies [LocalContentColor] to
+     * the icon and down the UI tree.
+     *
+     * @param containerColor the container color of this icon button when enabled.
+     * @param contentColor the content color of this icon button when enabled.
+     * @param disabledContainerColor the container color of this icon button when not enabled.
+     * @param disabledContentColor the content color of this icon button when not enabled.
+     * @param checkedContainerColor the container color of this icon button when checked.
+     * @param checkedContentColor the content color of this icon button when checked.
+     */
+    @Composable
+    fun outlinedIconToggleButtonVibrantColors(
+        containerColor: Color = Color.Unspecified,
+        contentColor: Color = Color.Unspecified,
+        disabledContainerColor: Color = Color.Unspecified,
+        disabledContentColor: Color =
+            contentColor.copy(alpha = OutlinedIconButtonTokens.DisabledOpacity),
+        checkedContainerColor: Color = Color.Unspecified,
+        checkedContentColor: Color = contentColorFor(checkedContainerColor)
+    ): IconToggleButtonColors =
+        MaterialTheme.colorScheme
+            .defaultOutlinedIconToggleButtonVibrantColors()
+            .copy(
+                containerColor = containerColor,
+                contentColor = contentColor,
+                disabledContainerColor = disabledContainerColor,
+                disabledContentColor = disabledContentColor,
+                checkedContainerColor = checkedContainerColor,
+                checkedContentColor = checkedContentColor,
+            )
+
+    internal fun ColorScheme.defaultOutlinedIconToggleButtonVibrantColors():
+        IconToggleButtonColors {
+        return defaultOutlinedIconToggleButtonVibrantColorsCached
+            ?: run {
+                IconToggleButtonColors(
+                        containerColor = Color.Transparent,
+                        contentColor = fromToken(OutlinedIconButtonTokens.UnselectedColor),
+                        disabledContainerColor = Color.Transparent,
+                        disabledContentColor =
+                            fromToken(OutlinedIconButtonTokens.DisabledColor)
+                                .copy(alpha = OutlinedIconButtonTokens.DisabledOpacity),
+                        checkedContainerColor =
+                            fromToken(OutlinedIconButtonTokens.SelectedContainerColor),
+                        checkedContentColor = fromToken(OutlinedIconButtonTokens.SelectedColor)
+                    )
+                    .also { defaultOutlinedIconToggleButtonColorsCached = it }
+            }
+    }
+
+    /**
+     * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] and
+     * [checked] state. [LocalContentColor] will be used as the border color.
+     *
+     * See [outlinedIconToggleButtonVibrantBorder] for a [BorderStroke] that uses the spec
+     * recommended color as the border color.
+     *
+     * @param enabled whether the icon button is enabled
+     * @param checked whether the icon button is checked
+     */
+    @Composable
+    fun outlinedIconToggleButtonBorder(enabled: Boolean, checked: Boolean): BorderStroke? {
+        if (checked) {
+            return null
+        }
+        return outlinedIconButtonBorder(enabled)
+    }
+
+    /**
+     * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] and
+     * [checked] state. The spec recommended color will be used as the border color.
+     *
+     * @param enabled whether the icon button is enabled
+     * @param checked whether the icon button is checked
+     */
+    @Composable
+    fun outlinedIconToggleButtonVibrantBorder(enabled: Boolean, checked: Boolean): BorderStroke? {
+        if (checked) {
+            return null
+        }
+        return outlinedIconButtonVibrantBorder(enabled)
+    }
+
+    /**
+     * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] state.
+     * [LocalContentColor] will be used as the border color.
+     *
+     * See [outlinedIconToggleButtonVibrantBorder] for a [BorderStroke] that uses the spec
+     * recommended color as the border color.
+     *
+     * @param enabled whether the icon button is enabled
+     */
+    @Composable
+    fun outlinedIconButtonBorder(enabled: Boolean): BorderStroke {
+        val outlineColor = LocalContentColor.current
+        val color: Color =
+            if (enabled) {
+                outlineColor
+            } else {
+                outlineColor.copy(alpha = OutlinedIconButtonTokens.DisabledContainerOpacity)
+            }
+        return remember(color) { BorderStroke(SmallIconButtonTokens.OutlinedOutlineWidth, color) }
+    }
+
+    /**
+     * Represents the [BorderStroke] for an [OutlinedIconButton], depending on its [enabled] state.
+     * The spec recommended color will be used as the border color.
+     *
+     * @param enabled whether the icon button is enabled
+     */
+    @Composable
+    fun outlinedIconButtonVibrantBorder(enabled: Boolean): BorderStroke {
+        val outlineColor = OutlinedIconButtonTokens.OutlineColor.value
+        val color: Color =
+            if (enabled) {
+                outlineColor
+            } else {
+                outlineColor.copy(alpha = OutlinedIconButtonTokens.DisabledContainerOpacity)
+            }
+        return remember(color) { BorderStroke(SmallIconButtonTokens.OutlinedOutlineWidth, color) }
+    }
+
+    /** Default ripple shape for a standard icon button. */
+    val standardShape: Shape
+        @Composable get() = SmallIconButtonTokens.ContainerShapeRound.value
+
+    /** Default shape for a filled icon button. */
+    val filledShape: Shape
+        @Composable get() = SmallIconButtonTokens.ContainerShapeRound.value
+
+    /** Default shape for an outlined icon button. */
+    val outlinedShape: Shape
+        @Composable get() = SmallIconButtonTokens.ContainerShapeRound.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default round shape for any extra small icon button. */
+    val xSmallRoundShape: Shape
+        @Composable get() = XSmallIconButtonTokens.ContainerShapeRound.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default square shape for any extra small icon button. */
+    val xSmallSquareShape: Shape
+        @Composable get() = XSmallIconButtonTokens.ContainerShapeSquare.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default pressed shape for any extra small icon button. */
+    val xSmallPressedShape: Shape
+        @Composable get() = XSmallIconButtonTokens.PressedContainerShape.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default shape for any small icon button. */
+    val smallRoundShape: Shape
+        @Composable get() = SmallIconButtonTokens.ContainerShapeRound.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default shape for any small icon button. */
+    val smallSquareShape: Shape
+        @Composable get() = SmallIconButtonTokens.ContainerShapeSquare.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default pressed shape for any small icon button. */
+    val smallPressedShape: Shape
+        @Composable get() = SmallIconButtonTokens.PressedContainerShape.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default shape for any medium icon button. */
+    val mediumRoundShape: Shape
+        @Composable get() = MediumIconButtonTokens.ContainerShapeRound.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default shape for any medium icon button. */
+    val mediumSquareShape: Shape
+        @Composable get() = MediumIconButtonTokens.ContainerShapeSquare.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default pressed shape for any medium icon button. */
+    val mediumPressedShape: Shape
+        @Composable get() = MediumIconButtonTokens.PressedContainerShape.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default shape for any large icon button. */
+    val largeRoundShape: Shape
+        @Composable get() = LargeIconButtonTokens.ContainerShapeRound.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default shape for any large icon button. */
+    val largeSquareShape: Shape
+        @Composable get() = LargeIconButtonTokens.ContainerShapeSquare.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default pressed shape for any large icon button. */
+    val largePressedShape: Shape
+        @Composable get() = LargeIconButtonTokens.PressedContainerShape.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default shape for any xlarge icon button. */
+    val xLargeRoundShape: Shape
+        @Composable get() = XLargeIconButtonTokens.ContainerShapeRound.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default shape for any xlarge icon button. */
+    val xLargeSquareShape: Shape
+        @Composable get() = XLargeIconButtonTokens.ContainerShapeSquare.value
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default pressed shape for any extra large icon button. */
+    val xLargePressedShape: Shape
+        @Composable get() = XLargeIconButtonTokens.PressedContainerShape.value
+
+    /**
+     * Creates a [ButtonShapes] that correspond to the shapes in the default, pressed, and checked
+     * states. Toggle button will morph between these shapes as long as the shapes are all
+     * [CornerBasedShape]s.
+     *
+     * @param shape the unchecked shape for [ButtonShapes]
+     * @param pressedShape the unchecked shape for [ButtonShapes]
+     * @param checkedShape the unchecked shape for [ButtonShapes]
+     */
+    @ExperimentalMaterial3ExpressiveApi
+    @Composable
+    fun shapes(shape: Shape, pressedShape: Shape, checkedShape: Shape): IconButtonShapes =
+        remember(shape, pressedShape, checkedShape) {
+            IconButtonShapes(shape, pressedShape, checkedShape)
+        }
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default container for any extra small icon button. */
+    val xSmallIconSize: Dp = XSmallIconButtonTokens.IconSize
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default size for any small icon button. */
+    val smallIconSize: Dp = SmallIconButtonTokens.IconSize
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default container size for any medium icon button. */
+    val mediumIconSize: Dp = MediumIconButtonTokens.IconSize
+
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    /** Default size for any large icon button. */
+    val largeIconSize: Dp = LargeIconButtonTokens.IconSize
+
+    /** Default size for any xlarge icon button. */
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @get:ExperimentalMaterial3ExpressiveApi
+    @ExperimentalMaterial3ExpressiveApi
+    val xLargeIconSize: Dp = XLargeIconButtonTokens.IconSize
+
+    /**
+     * Default container size for any extra small icon button.
+     *
+     * @param widthOption the width of the container
+     */
+    @ExperimentalMaterial3ExpressiveApi
+    fun xSmallContainerSize(
+        widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform
+    ): DpSize {
+        val horizontalSpace =
+            when (widthOption) {
+                IconButtonWidthOption.Narrow ->
+                    XSmallIconButtonTokens.NarrowLeadingSpace +
+                        XSmallIconButtonTokens.NarrowTrailingSpace
+                IconButtonWidthOption.Uniform ->
+                    XSmallIconButtonTokens.UniformLeadingSpace +
+                        XSmallIconButtonTokens.UniformLeadingSpace
+                IconButtonWidthOption.Wide ->
+                    XSmallIconButtonTokens.WideLeadingSpace +
+                        XSmallIconButtonTokens.WideTrailingSpace
+                else -> 0.dp
+            }
+        return DpSize(
+            XSmallIconButtonTokens.IconSize + horizontalSpace,
+            XSmallIconButtonTokens.ContainerHeight
+        )
+    }
+
+    /**
+     * Default container size for any small icon button.
+     *
+     * @param widthOption the width of the container
+     */
+    @ExperimentalMaterial3ExpressiveApi
+    fun smallContainerSize(
+        widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform
+    ): DpSize {
+        val horizontalSpace =
+            when (widthOption) {
+                IconButtonWidthOption.Narrow ->
+                    SmallIconButtonTokens.NarrowLeadingSpace +
+                        SmallIconButtonTokens.NarrowTrailingSpace
+                IconButtonWidthOption.Uniform ->
+                    SmallIconButtonTokens.UniformLeadingSpace +
+                        SmallIconButtonTokens.UniformLeadingSpace
+                IconButtonWidthOption.Wide ->
+                    SmallIconButtonTokens.WideLeadingSpace + SmallIconButtonTokens.WideTrailingSpace
+                else -> 0.dp
+            }
+        return DpSize(
+            SmallIconButtonTokens.IconSize + horizontalSpace,
+            SmallIconButtonTokens.ContainerHeight
+        )
+    }
+
+    /**
+     * Default container size for any medium icon button.
+     *
+     * @param widthOption the width of the container
+     */
+    @ExperimentalMaterial3ExpressiveApi
+    fun mediumContainerSize(
+        widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform
+    ): DpSize {
+        val horizontalSpace =
+            when (widthOption) {
+                IconButtonWidthOption.Narrow ->
+                    MediumIconButtonTokens.NarrowLeadingSpace +
+                        MediumIconButtonTokens.NarrowTrailingSpace
+                IconButtonWidthOption.Uniform ->
+                    MediumIconButtonTokens.UniformLeadingSpace +
+                        MediumIconButtonTokens.UniformLeadingSpace
+                IconButtonWidthOption.Wide ->
+                    MediumIconButtonTokens.WideLeadingSpace +
+                        MediumIconButtonTokens.WideTrailingSpace
+                else -> 0.dp
+            }
+        return DpSize(
+            MediumIconButtonTokens.IconSize + horizontalSpace,
+            MediumIconButtonTokens.ContainerHeight
+        )
+    }
+
+    /**
+     * Default container size for any large icon button.
+     *
+     * @param widthOption the width of the container
+     */
+    @ExperimentalMaterial3ExpressiveApi
+    fun largeContainerSize(
+        widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform
+    ): DpSize {
+        val horizontalSpace =
+            when (widthOption) {
+                IconButtonWidthOption.Narrow ->
+                    LargeIconButtonTokens.NarrowLeadingSpace +
+                        LargeIconButtonTokens.NarrowTrailingSpace
+                IconButtonWidthOption.Uniform ->
+                    LargeIconButtonTokens.UniformLeadingSpace +
+                        LargeIconButtonTokens.UniformLeadingSpace
+                IconButtonWidthOption.Wide ->
+                    LargeIconButtonTokens.WideLeadingSpace + LargeIconButtonTokens.WideTrailingSpace
+                else -> 0.dp
+            }
+        return DpSize(
+            LargeIconButtonTokens.IconSize + horizontalSpace,
+            LargeIconButtonTokens.ContainerHeight
+        )
+    }
+
+    /**
+     * Default container size for any extra large icon button.
+     *
+     * @param widthOption the width of the container
+     */
+    @ExperimentalMaterial3ExpressiveApi
+    fun xLargeContainerSize(
+        widthOption: IconButtonWidthOption = IconButtonWidthOption.Uniform
+    ): DpSize {
+        val horizontalSpace =
+            when (widthOption) {
+                IconButtonWidthOption.Narrow ->
+                    XLargeIconButtonTokens.NarrowLeadingSpace +
+                        XLargeIconButtonTokens.NarrowTrailingSpace
+                IconButtonWidthOption.Uniform ->
+                    XLargeIconButtonTokens.UniformLeadingSpace +
+                        XLargeIconButtonTokens.UniformLeadingSpace
+                IconButtonWidthOption.Wide ->
+                    XLargeIconButtonTokens.WideLeadingSpace +
+                        XLargeIconButtonTokens.WideTrailingSpace
+                else -> 0.dp
+            }
+        return DpSize(
+            XLargeIconButtonTokens.IconSize + horizontalSpace,
+            XLargeIconButtonTokens.ContainerHeight
+        )
+    }
+
+    /** Class that describes the different supported widths of the [IconButton]. */
+    @JvmInline
+    value class IconButtonWidthOption private constructor(private val value: Int) {
+        companion object {
+            // TODO(b/342666275): update this kdoc with spec guidance
+            /*
+             * This configuration is recommended for small screens.
+             */
+            val Narrow = IconButtonWidthOption(0)
+
+            /*
+             * This configuration is recommended for medium width screens.
+             */
+            val Uniform = IconButtonWidthOption(1)
+
+            /*
+             * This configuration is recommended for wide screens.
+             */
+            val Wide = IconButtonWidthOption(2)
+        }
+
+        override fun toString() =
+            when (this) {
+                Narrow -> "Narrow"
+                Uniform -> "Uniform"
+                Wide -> "Wide"
+                else -> "Unknown"
+            }
+    }
+}
+
+/**
+ * Represents the container and content colors used in an icon button in different states.
+ *
+ * @param containerColor the container color of this icon button when enabled.
+ * @param contentColor the content color of this icon button when enabled.
+ * @param disabledContainerColor the container color of this icon button when not enabled.
+ * @param disabledContentColor the content color of this icon button when not enabled.
+ * @constructor create an instance with arbitrary colors.
+ * - See [IconButtonDefaults.filledIconButtonColors] and
+ *   [IconButtonDefaults.filledTonalIconButtonColors] for the default colors used in a
+ *   [FilledIconButton].
+ * - See [IconButtonDefaults.outlinedIconButtonVibrantColors] for the default colors used in an
+ *   [OutlinedIconButton].
+ */
+@Immutable
+class IconButtonColors(
+    val containerColor: Color,
+    val contentColor: Color,
+    val disabledContainerColor: Color,
+    val disabledContentColor: Color,
+) {
+
+    /**
+     * Returns a copy of this IconButtonColors, optionally overriding some of the values. This uses
+     * the Color.Unspecified to mean “use the value from the source”
+     */
+    fun copy(
+        containerColor: Color = this.containerColor,
+        contentColor: Color = this.contentColor,
+        disabledContainerColor: Color = this.disabledContainerColor,
+        disabledContentColor: Color = this.disabledContentColor,
+    ) =
+        IconButtonColors(
+            containerColor.takeOrElse { this.containerColor },
+            contentColor.takeOrElse { this.contentColor },
+            disabledContainerColor.takeOrElse { this.disabledContainerColor },
+            disabledContentColor.takeOrElse { this.disabledContentColor },
+        )
+
+    /**
+     * Represents the container color for this icon button, depending on [enabled].
+     *
+     * @param enabled whether the icon button is enabled
+     */
+    @Stable
+    internal fun containerColor(enabled: Boolean): Color =
+        if (enabled) containerColor else disabledContainerColor
+
+    /**
+     * Represents the content color for this icon button, depending on [enabled].
+     *
+     * @param enabled whether the icon button is enabled
+     */
+    @Stable
+    internal fun contentColor(enabled: Boolean): Color =
+        if (enabled) contentColor else disabledContentColor
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || other !is IconButtonColors) return false
+
+        if (containerColor != other.containerColor) return false
+        if (contentColor != other.contentColor) return false
+        if (disabledContainerColor != other.disabledContainerColor) return false
+        if (disabledContentColor != other.disabledContentColor) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = containerColor.hashCode()
+        result = 31 * result + contentColor.hashCode()
+        result = 31 * result + disabledContainerColor.hashCode()
+        result = 31 * result + disabledContentColor.hashCode()
+
+        return result
+    }
+}
+
+/**
+ * Represents the container and content colors used in a toggleable icon button in different states.
+ *
+ * @param containerColor the container color of this icon button when enabled.
+ * @param contentColor the content color of this icon button when enabled.
+ * @param disabledContainerColor the container color of this icon button when not enabled.
+ * @param disabledContentColor the content color of this icon button when not enabled.
+ * @param checkedContainerColor the container color of this icon button when checked.
+ * @param checkedContentColor the content color of this icon button when checked.
+ * @constructor create an instance with arbitrary colors.
+ * - See [IconButtonDefaults.filledIconToggleButtonColors] and
+ *   [IconButtonDefaults.filledTonalIconToggleButtonColors] for the default colors used in a
+ *   [FilledIconButton].
+ * - See [IconButtonDefaults.outlinedIconToggleButtonVibrantColors] for the default colors used in a
+ *   toggleable [OutlinedIconButton].
+ */
+@Immutable
+class IconToggleButtonColors(
+    val containerColor: Color,
+    val contentColor: Color,
+    val disabledContainerColor: Color,
+    val disabledContentColor: Color,
+    val checkedContainerColor: Color,
+    val checkedContentColor: Color,
+) {
+
+    /**
+     * Returns a copy of this IconToggleButtonColors, optionally overriding some of the values. This
+     * uses the Color.Unspecified to mean “use the value from the source”
+     */
+    fun copy(
+        containerColor: Color = this.containerColor,
+        contentColor: Color = this.contentColor,
+        disabledContainerColor: Color = this.disabledContainerColor,
+        disabledContentColor: Color = this.disabledContentColor,
+        checkedContainerColor: Color = this.checkedContainerColor,
+        checkedContentColor: Color = this.checkedContentColor
+    ) =
+        IconToggleButtonColors(
+            containerColor.takeOrElse { this.containerColor },
+            contentColor.takeOrElse { this.contentColor },
+            disabledContainerColor.takeOrElse { this.disabledContainerColor },
+            disabledContentColor.takeOrElse { this.disabledContentColor },
+            checkedContainerColor.takeOrElse { this.checkedContainerColor },
+            checkedContentColor.takeOrElse { this.checkedContentColor }
+        )
+
+    /**
+     * Represents the container color for this icon button, depending on [enabled] and [checked].
+     *
+     * @param enabled whether the icon button is enabled
+     * @param checked whether the icon button is checked
+     */
+    @Composable
+    internal fun containerColor(enabled: Boolean, checked: Boolean): State<Color> {
+        val target =
+            when {
+                !enabled -> disabledContainerColor
+                !checked -> containerColor
+                else -> checkedContainerColor
+            }
+        return rememberUpdatedState(target)
+    }
+
+    /**
+     * Represents the content color for this icon button, depending on [enabled] and [checked].
+     *
+     * @param enabled whether the icon button is enabled
+     * @param checked whether the icon button is checked
+     */
+    @Composable
+    internal fun contentColor(enabled: Boolean, checked: Boolean): State<Color> {
+        val target =
+            when {
+                !enabled -> disabledContentColor
+                !checked -> contentColor
+                else -> checkedContentColor
+            }
+        return rememberUpdatedState(target)
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other == null || other !is IconToggleButtonColors) return false
+
+        if (containerColor != other.containerColor) return false
+        if (contentColor != other.contentColor) return false
+        if (disabledContainerColor != other.disabledContainerColor) return false
+        if (disabledContentColor != other.disabledContentColor) return false
+        if (checkedContainerColor != other.checkedContainerColor) return false
+        if (checkedContentColor != other.checkedContentColor) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = containerColor.hashCode()
+        result = 31 * result + contentColor.hashCode()
+        result = 31 * result + disabledContainerColor.hashCode()
+        result = 31 * result + disabledContentColor.hashCode()
+        result = 31 * result + checkedContainerColor.hashCode()
+        result = 31 * result + checkedContentColor.hashCode()
+
+        return result
+    }
+}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SearchBar.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SearchBar.kt
index bc1f68a..860584f 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SearchBar.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SearchBar.kt
@@ -165,6 +165,7 @@
 import androidx.compose.ui.util.fastFirst
 import androidx.compose.ui.util.fastFirstOrNull
 import androidx.compose.ui.util.lerp
+import androidx.compose.ui.window.DialogProperties
 import androidx.compose.ui.zIndex
 import kotlin.coroutines.cancellation.CancellationException
 import kotlin.math.abs
@@ -186,16 +187,15 @@
  * ![Search bar
  * image](https://developer.android.com/images/reference/androidx/compose/material3/search-bar.png)
  *
- * A search bar expands when focused to display dynamic suggestions or search results. An expanded
- * [SearchBar] displays its results in a full-screen dialog. If this expansion behavior is
- * undesirable, for example on large tablet screens, consider using [DockedSearchBar] instead.
+ * The [SearchBar] component represents a search bar in the collapsed state. It should be used in
+ * conjunction with an [ExpandedFullScreenSearchBar] to display search results when expanded.
  *
- * @param state the state of the search bar. This state should also be passed to the [inputField].
+ * @param state the state of the search bar. This state should also be passed to the [inputField]
+ *   and the expanded search bar.
  * @param inputField the input field of this search bar that allows entering a query, typically a
  *   [SearchBarDefaults.InputField].
  * @param modifier the [Modifier] to be applied to this search bar when collapsed.
- * @param shape the shape of this search bar when it is collapsed. When expanded, the shape will
- *   always be [SearchBarDefaults.fullScreenShape].
+ * @param shape the shape of this search bar when collapsed.
  * @param colors [SearchBarColors] that will be used to resolve the colors used for this search bar
  *   in different states. See [SearchBarDefaults.colors].
  * @param tonalElevation when [SearchBarColors.containerColor] is [ColorScheme.surface], a
@@ -203,8 +203,8 @@
  *   value will result in a darker color in light theme and lighter color in dark theme. See also:
  *   [Surface].
  * @param shadowElevation the elevation for the shadow below this search bar.
- * @param content the content of this search bar to display search results below the [inputField].
  */
+@Suppress("ComposableLambdaParameterNaming", "ComposableLambdaParameterPosition")
 @ExperimentalMaterial3Api
 @Composable
 internal fun SearchBar(
@@ -215,27 +215,19 @@
     colors: SearchBarColors = SearchBarDefaults.colors(),
     tonalElevation: Dp = SearchBarDefaults.TonalElevation,
     shadowElevation: Dp = SearchBarDefaults.ShadowElevation,
-    content: @Composable ColumnScope.() -> Unit,
 ) {
-    CollapsedSearchBar(
-        // Modifier gets passed to Collapsed because Expanded opens a separate dialog.
-        modifier = modifier,
-        state = state,
-        inputField = inputField,
-        shape = shape,
-        colors = colors,
-        tonalElevation = tonalElevation,
-        shadowElevation = shadowElevation
-    )
-    ExpandedFullScreenSearchBar(
-        state = state,
-        inputField = inputField,
-        collapsedShape = shape,
-        colors = colors,
-        tonalElevation = tonalElevation,
-        shadowElevation = shadowElevation,
-        content = content
-    )
+    // Disable when collapsed to avoid keyboard flicker when the expanded search bar opens.
+    DisableSoftKeyboard {
+        Surface(
+            modifier = modifier.onGloballyPositioned { state.collapsedCoords = it },
+            shape = shape,
+            color = colors.containerColor,
+            contentColor = contentColorFor(colors.containerColor),
+            tonalElevation = tonalElevation,
+            shadowElevation = shadowElevation,
+            content = inputField,
+        )
+    }
 }
 
 /**
@@ -245,18 +237,21 @@
  * A search bar represents a field that allows users to enter a keyword or phrase and get relevant
  * information. It can be used as a way to navigate through an app via search queries.
  *
- * A [TopSearchBar] can be used in conjunction with a [Scaffold] for a search bar that remains at
- * the top of the screen.
- *
  * ![Search bar
  * image](https://developer.android.com/images/reference/androidx/compose/material3/search-bar.png)
  *
- * @param state the state of the search bar. This state should also be passed to the [inputField].
+ * A [TopSearchBar] is a [SearchBar] with additional handling for top app bar behavior, such as
+ * window insets and scrolling. Using a [TopSearchBar] as the top bar of a [Scaffold] ensures that
+ * the search bar remains at the top of the screen. Like with [SearchBar], [TopSearchBar] should be
+ * used in conjunction with an [ExpandedFullScreenSearchBar] to display search results when
+ * expanded.
+ *
+ * @param state the state of the search bar. This state should also be passed to the [inputField]
+ *   and the expanded search bar.
  * @param inputField the input field of this search bar that allows entering a query, typically a
  *   [SearchBarDefaults.InputField].
  * @param modifier the [Modifier] to be applied to this search bar when collapsed.
- * @param shape the shape of this search bar when it is collapsed. When expanded, the shape will
- *   always be [SearchBarDefaults.fullScreenShape].
+ * @param shape the shape of this search bar when collapsed.
  * @param colors [SearchBarColors] that will be used to resolve the colors used for this search bar
  *   in different states. See [SearchBarDefaults.colors].
  * @param tonalElevation when [SearchBarColors.containerColor] is [ColorScheme.surface], a
@@ -264,13 +259,12 @@
  *   value will result in a darker color in light theme and lighter color in dark theme. See also:
  *   [Surface].
  * @param shadowElevation the elevation for the shadow below this search bar.
- * @param windowInsets the window insets that the search bar will respect when collapsed. When
- *   expanded, the window insets will always be [SearchBarDefaults.fullScreenWindowInsets].
+ * @param windowInsets the window insets that the search bar will respect when collapsed.
  * @param scrollBehavior a [SearchBarScrollBehavior] which works in conjunction with a scrolled
  *   content to change the search bar appearance as the content scrolls. If null, the search bar
  *   will not automatically react to scrolling.
- * @param content the content of this search bar to display search results below the [inputField].
  */
+@Suppress("ComposableLambdaParameterNaming", "ComposableLambdaParameterPosition")
 @ExperimentalMaterial3Api
 @Composable
 internal fun TopSearchBar(
@@ -283,7 +277,6 @@
     shadowElevation: Dp = SearchBarDefaults.ShadowElevation,
     windowInsets: WindowInsets = SearchBarDefaults.windowInsets,
     scrollBehavior: SearchBarScrollBehavior? = null,
-    content: @Composable ColumnScope.() -> Unit,
 ) {
     SearchBar(
         state = state,
@@ -302,11 +295,85 @@
         colors = colors,
         tonalElevation = tonalElevation,
         shadowElevation = shadowElevation,
-        content = content,
     )
 }
 
 /**
+ * [ExpandedFullScreenSearchBar] represents a search bar that is currently expanding or in the
+ * expanded state, showing search results. This component is displayed in a new full-screen dialog.
+ *
+ * @param state the state of the search bar. This state should also be passed to the [inputField]
+ *   and the collapsed search bar.
+ * @param inputField the input field of this search bar that allows entering a query, typically a
+ *   [SearchBarDefaults.InputField].
+ * @param modifier the [Modifier] to be applied to this expanded search bar.
+ * @param collapsedShape the shape of the search bar when it is collapsed. When fully expanded, the
+ *   shape will always be [SearchBarDefaults.fullScreenShape].
+ * @param colors [SearchBarColors] that will be used to resolve the colors used for this search bar
+ *   in different states. See [SearchBarDefaults.colors].
+ * @param tonalElevation when [SearchBarColors.containerColor] is [ColorScheme.surface], a
+ *   translucent primary color overlay is applied on top of the container. A higher tonal elevation
+ *   value will result in a darker color in light theme and lighter color in dark theme. See also:
+ *   [Surface].
+ * @param shadowElevation the elevation for the shadow below this search bar.
+ * @param windowInsets the window insets that this search bar will respect when expanded.
+ * @param properties the platform-specific properties to configure the dialog's behavior. Any
+ *   properties which limit the dialog's size (e.g. [DialogProperties.usePlatformDefaultWidth]) are
+ *   ignored.
+ * @param content the content of this search bar to display search results below the [inputField].
+ */
+@ExperimentalMaterial3Api
+@Composable
+internal fun ExpandedFullScreenSearchBar(
+    state: SearchBarState,
+    inputField: @Composable () -> Unit,
+    modifier: Modifier = Modifier,
+    collapsedShape: Shape = SearchBarDefaults.inputFieldShape,
+    colors: SearchBarColors = SearchBarDefaults.colors(),
+    tonalElevation: Dp = SearchBarDefaults.TonalElevation,
+    shadowElevation: Dp = SearchBarDefaults.ShadowElevation,
+    windowInsets: @Composable () -> WindowInsets = { SearchBarDefaults.fullScreenWindowInsets },
+    properties: DialogProperties = DialogProperties(),
+    content: @Composable ColumnScope.() -> Unit,
+) {
+    if (!state.isExpanded) return
+
+    val coroutineScope = rememberCoroutineScope()
+
+    BasicEdgeToEdgeDialog(
+        onDismissRequest = { coroutineScope.launch { state.animateToCollapsed() } },
+        properties = properties,
+    ) { predictiveBackState ->
+        val focusRequester = remember { FocusRequester() }
+        val softwareKeyboardController = LocalSoftwareKeyboardController.current
+        SideEffect { state.softwareKeyboardController = softwareKeyboardController }
+        FullScreenSearchBarLayout(
+            state = state,
+            predictiveBackState = predictiveBackState,
+            inputField = {
+                Box(
+                    modifier = Modifier.focusRequester(focusRequester),
+                    propagateMinConstraints = true,
+                ) {
+                    inputField()
+                }
+            },
+            modifier = modifier,
+            collapsedShape = collapsedShape,
+            colors = colors,
+            tonalElevation = tonalElevation,
+            shadowElevation = shadowElevation,
+            windowInsets = windowInsets(),
+            content = content,
+        )
+
+        // Focus the input field on the first expansion,
+        // but no need to re-focus if the focus gets cleared.
+        LaunchedEffect(state.isExpanded) { focusRequester.requestFocus() }
+    }
+}
+
+/**
  * <a href="https://m3.material.io/components/search/overview" class="external"
  * target="_blank">Material Design search</a>.
  *
@@ -508,118 +575,7 @@
     BackHandler(enabled = expanded) { onExpandedChange(false) }
 }
 
-/**
- * A building block component representing a search bar in the collapsed state.
- *
- * Unless specific customization is needed, consider using a higher level component such as
- * [SearchBar] or [DockedSearchBar] instead.
- *
- * @param state the state of the search bar. This state should also be passed to the [inputField].
- * @param inputField the input field of this search bar that allows entering a query, typically a
- *   [SearchBarDefaults.InputField].
- * @param modifier the [Modifier] to be applied to this collapsed search bar.
- * @param shape the shape of this search bar.
- * @param colors [SearchBarColors] that will be used to resolve the colors used for this search bar
- *   in different states. See [SearchBarDefaults.colors].
- * @param tonalElevation when [SearchBarColors.containerColor] is [ColorScheme.surface], a
- *   translucent primary color overlay is applied on top of the container. A higher tonal elevation
- *   value will result in a darker color in light theme and lighter color in dark theme. See also:
- *   [Surface].
- * @param shadowElevation the elevation for the shadow below this search bar.
- */
-@Suppress("ComposableLambdaParameterNaming", "ComposableLambdaParameterPosition")
-@ExperimentalMaterial3Api
-@Composable
-internal fun CollapsedSearchBar(
-    state: SearchBarState,
-    inputField: @Composable () -> Unit,
-    modifier: Modifier = Modifier,
-    shape: Shape = SearchBarDefaults.inputFieldShape,
-    colors: SearchBarColors = SearchBarDefaults.colors(),
-    tonalElevation: Dp = SearchBarDefaults.TonalElevation,
-    shadowElevation: Dp = SearchBarDefaults.ShadowElevation,
-) {
-    // Disable when collapsed to avoid keyboard flicker when the expanded search bar opens.
-    DisableSoftKeyboard {
-        Surface(
-            modifier = modifier.onGloballyPositioned { state.collapsedCoords = it },
-            shape = shape,
-            color = colors.containerColor,
-            contentColor = contentColorFor(colors.containerColor),
-            tonalElevation = tonalElevation,
-            shadowElevation = shadowElevation,
-            content = inputField,
-        )
-    }
-}
-
-/**
- * A building block component representing a search bar that is currently expanding or in the
- * expanded state. This component is displayed in a new full-screen dialog.
- *
- * Unless specific customization is needed, consider using a higher level component such as
- * [SearchBar] or [DockedSearchBar] instead.
- *
- * @param state the state of the search bar. This state should also be passed to the [inputField].
- * @param inputField the input field of this search bar that allows entering a query, typically a
- *   [SearchBarDefaults.InputField].
- * @param modifier the [Modifier] to be applied to this expanded search bar.
- * @param collapsedShape the shape of the search bar when it is collapsed. When fully expanded, the
- *   shape will always be [SearchBarDefaults.fullScreenShape].
- * @param colors [SearchBarColors] that will be used to resolve the colors used for this search bar
- *   in different states. See [SearchBarDefaults.colors].
- * @param tonalElevation when [SearchBarColors.containerColor] is [ColorScheme.surface], a
- *   translucent primary color overlay is applied on top of the container. A higher tonal elevation
- *   value will result in a darker color in light theme and lighter color in dark theme. See also:
- *   [Surface].
- * @param shadowElevation the elevation for the shadow below this search bar.
- * @param windowInsets the window insets that this search bar will respect.
- * @param content the content of this search bar to display search results below the [inputField].
- */
-@ExperimentalMaterial3Api
-@Composable
-internal fun ExpandedFullScreenSearchBar(
-    state: SearchBarState,
-    inputField: @Composable () -> Unit,
-    modifier: Modifier = Modifier,
-    collapsedShape: Shape = SearchBarDefaults.inputFieldShape,
-    colors: SearchBarColors = SearchBarDefaults.colors(),
-    tonalElevation: Dp = SearchBarDefaults.TonalElevation,
-    shadowElevation: Dp = SearchBarDefaults.ShadowElevation,
-    windowInsets: @Composable () -> WindowInsets = { SearchBarDefaults.fullScreenWindowInsets },
-    content: @Composable ColumnScope.() -> Unit,
-) {
-    if (!state.isExpanded) return
-
-    val coroutineScope = rememberCoroutineScope()
-
-    BasicEdgeToEdgeDialog(
-        onDismissRequest = { coroutineScope.launch { state.animateToCollapsed() } }
-    ) { predictiveBackState ->
-        val softwareKeyboardController = LocalSoftwareKeyboardController.current
-        SideEffect { state.softwareKeyboardController = softwareKeyboardController }
-        FullScreenSearchBarLayout(
-            state = state,
-            predictiveBackState = predictiveBackState,
-            inputField = inputField,
-            modifier = modifier,
-            collapsedShape = collapsedShape,
-            colors = colors,
-            tonalElevation = tonalElevation,
-            shadowElevation = shadowElevation,
-            windowInsets = windowInsets(),
-            content = content,
-        )
-    }
-}
-
-/**
- * The state of a search bar.
- *
- * @property focusRequester The [FocusRequester] to request focus on the search bar.
- *   [SearchBarDefaults.InputField] applies this automatically. Custom input fields must attach this
- *   focus requester using [Modifier.focusRequester].
- */
+/** The state of a search bar. */
 @ExperimentalMaterial3Api
 @Stable
 internal class SearchBarState
@@ -627,7 +583,6 @@
     private val animatable: Animatable<Float, AnimationVector1D>,
     private val animationSpecForExpand: AnimationSpec<Float>,
     private val animationSpecForCollapse: AnimationSpec<Float>,
-    val focusRequester: FocusRequester,
 ) {
     /**
      * Construct a [SearchBarState].
@@ -635,21 +590,21 @@
      * @param initialExpanded the initial value of whether the search bar is expanded.
      * @param animationSpecForExpand the animation spec used when the search bar expands.
      * @param animationSpecForCollapse the animation spec used when the search bar collapses.
-     * @param focusRequester the focus requester to be applied to the search bar's input field.
      */
     constructor(
         initialExpanded: Boolean,
         animationSpecForExpand: AnimationSpec<Float>,
         animationSpecForCollapse: AnimationSpec<Float>,
-        focusRequester: FocusRequester = FocusRequester(),
     ) : this(
         animatable = Animatable(if (initialExpanded) 1f else 0f),
         animationSpecForExpand = animationSpecForExpand,
         animationSpecForCollapse = animationSpecForCollapse,
-        focusRequester = focusRequester,
     )
 
-    /** The layout coordinates, if available, of the search bar when it is collapsed. */
+    /**
+     * The layout coordinates, if available, of the search bar when it is collapsed. Used to
+     * coordinate the expansion animation.
+     */
     var collapsedCoords: LayoutCoordinates? by mutableStateOf(null)
 
     /**
@@ -660,9 +615,7 @@
     val progress: Float
         get() = animatable.value.coerceIn(0f, 1f)
 
-    /**
-     * Whether this search bar is expanded (showing search results), or in the process of expanding.
-     */
+    /** Whether this search bar is expanded or in the process of expanding. */
     val isExpanded: Boolean by derivedStateOf { progress > 0f }
 
     internal var softwareKeyboardController: SoftwareKeyboardController? = null
@@ -670,7 +623,6 @@
     /** Animate the search bar to its expanded state. */
     suspend fun animateToExpanded() {
         animatable.animateTo(targetValue = 1f, animationSpec = animationSpecForExpand)
-        focusRequester.requestFocus()
     }
 
     /** Animate the search bar to its collapsed state. */
@@ -688,7 +640,6 @@
         fun Saver(
             animationSpecForExpand: AnimationSpec<Float>,
             animationSpecForCollapse: AnimationSpec<Float>,
-            focusRequester: FocusRequester,
         ): Saver<SearchBarState, *> =
             listSaver(
                 save = { listOf(it.progress) },
@@ -697,7 +648,6 @@
                         animatable = Animatable(it[0], Float.VectorConverter),
                         animationSpecForExpand = animationSpecForExpand,
                         animationSpecForCollapse = animationSpecForCollapse,
-                        focusRequester = focusRequester,
                     )
                 },
             )
@@ -710,7 +660,6 @@
  * @param initialExpanded the initial value of whether the search bar is expanded.
  * @param animationSpecForExpand the animation spec used when the search bar expands.
  * @param animationSpecForCollapse the animation spec used when the search bar collapses.
- * @param focusRequester the focus requester to be applied to the search bar's input field.
  */
 @ExperimentalMaterial3Api
 @Composable
@@ -718,26 +667,21 @@
     initialExpanded: Boolean = false,
     animationSpecForExpand: AnimationSpec<Float> = MotionSchemeKeyTokens.SlowSpatial.value(),
     animationSpecForCollapse: AnimationSpec<Float> = MotionSchemeKeyTokens.DefaultSpatial.value(),
-    focusRequester: FocusRequester? = null,
 ): SearchBarState {
-    @Suppress("NAME_SHADOWING") val focusRequester = focusRequester ?: remember { FocusRequester() }
     return rememberSaveable(
         initialExpanded,
         animationSpecForExpand,
         animationSpecForCollapse,
-        focusRequester,
         saver =
             SearchBarState.Saver(
                 animationSpecForExpand = animationSpecForExpand,
                 animationSpecForCollapse = animationSpecForCollapse,
-                focusRequester = focusRequester,
             )
     ) {
         SearchBarState(
             initialExpanded = initialExpanded,
             animationSpecForExpand = animationSpecForExpand,
             animationSpecForCollapse = animationSpecForCollapse,
-            focusRequester = focusRequester,
         )
     }
 }
@@ -1224,6 +1168,7 @@
 
         val focused = interactionSource.collectIsFocusedAsState().value
         val focusManager = LocalFocusManager.current
+        val focusRequester = remember { FocusRequester() }
 
         val searchSemantics = getString(Strings.SearchBarSearch)
         val suggestionsAvailableSemantics = getString(Strings.SuggestionsAvailable)
@@ -1245,7 +1190,7 @@
                         maxWidth = SearchBarMaxWidth,
                         minHeight = InputFieldHeight,
                     )
-                    .focusRequester(searchBarState.focusRequester)
+                    .focusRequester(focusRequester)
                     .onFocusChanged {
                         if (it.isFocused) {
                             coroutineScope.launch { searchBarState.animateToExpanded() }
@@ -1257,7 +1202,7 @@
                             stateDescription = suggestionsAvailableSemantics
                         }
                         onClick {
-                            searchBarState.focusRequester.requestFocus()
+                            focusRequester.requestFocus()
                             true
                         }
                     },
@@ -2508,7 +2453,7 @@
 private const val LayoutIdSearchContent = "Content"
 
 // Measurement specs
-private val SearchBarAsTopBarPadding = 8.dp
+internal val SearchBarAsTopBarPadding = 8.dp
 @OptIn(ExperimentalMaterial3Api::class) private val SearchBarCornerRadius: Dp = InputFieldHeight / 2
 internal val DockedExpandedTableMinHeight: Dp = 240.dp
 private const val DockedExpandedTableMaxHeightScreenRatio: Float = 2f / 3f
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Slider.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Slider.kt
index 215eba6..7705df8 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Slider.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Slider.kt
@@ -2449,7 +2449,7 @@
     }
 
     /** callback in which value should be updated */
-    internal var onValueChange: ((Float) -> Unit)? = null
+    var onValueChange: ((Float) -> Unit)? = null
 
     internal val tickFractions = stepsToTickFractions(steps)
     private var totalWidth by mutableIntStateOf(0)
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarLargeFlexibleTokens.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarLargeFlexibleTokens.kt
new file mode 100644
index 0000000..48df916
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarLargeFlexibleTokens.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: 14_0_0
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.compose.material3.tokens
+
+import androidx.compose.ui.unit.dp
+
+internal object AppBarLargeFlexibleTokens {
+    val ContainerHeight = 120.0.dp
+    val SubtitleFont = TypographyKeyTokens.TitleMedium
+    val TitleFont = TypographyKeyTokens.DisplaySmall
+    val LargeContainerHeight = 152.0.dp
+}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarLargeTokens.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarLargeTokens.kt
new file mode 100644
index 0000000..2295347
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarLargeTokens.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+// VERSION: 14_0_0
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.compose.material3.tokens
+
+import androidx.compose.ui.unit.dp
+
+internal object AppBarLargeTokens {
+    val ContainerHeight = 152.0.dp
+    val TitleFont = TypographyKeyTokens.HeadlineMedium
+}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarMediumFlexibleTokens.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarMediumFlexibleTokens.kt
new file mode 100644
index 0000000..fd1dda4
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarMediumFlexibleTokens.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: 14_0_0
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.compose.material3.tokens
+
+import androidx.compose.ui.unit.dp
+
+internal object AppBarMediumFlexibleTokens {
+    val ContainerHeight = 112.0.dp
+    val SubtitleFont = TypographyKeyTokens.LabelLarge
+    val TitleFont = TypographyKeyTokens.HeadlineMedium
+    val LargeContainerHeight = 136.0.dp
+}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarMediumTokens.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarMediumTokens.kt
new file mode 100644
index 0000000..6475942
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarMediumTokens.kt
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+// VERSION: 14_0_0
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.compose.material3.tokens
+
+import androidx.compose.ui.unit.dp
+
+internal object AppBarMediumTokens {
+    val ContainerHeight = 112.0.dp
+    val TitleFont = TypographyKeyTokens.HeadlineSmall
+}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarSmallTokens.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarSmallTokens.kt
new file mode 100644
index 0000000..73a1624
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarSmallTokens.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// VERSION: 14_0_0
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.compose.material3.tokens
+
+import androidx.compose.ui.unit.dp
+
+internal object AppBarSmallTokens {
+    val ContainerHeight = 64.0.dp
+    val SubtitleFont = TypographyKeyTokens.LabelMedium
+    val TitleFont = TypographyKeyTokens.TitleLarge
+}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TopAppBarSmallTokens.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarTokens.kt
similarity index 75%
rename from compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TopAppBarSmallTokens.kt
rename to compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarTokens.kt
index 4e099d3..6fa1382 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TopAppBarSmallTokens.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/AppBarTokens.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -13,24 +13,27 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-// VERSION: v0_210
+
+// VERSION: 14_0_0
 // GENERATED CODE - DO NOT MODIFY BY HAND
 
 package androidx.compose.material3.tokens
 
 import androidx.compose.ui.unit.dp
 
-internal object TopAppBarSmallTokens {
+internal object AppBarTokens {
+    val AvatarSize = 32.0.dp
     val ContainerColor = ColorSchemeKeyTokens.Surface
     val ContainerElevation = ElevationTokens.Level0
-    val ContainerHeight = 64.0.dp
     val ContainerShape = ShapeKeyTokens.CornerNone
-    val HeadlineColor = ColorSchemeKeyTokens.OnSurface
-    val HeadlineFont = TypographyKeyTokens.TitleLarge
+    val IconButtonSpace = 0.0.dp
+    val IconSize = 24.0.dp
     val LeadingIconColor = ColorSchemeKeyTokens.OnSurface
-    val LeadingIconSize = 24.0.dp
+    val LeadingSpace = 4.0.dp
     val OnScrollContainerColor = ColorSchemeKeyTokens.SurfaceContainer
     val OnScrollContainerElevation = ElevationTokens.Level2
+    val SubtitleColor = ColorSchemeKeyTokens.OnSurfaceVariant
+    val TitleColor = ColorSchemeKeyTokens.OnSurface
     val TrailingIconColor = ColorSchemeKeyTokens.OnSurfaceVariant
-    val TrailingIconSize = 24.0.dp
+    val TrailingSpace = 4.0.dp
 }
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TopAppBarLargeTokens.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TopAppBarLargeTokens.kt
deleted file mode 100644
index b45cf89..0000000
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TopAppBarLargeTokens.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// VERSION: v0_103
-// GENERATED CODE - DO NOT MODIFY BY HAND
-
-package androidx.compose.material3.tokens
-
-import androidx.compose.ui.unit.dp
-
-internal object TopAppBarLargeTokens {
-    val ContainerColor = ColorSchemeKeyTokens.Surface
-    val ContainerElevation = ElevationTokens.Level0
-    val ContainerHeight = 152.0.dp
-    val ContainerShape = ShapeKeyTokens.CornerNone
-    val ContainerSurfaceTintLayerColor = ColorSchemeKeyTokens.SurfaceTint
-    val HeadlineColor = ColorSchemeKeyTokens.OnSurface
-    val HeadlineFont = TypographyKeyTokens.HeadlineMedium
-    val LeadingIconColor = ColorSchemeKeyTokens.OnSurface
-    val LeadingIconSize = 24.0.dp
-    val TrailingIconColor = ColorSchemeKeyTokens.OnSurfaceVariant
-    val TrailingIconSize = 24.0.dp
-}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TopAppBarMediumTokens.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TopAppBarMediumTokens.kt
deleted file mode 100644
index b342dc2..0000000
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TopAppBarMediumTokens.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// VERSION: v0_103
-// GENERATED CODE - DO NOT MODIFY BY HAND
-
-package androidx.compose.material3.tokens
-
-import androidx.compose.ui.unit.dp
-
-internal object TopAppBarMediumTokens {
-    val ContainerColor = ColorSchemeKeyTokens.Surface
-    val ContainerElevation = ElevationTokens.Level0
-    val ContainerHeight = 112.0.dp
-    val ContainerShape = ShapeKeyTokens.CornerNone
-    val ContainerSurfaceTintLayerColor = ColorSchemeKeyTokens.SurfaceTint
-    val HeadlineColor = ColorSchemeKeyTokens.OnSurface
-    val HeadlineFont = TypographyKeyTokens.HeadlineSmall
-    val LeadingIconColor = ColorSchemeKeyTokens.OnSurface
-    val LeadingIconSize = 24.0.dp
-    val TrailingIconColor = ColorSchemeKeyTokens.OnSurfaceVariant
-    val TrailingIconSize = 24.0.dp
-}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TopAppBarSmallCenteredTokens.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TopAppBarSmallCenteredTokens.kt
deleted file mode 100644
index 45e29bb..0000000
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/TopAppBarSmallCenteredTokens.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-// VERSION: v0_210
-// GENERATED CODE - DO NOT MODIFY BY HAND
-
-package androidx.compose.material3.tokens
-
-import androidx.compose.ui.unit.dp
-
-internal object TopAppBarSmallCenteredTokens {
-    val AvatarShape = ShapeKeyTokens.CornerFull
-    val AvatarSize = 30.0.dp
-    val ContainerColor = ColorSchemeKeyTokens.Surface
-    val ContainerElevation = ElevationTokens.Level0
-    val ContainerHeight = 64.0.dp
-    val ContainerShape = ShapeKeyTokens.CornerNone
-    val ContainerSurfaceTintLayerColor = ColorSchemeKeyTokens.SurfaceTint
-    val HeadlineColor = ColorSchemeKeyTokens.OnSurface
-    val HeadlineFont = TypographyKeyTokens.TitleLarge
-    val LeadingIconColor = ColorSchemeKeyTokens.OnSurface
-    val LeadingIconSize = 24.0.dp
-    val OnScrollContainerColor = ColorSchemeKeyTokens.SurfaceContainer
-    val OnScrollContainerElevation = ElevationTokens.Level2
-    val TrailingIconColor = ColorSchemeKeyTokens.OnSurfaceVariant
-    val TrailingIconSize = 24.0.dp
-}
diff --git a/compose/runtime/runtime-saveable/src/commonMain/kotlin/androidx/compose/runtime/saveable/RememberSaveable.kt b/compose/runtime/runtime-saveable/src/commonMain/kotlin/androidx/compose/runtime/saveable/RememberSaveable.kt
index 7d0f0804..6115307 100644
--- a/compose/runtime/runtime-saveable/src/commonMain/kotlin/androidx/compose/runtime/saveable/RememberSaveable.kt
+++ b/compose/runtime/runtime-saveable/src/commonMain/kotlin/androidx/compose/runtime/saveable/RememberSaveable.kt
@@ -54,7 +54,8 @@
  *
  * @sample androidx.compose.runtime.saveable.samples.RememberSaveableWithMutableStateAndCustomSaver
  * @param inputs A set of inputs such that, when any of them have changed, will cause the state to
- *   reset and [init] to be rerun
+ *   reset and [init] to be rerun. Note that state restoration DOES NOT validate against inputs
+ *   provided before value was saved.
  * @param saver The [Saver] object which defines how the state is saved and restored.
  * @param key An optional key to be used as a key for the saved value. If not provided we use the
  *   automatically generated by the Compose runtime which is unique for the every exact code
@@ -105,7 +106,8 @@
  *
  * @sample androidx.compose.runtime.saveable.samples.RememberSaveableWithMutableStateAndCustomSaver
  * @param inputs A set of inputs such that, when any of them have changed, will cause the state to
- *   reset and [init] to be rerun
+ *   reset and [init] to be rerun. Note that state restoration DOES NOT validate against inputs
+ *   provided before value was saved.
  * @param stateSaver The [Saver] object which defines how the value inside the MutableState is saved
  *   and restored.
  * @param key An optional key to be used as a key for the saved value. If not provided we use the
diff --git a/compose/runtime/runtime/api/current.txt b/compose/runtime/runtime/api/current.txt
index e09c09f..f189ba5 100644
--- a/compose/runtime/runtime/api/current.txt
+++ b/compose/runtime/runtime/api/current.txt
@@ -356,7 +356,7 @@
 
   public final class HotReloaderKt {
     method @org.jetbrains.annotations.TestOnly public static void clearCompositionErrors();
-    method @org.jetbrains.annotations.TestOnly public static java.util.List<kotlin.Pair<java.lang.Exception,java.lang.Boolean>> currentCompositionErrors();
+    method @Deprecated @org.jetbrains.annotations.TestOnly public static java.util.List<kotlin.Pair<java.lang.Exception,java.lang.Boolean>> currentCompositionErrors();
     method @org.jetbrains.annotations.TestOnly public static void invalidateGroupsWithKey(int key);
     method @org.jetbrains.annotations.TestOnly public static void simulateHotReload(Object context);
   }
diff --git a/compose/runtime/runtime/api/restricted_current.txt b/compose/runtime/runtime/api/restricted_current.txt
index 4ea7878..711489b 100644
--- a/compose/runtime/runtime/api/restricted_current.txt
+++ b/compose/runtime/runtime/api/restricted_current.txt
@@ -397,7 +397,7 @@
 
   public final class HotReloaderKt {
     method @org.jetbrains.annotations.TestOnly public static void clearCompositionErrors();
-    method @org.jetbrains.annotations.TestOnly public static java.util.List<kotlin.Pair<java.lang.Exception,java.lang.Boolean>> currentCompositionErrors();
+    method @Deprecated @org.jetbrains.annotations.TestOnly public static java.util.List<kotlin.Pair<java.lang.Exception,java.lang.Boolean>> currentCompositionErrors();
     method @org.jetbrains.annotations.TestOnly public static void invalidateGroupsWithKey(int key);
     method @org.jetbrains.annotations.TestOnly public static void simulateHotReload(Object context);
   }
diff --git a/compose/runtime/runtime/bcv/native/1.7.0.txt b/compose/runtime/runtime/bcv/native/1.7.0.txt
index 4506d78..9ad5f48 100644
--- a/compose/runtime/runtime/bcv/native/1.7.0.txt
+++ b/compose/runtime/runtime/bcv/native/1.7.0.txt
@@ -74,9 +74,6 @@
         abstract fun <get-value>(): #A // androidx.compose.runtime/State.value.<get-value>|<get-value>(){}[0]
 }
 abstract interface androidx.compose.runtime.internal/ComposableLambda : kotlin/Function10<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Any?>, kotlin/Function11<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Any?>, kotlin/Function13<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Int, kotlin/Any?>, kotlin/Function14<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Int, kotlin/Any?>, kotlin/Function15<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Int, kotlin/Any?>, kotlin/Function16<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Int, kotlin/Any?>, kotlin/Function17<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Int, kotlin/Any?>, kotlin/Function18<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Int, kotlin/Any?>, kotlin/Function19<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Int, kotlin/Any?>, kotlin/Function20<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Int, kotlin/Any?>, kotlin/Function21<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Int, kotlin/Any?>, kotlin/Function2<androidx.compose.runtime/Composer, kotlin/Int, kotlin/Any?>, kotlin/Function3<kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Any?>, kotlin/Function4<kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Any?>, kotlin/Function5<kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Any?>, kotlin/Function6<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Any?>, kotlin/Function7<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Any?>, kotlin/Function8<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Any?>, kotlin/Function9<kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Any?, androidx.compose.runtime/Composer, kotlin/Int, kotlin/Any?> // androidx.compose.runtime.internal/ComposableLambda|null[0]
-abstract interface androidx.compose.runtime.snapshots/SnapshotContextElement : kotlin.coroutines/CoroutineContext.Element { // androidx.compose.runtime.snapshots/SnapshotContextElement|null[0]
-    final object Key : kotlin.coroutines/CoroutineContext.Key<androidx.compose.runtime.snapshots/SnapshotContextElement> // androidx.compose.runtime.snapshots/SnapshotContextElement.Key|null[0]
-}
 abstract interface androidx.compose.runtime.snapshots/StateObject { // androidx.compose.runtime.snapshots/StateObject|null[0]
     abstract fun prependStateRecord(androidx.compose.runtime.snapshots/StateRecord) // androidx.compose.runtime.snapshots/StateObject.prependStateRecord|prependStateRecord(androidx.compose.runtime.snapshots.StateRecord){}[0]
     abstract val firstStateRecord // androidx.compose.runtime.snapshots/StateObject.firstStateRecord|<get-firstStateRecord>(){}[0]
@@ -106,18 +103,6 @@
     open val slotsSize // androidx.compose.runtime.tooling/CompositionGroup.slotsSize|{}slotsSize[0]
         open fun <get-slotsSize>(): kotlin/Int // androidx.compose.runtime.tooling/CompositionGroup.slotsSize.<get-slotsSize>|<get-slotsSize>(){}[0]
 }
-abstract interface androidx.compose.runtime.tooling/CompositionObserver { // androidx.compose.runtime.tooling/CompositionObserver|null[0]
-    abstract fun onBeginComposition(androidx.compose.runtime/Composition, kotlin.collections/Map<androidx.compose.runtime/RecomposeScope, kotlin.collections/Set<kotlin/Any>?>) // androidx.compose.runtime.tooling/CompositionObserver.onBeginComposition|onBeginComposition(androidx.compose.runtime.Composition;kotlin.collections.Map<androidx.compose.runtime.RecomposeScope,kotlin.collections.Set<kotlin.Any>?>){}[0]
-    abstract fun onEndComposition(androidx.compose.runtime/Composition) // androidx.compose.runtime.tooling/CompositionObserver.onEndComposition|onEndComposition(androidx.compose.runtime.Composition){}[0]
-}
-abstract interface androidx.compose.runtime.tooling/CompositionObserverHandle { // androidx.compose.runtime.tooling/CompositionObserverHandle|null[0]
-    abstract fun dispose() // androidx.compose.runtime.tooling/CompositionObserverHandle.dispose|dispose(){}[0]
-}
-abstract interface androidx.compose.runtime.tooling/RecomposeScopeObserver { // androidx.compose.runtime.tooling/RecomposeScopeObserver|null[0]
-    abstract fun onBeginScopeComposition(androidx.compose.runtime/RecomposeScope) // androidx.compose.runtime.tooling/RecomposeScopeObserver.onBeginScopeComposition|onBeginScopeComposition(androidx.compose.runtime.RecomposeScope){}[0]
-    abstract fun onEndScopeComposition(androidx.compose.runtime/RecomposeScope) // androidx.compose.runtime.tooling/RecomposeScopeObserver.onEndScopeComposition|onEndScopeComposition(androidx.compose.runtime.RecomposeScope){}[0]
-    abstract fun onScopeDisposed(androidx.compose.runtime/RecomposeScope) // androidx.compose.runtime.tooling/RecomposeScopeObserver.onScopeDisposed|onScopeDisposed(androidx.compose.runtime.RecomposeScope){}[0]
-}
 abstract interface androidx.compose.runtime/ComposeNodeLifecycleCallback { // androidx.compose.runtime/ComposeNodeLifecycleCallback|null[0]
     abstract fun onDeactivate() // androidx.compose.runtime/ComposeNodeLifecycleCallback.onDeactivate|onDeactivate(){}[0]
     abstract fun onRelease() // androidx.compose.runtime/ComposeNodeLifecycleCallback.onRelease|onRelease(){}[0]
@@ -138,11 +123,6 @@
 abstract interface androidx.compose.runtime/CompositionServices { // androidx.compose.runtime/CompositionServices|null[0]
     abstract fun <#A1: kotlin/Any?> getCompositionService(androidx.compose.runtime/CompositionServiceKey<#A1>): #A1? // androidx.compose.runtime/CompositionServices.getCompositionService|getCompositionService(androidx.compose.runtime.CompositionServiceKey<0:0>){0§<kotlin.Any?>}[0]
 }
-abstract interface androidx.compose.runtime/CompositionTracer { // androidx.compose.runtime/CompositionTracer|null[0]
-    abstract fun isTraceInProgress(): kotlin/Boolean // androidx.compose.runtime/CompositionTracer.isTraceInProgress|isTraceInProgress(){}[0]
-    abstract fun traceEventEnd() // androidx.compose.runtime/CompositionTracer.traceEventEnd|traceEventEnd(){}[0]
-    abstract fun traceEventStart(kotlin/Int, kotlin/Int, kotlin/Int, kotlin/String) // androidx.compose.runtime/CompositionTracer.traceEventStart|traceEventStart(kotlin.Int;kotlin.Int;kotlin.Int;kotlin.String){}[0]
-}
 abstract interface androidx.compose.runtime/DisposableEffectResult { // androidx.compose.runtime/DisposableEffectResult|null[0]
     abstract fun dispose() // androidx.compose.runtime/DisposableEffectResult.dispose|dispose(){}[0]
 }
@@ -355,11 +335,6 @@
     final var firstStateRecord // androidx.compose.runtime.snapshots/SnapshotStateList.firstStateRecord|{}firstStateRecord[0]
         final fun <get-firstStateRecord>(): androidx.compose.runtime.snapshots/StateRecord // androidx.compose.runtime.snapshots/SnapshotStateList.firstStateRecord.<get-firstStateRecord>|<get-firstStateRecord>(){}[0]
 }
-final class <#A: kotlin/Any?> androidx.compose.runtime/MovableContent { // androidx.compose.runtime/MovableContent|null[0]
-    constructor <init>(kotlin/Function1<#A, kotlin/Unit>) // androidx.compose.runtime/MovableContent.<init>|<init>(kotlin.Function1<1:0,kotlin.Unit>){}[0]
-    final val content // androidx.compose.runtime/MovableContent.content|{}content[0]
-        final fun <get-content>(): kotlin/Function1<#A, kotlin/Unit> // androidx.compose.runtime/MovableContent.content.<get-content>|<get-content>(){}[0]
-}
 final class <#A: kotlin/Any?> androidx.compose.runtime/ProvidedValue { // androidx.compose.runtime/ProvidedValue|null[0]
     final val compositionLocal // androidx.compose.runtime/ProvidedValue.compositionLocal|{}compositionLocal[0]
         final fun <get-compositionLocal>(): androidx.compose.runtime/CompositionLocal<#A> // androidx.compose.runtime/ProvidedValue.compositionLocal.<get-compositionLocal>|<get-compositionLocal>(){}[0]
@@ -405,8 +380,6 @@
     constructor <init>() // androidx.compose.runtime/DisposableEffectScope.<init>|<init>(){}[0]
     final inline fun onDispose(crossinline kotlin/Function0<kotlin/Unit>): androidx.compose.runtime/DisposableEffectResult // androidx.compose.runtime/DisposableEffectScope.onDispose|onDispose(kotlin.Function0<kotlin.Unit>){}[0]
 }
-final class androidx.compose.runtime/MovableContentState // androidx.compose.runtime/MovableContentState|null[0]
-final class androidx.compose.runtime/MovableContentStateReference // androidx.compose.runtime/MovableContentStateReference|null[0]
 final class androidx.compose.runtime/PausableMonotonicFrameClock : androidx.compose.runtime/MonotonicFrameClock { // androidx.compose.runtime/PausableMonotonicFrameClock|null[0]
     constructor <init>(androidx.compose.runtime/MonotonicFrameClock) // androidx.compose.runtime/PausableMonotonicFrameClock.<init>|<init>(androidx.compose.runtime.MonotonicFrameClock){}[0]
     final fun pause() // androidx.compose.runtime/PausableMonotonicFrameClock.pause|pause(){}[0]
@@ -439,7 +412,6 @@
     final suspend fun awaitIdle() // androidx.compose.runtime/Recomposer.awaitIdle|awaitIdle(){}[0]
     final suspend fun join() // androidx.compose.runtime/Recomposer.join|join(){}[0]
     final suspend fun runRecomposeAndApplyChanges() // androidx.compose.runtime/Recomposer.runRecomposeAndApplyChanges|runRecomposeAndApplyChanges(){}[0]
-    final suspend fun runRecomposeConcurrentlyAndApplyChanges(kotlin.coroutines/CoroutineContext) // androidx.compose.runtime/Recomposer.runRecomposeConcurrentlyAndApplyChanges|runRecomposeConcurrentlyAndApplyChanges(kotlin.coroutines.CoroutineContext){}[0]
     final val currentState // androidx.compose.runtime/Recomposer.currentState|<get-currentState>(){}[0]
         final fun <get-currentState>(): kotlinx.coroutines.flow/StateFlow<androidx.compose.runtime/Recomposer.State> // androidx.compose.runtime/Recomposer.currentState.<get-currentState>|<get-currentState>(){}[0]
     final val effectCoroutineContext // androidx.compose.runtime/Recomposer.effectCoroutineContext|{}effectCoroutineContext[0]
@@ -465,9 +437,6 @@
     final fun <get-referenceKey>(): kotlin/Int // androidx.compose.runtime/referenceKey.<get-referenceKey>|<get-referenceKey>(){}[0]
 final const val androidx.compose.runtime/reuseKey // androidx.compose.runtime/reuseKey|<get-reuseKey>(){}[0]
     final fun <get-reuseKey>(): kotlin/Int // androidx.compose.runtime/reuseKey.<get-reuseKey>|<get-reuseKey>(){}[0]
-final fun (androidx.compose.runtime.snapshots/Snapshot).androidx.compose.runtime.snapshots/asContextElement(): androidx.compose.runtime.snapshots/SnapshotContextElement // androidx.compose.runtime.snapshots/asContextElement|[email protected](){}[0]
-final fun (androidx.compose.runtime/Composition).androidx.compose.runtime.tooling/observe(androidx.compose.runtime.tooling/CompositionObserver): androidx.compose.runtime.tooling/CompositionObserverHandle? // androidx.compose.runtime.tooling/observe|[email protected](androidx.compose.runtime.tooling.CompositionObserver){}[0]
-final fun (androidx.compose.runtime/RecomposeScope).androidx.compose.runtime.tooling/observe(androidx.compose.runtime.tooling/RecomposeScopeObserver): androidx.compose.runtime.tooling/CompositionObserverHandle // androidx.compose.runtime.tooling/observe|[email protected](androidx.compose.runtime.tooling.RecomposeScopeObserver){}[0]
 final fun (androidx.compose.runtime/State<kotlin/Double>).androidx.compose.runtime/asDoubleState(): androidx.compose.runtime/DoubleState // androidx.compose.runtime/asDoubleState|[email protected]<kotlin.Double>(){}[0]
 final fun (androidx.compose.runtime/State<kotlin/Float>).androidx.compose.runtime/asFloatState(): androidx.compose.runtime/FloatState // androidx.compose.runtime/asFloatState|[email protected]<kotlin.Float>(){}[0]
 final fun (androidx.compose.runtime/State<kotlin/Int>).androidx.compose.runtime/asIntState(): androidx.compose.runtime/IntState // androidx.compose.runtime/asIntState|[email protected]<kotlin.Int>(){}[0]
@@ -489,7 +458,6 @@
 final fun <#A: kotlin/Any?, #B: kotlin/Any?> androidx.compose.runtime/mutableStateMapOf(kotlin/Array<out kotlin/Pair<#A, #B>>...): androidx.compose.runtime.snapshots/SnapshotStateMap<#A, #B> // androidx.compose.runtime/mutableStateMapOf|mutableStateMapOf(kotlin.Array<out|kotlin.Pair<0:0,0:1>>...){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
 final fun <#A: kotlin/Any?> (kotlin.collections/Collection<#A>).androidx.compose.runtime/toMutableStateList(): androidx.compose.runtime.snapshots/SnapshotStateList<#A> // androidx.compose.runtime/toMutableStateList|[email protected]<0:0>(){0§<kotlin.Any?>}[0]
 final fun <#A: kotlin/Any?> (kotlinx.coroutines.flow/StateFlow<#A>).androidx.compose.runtime/collectAsState(kotlin.coroutines/CoroutineContext =...): androidx.compose.runtime/State<#A> // androidx.compose.runtime/collectAsState|[email protected]<0:0>(kotlin.coroutines.CoroutineContext){0§<kotlin.Any?>}[0]
-final fun <#A: kotlin/Any?> androidx.compose.runtime.internal/liveLiteral(kotlin/String, #A): androidx.compose.runtime/State<#A> // androidx.compose.runtime.internal/liveLiteral|liveLiteral(kotlin.String;0:0){0§<kotlin.Any?>}[0]
 final fun <#A: kotlin/Any?> androidx.compose.runtime/compositionLocalOf(androidx.compose.runtime/SnapshotMutationPolicy<#A> =..., kotlin/Function0<#A>): androidx.compose.runtime/ProvidableCompositionLocal<#A> // androidx.compose.runtime/compositionLocalOf|compositionLocalOf(androidx.compose.runtime.SnapshotMutationPolicy<0:0>;kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]
 final fun <#A: kotlin/Any?> androidx.compose.runtime/compositionLocalWithComputedDefaultOf(kotlin/Function1<androidx.compose.runtime/CompositionLocalAccessorScope, #A>): androidx.compose.runtime/ProvidableCompositionLocal<#A> // androidx.compose.runtime/compositionLocalWithComputedDefaultOf|compositionLocalWithComputedDefaultOf(kotlin.Function1<androidx.compose.runtime.CompositionLocalAccessorScope,0:0>){0§<kotlin.Any?>}[0]
 final fun <#A: kotlin/Any?> androidx.compose.runtime/derivedStateOf(androidx.compose.runtime/SnapshotMutationPolicy<#A>, kotlin/Function0<#A>): androidx.compose.runtime/State<#A> // androidx.compose.runtime/derivedStateOf|derivedStateOf(androidx.compose.runtime.SnapshotMutationPolicy<0:0>;kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]
@@ -512,18 +480,14 @@
 final fun <#A: kotlin/Any?> androidx.compose.runtime/structuralEqualityPolicy(): androidx.compose.runtime/SnapshotMutationPolicy<#A> // androidx.compose.runtime/structuralEqualityPolicy|structuralEqualityPolicy(){0§<kotlin.Any?>}[0]
 final fun androidx.compose.runtime.internal/composableLambda(androidx.compose.runtime/Composer, kotlin/Int, kotlin/Boolean, kotlin/Any): androidx.compose.runtime.internal/ComposableLambda // androidx.compose.runtime.internal/composableLambda|composableLambda(androidx.compose.runtime.Composer;kotlin.Int;kotlin.Boolean;kotlin.Any){}[0]
 final fun androidx.compose.runtime.internal/composableLambdaInstance(kotlin/Int, kotlin/Boolean, kotlin/Any): androidx.compose.runtime.internal/ComposableLambda // androidx.compose.runtime.internal/composableLambdaInstance|composableLambdaInstance(kotlin.Int;kotlin.Boolean;kotlin.Any){}[0]
-final fun androidx.compose.runtime.internal/enableLiveLiterals() // androidx.compose.runtime.internal/enableLiveLiterals|enableLiveLiterals(){}[0]
 final fun androidx.compose.runtime.internal/illegalDecoyCallException(kotlin/String): kotlin/Nothing // androidx.compose.runtime.internal/illegalDecoyCallException|illegalDecoyCallException(kotlin.String){}[0]
 final fun androidx.compose.runtime.internal/rememberComposableLambda(kotlin/Int, kotlin/Boolean, kotlin/Any): androidx.compose.runtime.internal/ComposableLambda // androidx.compose.runtime.internal/rememberComposableLambda|rememberComposableLambda(kotlin.Int;kotlin.Boolean;kotlin.Any){}[0]
-final fun androidx.compose.runtime.internal/updateLiveLiteralValue(kotlin/String, kotlin/Any?) // androidx.compose.runtime.internal/updateLiveLiteralValue|updateLiveLiteralValue(kotlin.String;kotlin.Any?){}[0]
 final fun androidx.compose.runtime.snapshots/notifyWrite(androidx.compose.runtime.snapshots/Snapshot, androidx.compose.runtime.snapshots/StateObject) // androidx.compose.runtime.snapshots/notifyWrite|notifyWrite(androidx.compose.runtime.snapshots.Snapshot;androidx.compose.runtime.snapshots.StateObject){}[0]
 final fun androidx.compose.runtime/Composition(androidx.compose.runtime/Applier<*>, androidx.compose.runtime/CompositionContext): androidx.compose.runtime/Composition // androidx.compose.runtime/Composition|Composition(androidx.compose.runtime.Applier<*>;androidx.compose.runtime.CompositionContext){}[0]
-final fun androidx.compose.runtime/Composition(androidx.compose.runtime/Applier<*>, androidx.compose.runtime/CompositionContext, kotlin.coroutines/CoroutineContext): androidx.compose.runtime/Composition // androidx.compose.runtime/Composition|Composition(androidx.compose.runtime.Applier<*>;androidx.compose.runtime.CompositionContext;kotlin.coroutines.CoroutineContext){}[0]
 final fun androidx.compose.runtime/CompositionLocalProvider(androidx.compose.runtime/CompositionLocalContext, kotlin/Function0<kotlin/Unit>) // androidx.compose.runtime/CompositionLocalProvider|CompositionLocalProvider(androidx.compose.runtime.CompositionLocalContext;kotlin.Function0<kotlin.Unit>){}[0]
 final fun androidx.compose.runtime/CompositionLocalProvider(androidx.compose.runtime/ProvidedValue<*>, kotlin/Function0<kotlin/Unit>) // androidx.compose.runtime/CompositionLocalProvider|CompositionLocalProvider(androidx.compose.runtime.ProvidedValue<*>;kotlin.Function0<kotlin.Unit>){}[0]
 final fun androidx.compose.runtime/CompositionLocalProvider(kotlin/Array<out androidx.compose.runtime/ProvidedValue<*>>..., kotlin/Function0<kotlin/Unit>) // androidx.compose.runtime/CompositionLocalProvider|CompositionLocalProvider(kotlin.Array<out|androidx.compose.runtime.ProvidedValue<*>>...;kotlin.Function0<kotlin.Unit>){}[0]
 final fun androidx.compose.runtime/ControlledComposition(androidx.compose.runtime/Applier<*>, androidx.compose.runtime/CompositionContext): androidx.compose.runtime/ControlledComposition // androidx.compose.runtime/ControlledComposition|ControlledComposition(androidx.compose.runtime.Applier<*>;androidx.compose.runtime.CompositionContext){}[0]
-final fun androidx.compose.runtime/ControlledComposition(androidx.compose.runtime/Applier<*>, androidx.compose.runtime/CompositionContext, kotlin.coroutines/CoroutineContext): androidx.compose.runtime/ControlledComposition // androidx.compose.runtime/ControlledComposition|ControlledComposition(androidx.compose.runtime.Applier<*>;androidx.compose.runtime.CompositionContext;kotlin.coroutines.CoroutineContext){}[0]
 final fun androidx.compose.runtime/DisposableEffect(kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Function1<androidx.compose.runtime/DisposableEffectScope, androidx.compose.runtime/DisposableEffectResult>) // androidx.compose.runtime/DisposableEffect|DisposableEffect(kotlin.Any?;kotlin.Any?;kotlin.Any?;kotlin.Function1<androidx.compose.runtime.DisposableEffectScope,androidx.compose.runtime.DisposableEffectResult>){}[0]
 final fun androidx.compose.runtime/DisposableEffect(kotlin/Any?, kotlin/Any?, kotlin/Function1<androidx.compose.runtime/DisposableEffectScope, androidx.compose.runtime/DisposableEffectResult>) // androidx.compose.runtime/DisposableEffect|DisposableEffect(kotlin.Any?;kotlin.Any?;kotlin.Function1<androidx.compose.runtime.DisposableEffectScope,androidx.compose.runtime.DisposableEffectResult>){}[0]
 final fun androidx.compose.runtime/DisposableEffect(kotlin/Any?, kotlin/Function1<androidx.compose.runtime/DisposableEffectScope, androidx.compose.runtime/DisposableEffectResult>) // androidx.compose.runtime/DisposableEffect|DisposableEffect(kotlin.Any?;kotlin.Function1<androidx.compose.runtime.DisposableEffectScope,androidx.compose.runtime.DisposableEffectResult>){}[0]
@@ -615,16 +579,12 @@
     final fun <get-currentRecomposeScope>(): androidx.compose.runtime/RecomposeScope // androidx.compose.runtime/currentRecomposeScope.<get-currentRecomposeScope>|<get-currentRecomposeScope>(){}[0]
 final val androidx.compose.runtime/invocation // androidx.compose.runtime/invocation|<get-invocation>(){}[0]
     final fun <get-invocation>(): kotlin/Any // androidx.compose.runtime/invocation.<get-invocation>|<get-invocation>(){}[0]
-final val androidx.compose.runtime/monotonicFrameClock // androidx.compose.runtime/monotonicFrameClock|<get-monotonicFrameClock>@kotlin.coroutines.CoroutineContext(){}[0]
-    final fun (kotlin.coroutines/CoroutineContext).<get-monotonicFrameClock>(): androidx.compose.runtime/MonotonicFrameClock // androidx.compose.runtime/monotonicFrameClock.<get-monotonicFrameClock>|<get-monotonicFrameClock>@kotlin.coroutines.CoroutineContext(){}[0]
 final val androidx.compose.runtime/provider // androidx.compose.runtime/provider|<get-provider>(){}[0]
     final fun <get-provider>(): kotlin/Any // androidx.compose.runtime/provider.<get-provider>|<get-provider>(){}[0]
 final val androidx.compose.runtime/providerMaps // androidx.compose.runtime/providerMaps|<get-providerMaps>(){}[0]
     final fun <get-providerMaps>(): kotlin/Any // androidx.compose.runtime/providerMaps.<get-providerMaps>|<get-providerMaps>(){}[0]
 final val androidx.compose.runtime/providerValues // androidx.compose.runtime/providerValues|{}providerValues[0]
     final fun <get-providerValues>(): kotlin/Any // androidx.compose.runtime/providerValues.<get-providerValues>|<get-providerValues>(){}[0]
-final val androidx.compose.runtime/recomposeCoroutineContext // androidx.compose.runtime/recomposeCoroutineContext|@androidx.compose.runtime.ControlledComposition{}recomposeCoroutineContext[0]
-    final fun (androidx.compose.runtime/ControlledComposition).<get-recomposeCoroutineContext>(): kotlin.coroutines/CoroutineContext // androidx.compose.runtime/recomposeCoroutineContext.<get-recomposeCoroutineContext>|<get-recomposeCoroutineContext>@androidx.compose.runtime.ControlledComposition(){}[0]
 final val androidx.compose.runtime/reference // androidx.compose.runtime/reference|<get-reference>(){}[0]
     final fun <get-reference>(): kotlin/Any // androidx.compose.runtime/reference.<get-reference>|<get-reference>(){}[0]
 final value class <#A: kotlin/Any?> androidx.compose.runtime/SkippableUpdater { // androidx.compose.runtime/SkippableUpdater|null[0]
@@ -650,22 +610,6 @@
     final val composer // androidx.compose.runtime/Updater.composer|{}composer[0]
         final fun <get-composer>(): androidx.compose.runtime/Composer // androidx.compose.runtime/Updater.composer.<get-composer>|<get-composer>(){}[0]
 }
-final var androidx.compose.runtime.internal/isLiveLiteralsEnabled // androidx.compose.runtime.internal/isLiveLiteralsEnabled|{}isLiveLiteralsEnabled[0]
-    final fun <get-isLiveLiteralsEnabled>(): kotlin/Boolean // androidx.compose.runtime.internal/isLiveLiteralsEnabled.<get-isLiveLiteralsEnabled>|<get-isLiveLiteralsEnabled>(){}[0]
-open annotation class androidx.compose.runtime.internal/Decoy : kotlin/Annotation { // androidx.compose.runtime.internal/Decoy|null[0]
-    constructor <init>(kotlin/String, kotlin/Array<out kotlin/String>...) // androidx.compose.runtime.internal/Decoy.<init>|<init>(kotlin.String;kotlin.Array<out|kotlin.String>...){}[0]
-    final val signature // androidx.compose.runtime.internal/Decoy.signature|{}signature[0]
-        final fun <get-signature>(): kotlin/Array<out kotlin/String> // androidx.compose.runtime.internal/Decoy.signature.<get-signature>|<get-signature>(){}[0]
-    final val targetName // androidx.compose.runtime.internal/Decoy.targetName|{}targetName[0]
-        final fun <get-targetName>(): kotlin/String // androidx.compose.runtime.internal/Decoy.targetName.<get-targetName>|<get-targetName>(){}[0]
-}
-open annotation class androidx.compose.runtime.internal/DecoyImplementation : kotlin/Annotation { // androidx.compose.runtime.internal/DecoyImplementation|null[0]
-    constructor <init>(kotlin/String, kotlin/Long) // androidx.compose.runtime.internal/DecoyImplementation.<init>|<init>(kotlin.String;kotlin.Long){}[0]
-    final val id // androidx.compose.runtime.internal/DecoyImplementation.id|{}id[0]
-        final fun <get-id>(): kotlin/Long // androidx.compose.runtime.internal/DecoyImplementation.id.<get-id>|<get-id>(){}[0]
-    final val name // androidx.compose.runtime.internal/DecoyImplementation.name|{}name[0]
-        final fun <get-name>(): kotlin/String // androidx.compose.runtime.internal/DecoyImplementation.name.<get-name>|<get-name>(){}[0]
-}
 open annotation class androidx.compose.runtime.internal/FunctionKeyMeta : kotlin/Annotation { // androidx.compose.runtime.internal/FunctionKeyMeta|null[0]
     constructor <init>(kotlin/Int, kotlin/Int, kotlin/Int) // androidx.compose.runtime.internal/FunctionKeyMeta.<init>|<init>(kotlin.Int;kotlin.Int;kotlin.Int){}[0]
     final val endOffset // androidx.compose.runtime.internal/FunctionKeyMeta.endOffset|{}endOffset[0]
@@ -708,11 +652,6 @@
 open annotation class androidx.compose.runtime/Composable : kotlin/Annotation { // androidx.compose.runtime/Composable|null[0]
     constructor <init>() // androidx.compose.runtime/Composable.<init>|<init>(){}[0]
 }
-open annotation class androidx.compose.runtime/ComposableInferredTarget : kotlin/Annotation { // androidx.compose.runtime/ComposableInferredTarget|null[0]
-    constructor <init>(kotlin/String) // androidx.compose.runtime/ComposableInferredTarget.<init>|<init>(kotlin.String){}[0]
-    final val scheme // androidx.compose.runtime/ComposableInferredTarget.scheme|{}scheme[0]
-        final fun <get-scheme>(): kotlin/String // androidx.compose.runtime/ComposableInferredTarget.scheme.<get-scheme>|<get-scheme>(){}[0]
-}
 open annotation class androidx.compose.runtime/ComposableOpenTarget : kotlin/Annotation { // androidx.compose.runtime/ComposableOpenTarget|null[0]
     constructor <init>(kotlin/Int) // androidx.compose.runtime/ComposableOpenTarget.<init>|<init>(kotlin.Int){}[0]
     final val index // androidx.compose.runtime/ComposableOpenTarget.index|{}index[0]
@@ -802,8 +741,6 @@
     abstract val root // androidx.compose.runtime.snapshots/Snapshot.root|{}root[0]
         abstract fun <get-root>(): androidx.compose.runtime.snapshots/Snapshot // androidx.compose.runtime.snapshots/Snapshot.root.<get-root>|<get-root>(){}[0]
     constructor <init>(kotlin/Int, androidx.compose.runtime.snapshots/SnapshotIdSet) // androidx.compose.runtime.snapshots/Snapshot.<init>|<init>(kotlin.Int;androidx.compose.runtime.snapshots.SnapshotIdSet){}[0]
-    final fun unsafeEnter(): androidx.compose.runtime.snapshots/Snapshot? // androidx.compose.runtime.snapshots/Snapshot.unsafeEnter|unsafeEnter(){}[0]
-    final fun unsafeLeave(androidx.compose.runtime.snapshots/Snapshot?) // androidx.compose.runtime.snapshots/Snapshot.unsafeLeave|unsafeLeave(androidx.compose.runtime.snapshots.Snapshot?){}[0]
     final inline fun <#A1: kotlin/Any?> enter(kotlin/Function0<#A1>): #A1 // androidx.compose.runtime.snapshots/Snapshot.enter|enter(kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]
     final object Companion { // androidx.compose.runtime.snapshots/Snapshot.Companion|null[0]
         final const val PreexistingSnapshotId // androidx.compose.runtime.snapshots/Snapshot.Companion.PreexistingSnapshotId|{}PreexistingSnapshotId[0]
@@ -812,7 +749,6 @@
         final fun createNonObservableSnapshot(): androidx.compose.runtime.snapshots/Snapshot // androidx.compose.runtime.snapshots/Snapshot.Companion.createNonObservableSnapshot|createNonObservableSnapshot(){}[0]
         final fun makeCurrentNonObservable(androidx.compose.runtime.snapshots/Snapshot?): androidx.compose.runtime.snapshots/Snapshot // androidx.compose.runtime.snapshots/Snapshot.Companion.makeCurrentNonObservable|makeCurrentNonObservable(androidx.compose.runtime.snapshots.Snapshot?){}[0]
         final fun notifyObjectsInitialized() // androidx.compose.runtime.snapshots/Snapshot.Companion.notifyObjectsInitialized|notifyObjectsInitialized(){}[0]
-        final fun openSnapshotCount(): kotlin/Int // androidx.compose.runtime.snapshots/Snapshot.Companion.openSnapshotCount|openSnapshotCount(){}[0]
         final fun registerApplyObserver(kotlin/Function2<kotlin.collections/Set<kotlin/Any>, androidx.compose.runtime.snapshots/Snapshot, kotlin/Unit>): androidx.compose.runtime.snapshots/ObserverHandle // androidx.compose.runtime.snapshots/Snapshot.Companion.registerApplyObserver|registerApplyObserver(kotlin.Function2<kotlin.collections.Set<kotlin.Any>,androidx.compose.runtime.snapshots.Snapshot,kotlin.Unit>){}[0]
         final fun registerGlobalWriteObserver(kotlin/Function1<kotlin/Any, kotlin/Unit>): androidx.compose.runtime.snapshots/ObserverHandle // androidx.compose.runtime.snapshots/Snapshot.Companion.registerGlobalWriteObserver|registerGlobalWriteObserver(kotlin.Function1<kotlin.Any,kotlin.Unit>){}[0]
         final fun removeCurrent(): androidx.compose.runtime.snapshots/Snapshot? // androidx.compose.runtime.snapshots/Snapshot.Companion.removeCurrent|removeCurrent(){}[0]
@@ -860,9 +796,7 @@
 }
 sealed interface androidx.compose.runtime/Composer { // androidx.compose.runtime/Composer|null[0]
     abstract fun <#A1: kotlin/Any?, #B1: kotlin/Any?> apply(#A1, kotlin/Function2<#B1, #A1, kotlin/Unit>) // androidx.compose.runtime/Composer.apply|apply(0:0;kotlin.Function2<0:1,0:0,kotlin.Unit>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
-    abstract fun <#A1: kotlin/Any?> consume(androidx.compose.runtime/CompositionLocal<#A1>): #A1 // androidx.compose.runtime/Composer.consume|consume(androidx.compose.runtime.CompositionLocal<0:0>){0§<kotlin.Any?>}[0]
     abstract fun <#A1: kotlin/Any?> createNode(kotlin/Function0<#A1>) // androidx.compose.runtime/Composer.createNode|createNode(kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]
-    abstract fun buildContext(): androidx.compose.runtime/CompositionContext // androidx.compose.runtime/Composer.buildContext|buildContext(){}[0]
     abstract fun changed(kotlin/Any?): kotlin/Boolean // androidx.compose.runtime/Composer.changed|changed(kotlin.Any?){}[0]
     abstract fun collectParameterInformation() // androidx.compose.runtime/Composer.collectParameterInformation|collectParameterInformation(){}[0]
     abstract fun deactivateToEndGroup(kotlin/Boolean) // androidx.compose.runtime/Composer.deactivateToEndGroup|deactivateToEndGroup(kotlin.Boolean){}[0]
@@ -872,18 +806,12 @@
     abstract fun endDefaults() // androidx.compose.runtime/Composer.endDefaults|endDefaults(){}[0]
     abstract fun endMovableGroup() // androidx.compose.runtime/Composer.endMovableGroup|endMovableGroup(){}[0]
     abstract fun endNode() // androidx.compose.runtime/Composer.endNode|endNode(){}[0]
-    abstract fun endProvider() // androidx.compose.runtime/Composer.endProvider|endProvider(){}[0]
-    abstract fun endProviders() // androidx.compose.runtime/Composer.endProviders|endProviders(){}[0]
     abstract fun endReplaceGroup() // androidx.compose.runtime/Composer.endReplaceGroup|endReplaceGroup(){}[0]
     abstract fun endReplaceableGroup() // androidx.compose.runtime/Composer.endReplaceableGroup|endReplaceableGroup(){}[0]
     abstract fun endRestartGroup(): androidx.compose.runtime/ScopeUpdateScope? // androidx.compose.runtime/Composer.endRestartGroup|endRestartGroup(){}[0]
     abstract fun endReusableGroup() // androidx.compose.runtime/Composer.endReusableGroup|endReusableGroup(){}[0]
     abstract fun endToMarker(kotlin/Int) // androidx.compose.runtime/Composer.endToMarker|endToMarker(kotlin.Int){}[0]
-    abstract fun insertMovableContent(androidx.compose.runtime/MovableContent<*>, kotlin/Any?) // androidx.compose.runtime/Composer.insertMovableContent|insertMovableContent(androidx.compose.runtime.MovableContent<*>;kotlin.Any?){}[0]
-    abstract fun insertMovableContentReferences(kotlin.collections/List<kotlin/Pair<androidx.compose.runtime/MovableContentStateReference, androidx.compose.runtime/MovableContentStateReference?>>) // androidx.compose.runtime/Composer.insertMovableContentReferences|insertMovableContentReferences(kotlin.collections.List<kotlin.Pair<androidx.compose.runtime.MovableContentStateReference,androidx.compose.runtime.MovableContentStateReference?>>){}[0]
     abstract fun joinKey(kotlin/Any?, kotlin/Any?): kotlin/Any // androidx.compose.runtime/Composer.joinKey|joinKey(kotlin.Any?;kotlin.Any?){}[0]
-    abstract fun recordSideEffect(kotlin/Function0<kotlin/Unit>) // androidx.compose.runtime/Composer.recordSideEffect|recordSideEffect(kotlin.Function0<kotlin.Unit>){}[0]
-    abstract fun recordUsed(androidx.compose.runtime/RecomposeScope) // androidx.compose.runtime/Composer.recordUsed|recordUsed(androidx.compose.runtime.RecomposeScope){}[0]
     abstract fun rememberedValue(): kotlin/Any? // androidx.compose.runtime/Composer.rememberedValue|rememberedValue(){}[0]
     abstract fun skipCurrentGroup() // androidx.compose.runtime/Composer.skipCurrentGroup|skipCurrentGroup(){}[0]
     abstract fun skipToGroupEnd() // androidx.compose.runtime/Composer.skipToGroupEnd|skipToGroupEnd(){}[0]
@@ -893,8 +821,6 @@
     abstract fun startDefaults() // androidx.compose.runtime/Composer.startDefaults|startDefaults(){}[0]
     abstract fun startMovableGroup(kotlin/Int, kotlin/Any?) // androidx.compose.runtime/Composer.startMovableGroup|startMovableGroup(kotlin.Int;kotlin.Any?){}[0]
     abstract fun startNode() // androidx.compose.runtime/Composer.startNode|startNode(){}[0]
-    abstract fun startProvider(androidx.compose.runtime/ProvidedValue<*>) // androidx.compose.runtime/Composer.startProvider|startProvider(androidx.compose.runtime.ProvidedValue<*>){}[0]
-    abstract fun startProviders(kotlin/Array<out androidx.compose.runtime/ProvidedValue<*>>) // androidx.compose.runtime/Composer.startProviders|startProviders(kotlin.Array<out|androidx.compose.runtime.ProvidedValue<*>>){}[0]
     abstract fun startReplaceGroup(kotlin/Int) // androidx.compose.runtime/Composer.startReplaceGroup|startReplaceGroup(kotlin.Int){}[0]
     abstract fun startReplaceableGroup(kotlin/Int) // androidx.compose.runtime/Composer.startReplaceableGroup|startReplaceableGroup(kotlin.Int){}[0]
     abstract fun startRestartGroup(kotlin/Int): androidx.compose.runtime/Composer // androidx.compose.runtime/Composer.startRestartGroup|startRestartGroup(kotlin.Int){}[0]
@@ -904,14 +830,10 @@
     abstract fun useNode() // androidx.compose.runtime/Composer.useNode|useNode(){}[0]
     abstract val applier // androidx.compose.runtime/Composer.applier|{}applier[0]
         abstract fun <get-applier>(): androidx.compose.runtime/Applier<*> // androidx.compose.runtime/Composer.applier.<get-applier>|<get-applier>(){}[0]
-    abstract val applyCoroutineContext // androidx.compose.runtime/Composer.applyCoroutineContext|{}applyCoroutineContext[0]
-        abstract fun <get-applyCoroutineContext>(): kotlin.coroutines/CoroutineContext // androidx.compose.runtime/Composer.applyCoroutineContext.<get-applyCoroutineContext>|<get-applyCoroutineContext>(){}[0]
     abstract val composition // androidx.compose.runtime/Composer.composition|{}composition[0]
         abstract fun <get-composition>(): androidx.compose.runtime/ControlledComposition // androidx.compose.runtime/Composer.composition.<get-composition>|<get-composition>(){}[0]
     abstract val compositionData // androidx.compose.runtime/Composer.compositionData|{}compositionData[0]
         abstract fun <get-compositionData>(): androidx.compose.runtime.tooling/CompositionData // androidx.compose.runtime/Composer.compositionData.<get-compositionData>|<get-compositionData>(){}[0]
-    abstract val compoundKeyHash // androidx.compose.runtime/Composer.compoundKeyHash|{}compoundKeyHash[0]
-        abstract fun <get-compoundKeyHash>(): kotlin/Int // androidx.compose.runtime/Composer.compoundKeyHash.<get-compoundKeyHash>|<get-compoundKeyHash>(){}[0]
     abstract val currentCompositionLocalMap // androidx.compose.runtime/Composer.currentCompositionLocalMap|{}currentCompositionLocalMap[0]
         abstract fun <get-currentCompositionLocalMap>(): androidx.compose.runtime/CompositionLocalMap // androidx.compose.runtime/Composer.currentCompositionLocalMap.<get-currentCompositionLocalMap>|<get-currentCompositionLocalMap>(){}[0]
     abstract val currentMarker // androidx.compose.runtime/Composer.currentMarker|{}currentMarker[0]
@@ -920,14 +842,11 @@
         abstract fun <get-defaultsInvalid>(): kotlin/Boolean // androidx.compose.runtime/Composer.defaultsInvalid.<get-defaultsInvalid>|<get-defaultsInvalid>(){}[0]
     abstract val inserting // androidx.compose.runtime/Composer.inserting|{}inserting[0]
         abstract fun <get-inserting>(): kotlin/Boolean // androidx.compose.runtime/Composer.inserting.<get-inserting>|<get-inserting>(){}[0]
-    abstract val recomposeScope // androidx.compose.runtime/Composer.recomposeScope|{}recomposeScope[0]
-        abstract fun <get-recomposeScope>(): androidx.compose.runtime/RecomposeScope? // androidx.compose.runtime/Composer.recomposeScope.<get-recomposeScope>|<get-recomposeScope>(){}[0]
     abstract val recomposeScopeIdentity // androidx.compose.runtime/Composer.recomposeScopeIdentity|{}recomposeScopeIdentity[0]
         abstract fun <get-recomposeScopeIdentity>(): kotlin/Any? // androidx.compose.runtime/Composer.recomposeScopeIdentity.<get-recomposeScopeIdentity>|<get-recomposeScopeIdentity>(){}[0]
     abstract val skipping // androidx.compose.runtime/Composer.skipping|{}skipping[0]
         abstract fun <get-skipping>(): kotlin/Boolean // androidx.compose.runtime/Composer.skipping.<get-skipping>|<get-skipping>(){}[0]
     final object Companion { // androidx.compose.runtime/Composer.Companion|null[0]
-        final fun setTracer(androidx.compose.runtime/CompositionTracer) // androidx.compose.runtime/Composer.Companion.setTracer|setTracer(androidx.compose.runtime.CompositionTracer){}[0]
         final val Empty // androidx.compose.runtime/Composer.Companion.Empty|{}Empty[0]
             final fun <get-Empty>(): kotlin/Any // androidx.compose.runtime/Composer.Companion.Empty.<get-Empty>|<get-Empty>(){}[0]
     }
@@ -955,8 +874,6 @@
     abstract fun applyLateChanges() // androidx.compose.runtime/ControlledComposition.applyLateChanges|applyLateChanges(){}[0]
     abstract fun changesApplied() // androidx.compose.runtime/ControlledComposition.changesApplied|changesApplied(){}[0]
     abstract fun composeContent(kotlin/Function0<kotlin/Unit>) // androidx.compose.runtime/ControlledComposition.composeContent|composeContent(kotlin.Function0<kotlin.Unit>){}[0]
-    abstract fun disposeUnusedMovableContent(androidx.compose.runtime/MovableContentState) // androidx.compose.runtime/ControlledComposition.disposeUnusedMovableContent|disposeUnusedMovableContent(androidx.compose.runtime.MovableContentState){}[0]
-    abstract fun insertMovableContent(kotlin.collections/List<kotlin/Pair<androidx.compose.runtime/MovableContentStateReference, androidx.compose.runtime/MovableContentStateReference?>>) // androidx.compose.runtime/ControlledComposition.insertMovableContent|insertMovableContent(kotlin.collections.List<kotlin.Pair<androidx.compose.runtime.MovableContentStateReference,androidx.compose.runtime.MovableContentStateReference?>>){}[0]
     abstract fun invalidateAll() // androidx.compose.runtime/ControlledComposition.invalidateAll|invalidateAll(){}[0]
     abstract fun observesAnyOf(kotlin.collections/Set<kotlin/Any>): kotlin/Boolean // androidx.compose.runtime/ControlledComposition.observesAnyOf|observesAnyOf(kotlin.collections.Set<kotlin.Any>){}[0]
     abstract fun prepareCompose(kotlin/Function0<kotlin/Unit>) // androidx.compose.runtime/ControlledComposition.prepareCompose|prepareCompose(kotlin.Function0<kotlin.Unit>){}[0]
@@ -964,7 +881,6 @@
     abstract fun recordModificationsOf(kotlin.collections/Set<kotlin/Any>) // androidx.compose.runtime/ControlledComposition.recordModificationsOf|recordModificationsOf(kotlin.collections.Set<kotlin.Any>){}[0]
     abstract fun recordReadOf(kotlin/Any) // androidx.compose.runtime/ControlledComposition.recordReadOf|recordReadOf(kotlin.Any){}[0]
     abstract fun recordWriteOf(kotlin/Any) // androidx.compose.runtime/ControlledComposition.recordWriteOf|recordWriteOf(kotlin.Any){}[0]
-    abstract fun verifyConsistent() // androidx.compose.runtime/ControlledComposition.verifyConsistent|verifyConsistent(){}[0]
     abstract val hasPendingChanges // androidx.compose.runtime/ControlledComposition.hasPendingChanges|{}hasPendingChanges[0]
         abstract fun <get-hasPendingChanges>(): kotlin/Boolean // androidx.compose.runtime/ControlledComposition.hasPendingChanges.<get-hasPendingChanges>|<get-hasPendingChanges>(){}[0]
     abstract val isComposing // androidx.compose.runtime/ControlledComposition.isComposing|{}isComposing[0]
diff --git a/compose/runtime/runtime/build.gradle b/compose/runtime/runtime/build.gradle
index 1406001..df41707 100644
--- a/compose/runtime/runtime/build.gradle
+++ b/compose/runtime/runtime/build.gradle
@@ -44,7 +44,7 @@
         commonMain {
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
-                implementation(libs.kotlinCoroutinesCore)
+                api(libs.kotlinCoroutinesCore)
                 implementation(project(":collection:collection"))
                 implementation(project(":performance:performance-annotation"))
             }
@@ -79,7 +79,6 @@
             dependsOn(nonEmulatorJvmMain)
             dependencies {
                 implementation(libs.kotlinStdlib)
-                api(libs.kotlinCoroutinesCore)
             }
         }
 
diff --git a/compose/runtime/runtime/integration-tests/src/androidInstrumentedTest/kotlin/androidx/compose/runtime/LiveEditApiTests.kt b/compose/runtime/runtime/integration-tests/src/androidInstrumentedTest/kotlin/androidx/compose/runtime/LiveEditApiTests.kt
index e82df85..0fecebd 100644
--- a/compose/runtime/runtime/integration-tests/src/androidInstrumentedTest/kotlin/androidx/compose/runtime/LiveEditApiTests.kt
+++ b/compose/runtime/runtime/integration-tests/src/androidInstrumentedTest/kotlin/androidx/compose/runtime/LiveEditApiTests.kt
@@ -38,7 +38,7 @@
         invalidateGroupsWithKey(key)
     }
 
-    private fun compositionErrors(): List<Pair<Exception, Boolean>> = currentCompositionErrors()
+    private fun compositionErrors(): List<Pair<Throwable, Boolean>> = getCurrentCompositionErrors()
 
     @Before
     fun setUp() {
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/HotReloader.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/HotReloader.kt
index 5d29f70..0e3f8d5 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/HotReloader.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/HotReloader.kt
@@ -18,6 +18,9 @@
 
 package androidx.compose.runtime
 
+import androidx.annotation.RestrictTo
+import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP
+
 /**
  * Apply Code Changes will invoke the two functions before and after a code swap.
  *
@@ -84,10 +87,28 @@
  *
  * @return pair of error and whether the error is recoverable.
  */
-// suppressing for test-only api
-@Suppress("ListIterator")
+@Deprecated(
+    "currentCompositionErrors only reports errors that extend from Exception. This method is " +
+        "unsupported outside of Compose runtime tests. Internally, getCurrentCompositionErrors " +
+        "should be used instead."
+)
 @TestOnly
 fun currentCompositionErrors(): List<Pair<Exception, Boolean>> =
+    getCurrentCompositionErrors().mapNotNull { (cause, recoverable) ->
+        (cause as? Exception ?: return@mapNotNull null) to recoverable
+    }
+
+/**
+ * Get list of errors captured in composition. This list is only available when recomposer is in hot
+ * reload mode. Test-only API, not for use in production.
+ *
+ * @return pair of error and whether the error is recoverable.
+ */
+// suppressing for test-only api
+@Suppress("ListIterator")
+@RestrictTo(LIBRARY_GROUP)
+@TestOnly
+fun getCurrentCompositionErrors(): List<Pair<Throwable, Boolean>> =
     HotReloader.getCurrentErrors().map { it.cause to it.recoverable }
 
 /**
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt
index 1cfa3cc..1562252 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt
@@ -124,7 +124,7 @@
 @InternalComposeApi
 internal interface RecomposerErrorInfo {
     /** Exception which forced recomposition to halt. */
-    val cause: Exception
+    val cause: Throwable
 
     /**
      * Whether composition can recover from the error by itself. If the error is not recoverable,
@@ -432,7 +432,7 @@
 
     private class RecomposerErrorState(
         override val recoverable: Boolean,
-        override val cause: Exception
+        override val cause: Throwable
     ) : RecomposerErrorInfo
 
     private val recomposerInfo = RecomposerInfoImpl()
@@ -620,7 +620,7 @@
                                 performRecompose(composition, modifiedValues)?.let { toApply += it }
                                 alreadyComposed.add(composition)
                             }
-                        } catch (e: Exception) {
+                        } catch (e: Throwable) {
                             processCompositionError(e, recoverable = true)
                             clearRecompositionState()
                             return@withFrameNanos
@@ -664,7 +664,7 @@
                                     toLateApply += performInsertValues(toInsert, modifiedValues)
                                     fillToInsert()
                                 }
-                            } catch (e: Exception) {
+                            } catch (e: Throwable) {
                                 processCompositionError(e, recoverable = true)
                                 clearRecompositionState()
                                 return@withFrameNanos
@@ -682,7 +682,7 @@
                             // toComplete += toApply
                             toApply.fastForEach { composition -> toComplete.add(composition) }
                             toApply.fastForEach { composition -> composition.applyChanges() }
-                        } catch (e: Exception) {
+                        } catch (e: Throwable) {
                             processCompositionError(e)
                             clearRecompositionState()
                             return@withFrameNanos
@@ -695,7 +695,7 @@
                         try {
                             toComplete += toLateApply
                             toLateApply.forEach { composition -> composition.applyLateChanges() }
-                        } catch (e: Exception) {
+                        } catch (e: Throwable) {
                             processCompositionError(e)
                             clearRecompositionState()
                             return@withFrameNanos
@@ -707,7 +707,7 @@
                     if (toComplete.isNotEmpty()) {
                         try {
                             toComplete.forEach { composition -> composition.changesApplied() }
-                        } catch (e: Exception) {
+                        } catch (e: Throwable) {
                             processCompositionError(e)
                             clearRecompositionState()
                             return@withFrameNanos
@@ -735,7 +735,7 @@
     }
 
     private fun processCompositionError(
-        e: Exception,
+        e: Throwable,
         failedInitialComposition: ControlledComposition? = null,
         recoverable: Boolean = false,
     ) {
@@ -1130,7 +1130,7 @@
         val composerWasComposing = composition.isComposing
         try {
             composing(composition, null) { composition.composeContent(content) }
-        } catch (e: Exception) {
+        } catch (e: Throwable) {
             processCompositionError(e, composition, recoverable = true)
             return
         }
@@ -1150,7 +1150,7 @@
 
         try {
             performInitialMovableContentInserts(composition)
-        } catch (e: Exception) {
+        } catch (e: Throwable) {
             processCompositionError(e, composition, recoverable = true)
             return
         }
@@ -1158,7 +1158,7 @@
         try {
             composition.applyChanges()
             composition.applyLateChanges()
-        } catch (e: Exception) {
+        } catch (e: Throwable) {
             processCompositionError(e)
             return
         }
diff --git a/compose/runtime/runtime/src/nonEmulatorJvmTest/kotlin/androidx/compose/runtime/LiveEditTests.kt b/compose/runtime/runtime/src/nonEmulatorJvmTest/kotlin/androidx/compose/runtime/LiveEditTests.kt
index 45485f9..253950b 100644
--- a/compose/runtime/runtime/src/nonEmulatorJvmTest/kotlin/androidx/compose/runtime/LiveEditTests.kt
+++ b/compose/runtime/runtime/src/nonEmulatorJvmTest/kotlin/androidx/compose/runtime/LiveEditTests.kt
@@ -676,14 +676,14 @@
     } catch (e: Exception) {
         addError(e)
     }
-    currentCompositionErrors().forEach { addError(it.first) }
+    getCurrentCompositionErrors().forEach { addError(it.first) }
 }
 
 @Stable
 class LiveEditTestScope {
     private val targetKeys = mutableSetOf<Int>()
     private val checks = mutableListOf<() -> Unit>()
-    private val errors = mutableSetOf<Exception>()
+    private val errors = mutableSetOf<Throwable>()
     private val logs = mutableListOf<Pair<String, String>>()
 
     fun invalidateTargets() {
@@ -706,7 +706,7 @@
         logs.add(ref to msg)
     }
 
-    fun addError(e: Exception) {
+    fun addError(e: Throwable) {
         errors.add(e)
     }
 
diff --git a/compose/ui/ui-graphics/lint-baseline.xml b/compose/ui/ui-graphics/lint-baseline.xml
index 862a7fe..3255d39 100644
--- a/compose/ui/ui-graphics/lint-baseline.xml
+++ b/compose/ui/ui-graphics/lint-baseline.xml
@@ -1,13 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.9.0-alpha06" type="baseline" client="gradle" dependencies="false" name="AGP (8.9.0-alpha06)" variant="all" version="8.9.0-alpha06">
+<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="Call requires API level 23 (current min is 21): `android.view.View#setForeground`"
-        errorLine1="                                foreground = GraphicsContextHostDrawable(graphicsContext, block)"
-        errorLine2="                                           ~">
+        message="This Kotlin extension function will be hidden by `java.util.SequencedCollection` starting in API 35"
+        errorLine1="                val node = s.removeLastKt()"
+        errorLine2="                           ~~~~~~~~~~~~~~~~">
         <location
-            file="src/androidInstrumentedTest/kotlin/androidx/compose/ui/graphics/layer/AndroidGraphicsLayerTest.kt"/>
+            file="src/commonMain/kotlin/androidx/compose/ui/graphics/IntervalTree.kt"/>
     </issue>
 
     <issue
diff --git a/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/RippleTest.kt b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/RippleTest.kt
index 74aa3b9..1e3e949 100644
--- a/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/RippleTest.kt
+++ b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/RippleTest.kt
@@ -47,6 +47,5 @@
                 .get()
         val toSkip = app.rootsList.single().viewsToSkipList
         assertThat(composeViewChildren).containsExactlyElementsIn(toSkip)
-        assertThat(toSkip).hasSize(1)
     }
 }
diff --git a/compose/ui/ui-test-manifest/integration-tests/testapp/build.gradle b/compose/ui/ui-test-manifest/integration-tests/testapp/build.gradle
index a0957a4..1997776 100644
--- a/compose/ui/ui-test-manifest/integration-tests/testapp/build.gradle
+++ b/compose/ui/ui-test-manifest/integration-tests/testapp/build.gradle
@@ -22,10 +22,10 @@
 }
 
 dependencies {
-
     debugImplementation(project(":compose:ui:ui-test-manifest"))
 
     implementation(project(":compose:ui:ui"))
+    implementation(project(":compose:foundation:foundation"))
     implementation("androidx.tracing:tracing:1.1.0")
     androidTestImplementation(project(":compose:ui:ui-test-junit4"))
     androidTestImplementation(libs.testRunner)
@@ -35,4 +35,8 @@
 android {
     compileSdk = 35
     namespace = "androidx.compose.ui.test.manifest.integration.testapp"
+
+    defaultConfig {
+        targetSdkVersion 35
+    }
 }
diff --git a/compose/ui/ui-test-manifest/integration-tests/testapp/src/androidTest/java/androidx/compose/ui/test/manifest/integration/testapp/ComponentActivityLaunchesTest.kt b/compose/ui/ui-test-manifest/integration-tests/testapp/src/androidTest/java/androidx/compose/ui/test/manifest/integration/testapp/ComponentActivityLaunchesTest.kt
index 6895df0..1ddeb53 100644
--- a/compose/ui/ui-test-manifest/integration-tests/testapp/src/androidTest/java/androidx/compose/ui/test/manifest/integration/testapp/ComponentActivityLaunchesTest.kt
+++ b/compose/ui/ui-test-manifest/integration-tests/testapp/src/androidTest/java/androidx/compose/ui/test/manifest/integration/testapp/ComponentActivityLaunchesTest.kt
@@ -16,9 +16,22 @@
 
 package androidx.compose.ui.test.manifest.integration.testapp
 
-import androidx.compose.ui.test.junit4.createComposeRule
+import android.os.Build
+import androidx.activity.ComponentActivity
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.size
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toPixelMap
+import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.junit4.createAndroidComposeRule
+import androidx.compose.ui.test.onNodeWithTag
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -26,11 +39,42 @@
 @LargeTest
 @RunWith(AndroidJUnit4::class)
 class ComponentActivityLaunchesTest {
-    @get:Rule val rule = createComposeRule()
+    @get:Rule val rule = createAndroidComposeRule<ComponentActivity>()
 
     @Test
-    fun test() {
+    fun activity_launches() {
         rule.setContent {}
         // Test does not crash and does not time out
     }
+
+    // Regression test for b/383368165
+    // When targeting SDK 35, an activity is edge-to-edge by default and the action bar will overlap
+    // the content. We can only detect this by taking a screenshot, assertIsDisplayed() doesn't work
+    // due to b/383368165#comment2.
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun activity_notCoveredByActionBar() {
+        val color = Color.Red
+        val size = 10
+        rule.setContent {
+            with(LocalDensity.current) {
+                Box(Modifier.size(size.toDp()).background(color).testTag("box"))
+            }
+        }
+
+        rule.onNodeWithTag("box").captureToImage().let {
+            assert(it.width == size && it.height == size) {
+                // We don't really need to test this, but better be safe then sorry
+                "Screenshot size should be 10x10, but was ${it.width}x${it.height}"
+            }
+            val map = it.toPixelMap()
+            for (y in 0 until map.height) {
+                for (x in 0 until map.width) {
+                    assert(map[x, y] == color) {
+                        "Pixel at ($x, $y) is ${map[x, y]} instead of $color"
+                    }
+                }
+            }
+        }
+    }
 }
diff --git a/compose/ui/ui-test-manifest/src/main/AndroidManifest.xml b/compose/ui/ui-test-manifest/src/main/AndroidManifest.xml
index d96a063..620129d 100644
--- a/compose/ui/ui-test-manifest/src/main/AndroidManifest.xml
+++ b/compose/ui/ui-test-manifest/src/main/AndroidManifest.xml
@@ -16,6 +16,7 @@
   -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
     <application>
-        <activity android:name="androidx.activity.ComponentActivity" android:exported="true" />
+        <activity android:theme="@android:style/Theme.Material.Light.NoActionBar"
+            android:name="androidx.activity.ComponentActivity" android:exported="true" />
     </application>
 </manifest>
diff --git a/compose/ui/ui-test/bcv/native/1.7.0.txt b/compose/ui/ui-test/bcv/native/1.7.0.txt
index 5ecdc65..ace0d02 100644
--- a/compose/ui/ui-test/bcv/native/1.7.0.txt
+++ b/compose/ui/ui-test/bcv/native/1.7.0.txt
@@ -6,12 +6,6 @@
 // - Show declarations: true
 
 // Library unique name: <androidx.compose.ui:ui-test>
-abstract class androidx.compose.ui.test.internal/DelayPropagatingContinuationInterceptorWrapper : kotlin.coroutines/AbstractCoroutineContextElement, kotlin.coroutines/ContinuationInterceptor, kotlinx.coroutines/Delay { // androidx.compose.ui.test.internal/DelayPropagatingContinuationInterceptorWrapper|null[0]
-    constructor <init>(kotlin.coroutines/ContinuationInterceptor?) // androidx.compose.ui.test.internal/DelayPropagatingContinuationInterceptorWrapper.<init>|<init>(kotlin.coroutines.ContinuationInterceptor?){}[0]
-    open fun invokeOnTimeout(kotlin/Long, kotlinx.coroutines/Runnable, kotlin.coroutines/CoroutineContext): kotlinx.coroutines/DisposableHandle // androidx.compose.ui.test.internal/DelayPropagatingContinuationInterceptorWrapper.invokeOnTimeout|invokeOnTimeout(kotlin.Long;kotlinx.coroutines.Runnable;kotlin.coroutines.CoroutineContext){}[0]
-    open fun scheduleResumeAfterDelay(kotlin/Long, kotlinx.coroutines/CancellableContinuation<kotlin/Unit>) // androidx.compose.ui.test.internal/DelayPropagatingContinuationInterceptorWrapper.scheduleResumeAfterDelay|scheduleResumeAfterDelay(kotlin.Long;kotlinx.coroutines.CancellableContinuation<kotlin.Unit>){}[0]
-    open suspend fun delay(kotlin/Long) // androidx.compose.ui.test.internal/DelayPropagatingContinuationInterceptorWrapper.delay|delay(kotlin.Long){}[0]
-}
 abstract fun interface androidx.compose.ui.test/DeviceConfigurationOverride { // androidx.compose.ui.test/DeviceConfigurationOverride|null[0]
     abstract fun Override(kotlin/Function0<kotlin/Unit>) // androidx.compose.ui.test/DeviceConfigurationOverride.Override|Override(kotlin.Function0<kotlin.Unit>){}[0]
     final object Companion // androidx.compose.ui.test/DeviceConfigurationOverride.Companion|null[0]
@@ -86,40 +80,15 @@
         abstract fun <get-autoAdvance>(): kotlin/Boolean // androidx.compose.ui.test/MainTestClock.autoAdvance.<get-autoAdvance>|<get-autoAdvance>(){}[0]
         abstract fun <set-autoAdvance>(kotlin/Boolean) // androidx.compose.ui.test/MainTestClock.autoAdvance.<set-autoAdvance>|<set-autoAdvance>(kotlin.Boolean){}[0]
 }
-abstract interface androidx.compose.ui.test/MouseInjectionScope : androidx.compose.ui.test/InjectionScope { // androidx.compose.ui.test/MouseInjectionScope|null[0]
-    abstract fun cancel(kotlin/Long =...) // androidx.compose.ui.test/MouseInjectionScope.cancel|cancel(kotlin.Long){}[0]
-    abstract fun enter(androidx.compose.ui.geometry/Offset =..., kotlin/Long =...) // androidx.compose.ui.test/MouseInjectionScope.enter|enter(androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
-    abstract fun exit(androidx.compose.ui.geometry/Offset =..., kotlin/Long =...) // androidx.compose.ui.test/MouseInjectionScope.exit|exit(androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
-    abstract fun moveTo(androidx.compose.ui.geometry/Offset, kotlin/Long =...) // androidx.compose.ui.test/MouseInjectionScope.moveTo|moveTo(androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
-    abstract fun press(androidx.compose.ui.test/MouseButton =...) // androidx.compose.ui.test/MouseInjectionScope.press|press(androidx.compose.ui.test.MouseButton){}[0]
-    abstract fun release(androidx.compose.ui.test/MouseButton =...) // androidx.compose.ui.test/MouseInjectionScope.release|release(androidx.compose.ui.test.MouseButton){}[0]
-    abstract fun scroll(kotlin/Float, androidx.compose.ui.test/ScrollWheel =...) // androidx.compose.ui.test/MouseInjectionScope.scroll|scroll(kotlin.Float;androidx.compose.ui.test.ScrollWheel){}[0]
-    abstract fun updatePointerTo(androidx.compose.ui.geometry/Offset) // androidx.compose.ui.test/MouseInjectionScope.updatePointerTo|updatePointerTo(androidx.compose.ui.geometry.Offset){}[0]
-    abstract val currentPosition // androidx.compose.ui.test/MouseInjectionScope.currentPosition|{}currentPosition[0]
-        abstract fun <get-currentPosition>(): androidx.compose.ui.geometry/Offset // androidx.compose.ui.test/MouseInjectionScope.currentPosition.<get-currentPosition>|<get-currentPosition>(){}[0]
-    open fun moveBy(androidx.compose.ui.geometry/Offset, kotlin/Long =...) // androidx.compose.ui.test/MouseInjectionScope.moveBy|moveBy(androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
-    open fun updatePointerBy(androidx.compose.ui.geometry/Offset) // androidx.compose.ui.test/MouseInjectionScope.updatePointerBy|updatePointerBy(androidx.compose.ui.geometry.Offset){}[0]
-}
-abstract interface androidx.compose.ui.test/RotaryInjectionScope : androidx.compose.ui.test/InjectionScope { // androidx.compose.ui.test/RotaryInjectionScope|null[0]
-    abstract fun rotateToScrollHorizontally(kotlin/Float) // androidx.compose.ui.test/RotaryInjectionScope.rotateToScrollHorizontally|rotateToScrollHorizontally(kotlin.Float){}[0]
-    abstract fun rotateToScrollVertically(kotlin/Float) // androidx.compose.ui.test/RotaryInjectionScope.rotateToScrollVertically|rotateToScrollVertically(kotlin.Float){}[0]
-}
 abstract interface androidx.compose.ui.test/SemanticsNodeInteractionsProvider { // androidx.compose.ui.test/SemanticsNodeInteractionsProvider|null[0]
     abstract fun onAllNodes(androidx.compose.ui.test/SemanticsMatcher, kotlin/Boolean =...): androidx.compose.ui.test/SemanticsNodeInteractionCollection // androidx.compose.ui.test/SemanticsNodeInteractionsProvider.onAllNodes|onAllNodes(androidx.compose.ui.test.SemanticsMatcher;kotlin.Boolean){}[0]
     abstract fun onNode(androidx.compose.ui.test/SemanticsMatcher, kotlin/Boolean =...): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/SemanticsNodeInteractionsProvider.onNode|onNode(androidx.compose.ui.test.SemanticsMatcher;kotlin.Boolean){}[0]
 }
-abstract interface androidx.compose.ui.test/TestOwner { // androidx.compose.ui.test/TestOwner|null[0]
-    abstract fun <#A1: kotlin/Any?> runOnUiThread(kotlin/Function0<#A1>): #A1 // androidx.compose.ui.test/TestOwner.runOnUiThread|runOnUiThread(kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]
-    abstract fun getRoots(kotlin/Boolean): kotlin.collections/Set<androidx.compose.ui.node/RootForTest> // androidx.compose.ui.test/TestOwner.getRoots|getRoots(kotlin.Boolean){}[0]
-    abstract val mainClock // androidx.compose.ui.test/TestOwner.mainClock|{}mainClock[0]
-        abstract fun <get-mainClock>(): androidx.compose.ui.test/MainTestClock // androidx.compose.ui.test/TestOwner.mainClock.<get-mainClock>|<get-mainClock>(){}[0]
-}
 abstract interface androidx.compose.ui.test/TouchInjectionScope : androidx.compose.ui.test/InjectionScope { // androidx.compose.ui.test/TouchInjectionScope|null[0]
     abstract fun cancel(kotlin/Long =...) // androidx.compose.ui.test/TouchInjectionScope.cancel|cancel(kotlin.Long){}[0]
     abstract fun currentPosition(kotlin/Int =...): androidx.compose.ui.geometry/Offset? // androidx.compose.ui.test/TouchInjectionScope.currentPosition|currentPosition(kotlin.Int){}[0]
     abstract fun down(kotlin/Int, androidx.compose.ui.geometry/Offset) // androidx.compose.ui.test/TouchInjectionScope.down|down(kotlin.Int;androidx.compose.ui.geometry.Offset){}[0]
     abstract fun move(kotlin/Long =...) // androidx.compose.ui.test/TouchInjectionScope.move|move(kotlin.Long){}[0]
-    abstract fun moveWithHistoryMultiPointer(kotlin.collections/List<kotlin/Long>, kotlin.collections/List<kotlin.collections/List<androidx.compose.ui.geometry/Offset>>, kotlin/Long =...) // androidx.compose.ui.test/TouchInjectionScope.moveWithHistoryMultiPointer|moveWithHistoryMultiPointer(kotlin.collections.List<kotlin.Long>;kotlin.collections.List<kotlin.collections.List<androidx.compose.ui.geometry.Offset>>;kotlin.Long){}[0]
     abstract fun up(kotlin/Int =...) // androidx.compose.ui.test/TouchInjectionScope.up|up(kotlin.Int){}[0]
     abstract fun updatePointerTo(kotlin/Int, androidx.compose.ui.geometry/Offset) // androidx.compose.ui.test/TouchInjectionScope.updatePointerTo|updatePointerTo(kotlin.Int;androidx.compose.ui.geometry.Offset){}[0]
     open fun down(androidx.compose.ui.geometry/Offset) // androidx.compose.ui.test/TouchInjectionScope.down|down(androidx.compose.ui.geometry.Offset){}[0]
@@ -127,7 +96,6 @@
     open fun moveBy(kotlin/Int, androidx.compose.ui.geometry/Offset, kotlin/Long =...) // androidx.compose.ui.test/TouchInjectionScope.moveBy|moveBy(kotlin.Int;androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
     open fun moveTo(androidx.compose.ui.geometry/Offset, kotlin/Long =...) // androidx.compose.ui.test/TouchInjectionScope.moveTo|moveTo(androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
     open fun moveTo(kotlin/Int, androidx.compose.ui.geometry/Offset, kotlin/Long =...) // androidx.compose.ui.test/TouchInjectionScope.moveTo|moveTo(kotlin.Int;androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
-    open fun moveWithHistory(kotlin.collections/List<kotlin/Long>, kotlin.collections/List<androidx.compose.ui.geometry/Offset>, kotlin/Long =...) // androidx.compose.ui.test/TouchInjectionScope.moveWithHistory|moveWithHistory(kotlin.collections.List<kotlin.Long>;kotlin.collections.List<androidx.compose.ui.geometry.Offset>;kotlin.Long){}[0]
     open fun updatePointerBy(kotlin/Int, androidx.compose.ui.geometry/Offset) // androidx.compose.ui.test/TouchInjectionScope.updatePointerBy|updatePointerBy(kotlin.Int;androidx.compose.ui.geometry.Offset){}[0]
 }
 final class androidx.compose.ui.test/ComposeTimeoutException : kotlin/Throwable { // androidx.compose.ui.test/ComposeTimeoutException|null[0]
@@ -182,21 +150,11 @@
     final val description // androidx.compose.ui.test/SemanticsSelector.description|{}description[0]
         final fun <get-description>(): kotlin/String // androidx.compose.ui.test/SemanticsSelector.description.<get-description>|<get-description>(){}[0]
 }
-final class androidx.compose.ui.test/StateRestorationTester { // androidx.compose.ui.test/StateRestorationTester|null[0]
-    constructor <init>(androidx.compose.ui.test/ComposeUiTest) // androidx.compose.ui.test/StateRestorationTester.<init>|<init>(androidx.compose.ui.test.ComposeUiTest){}[0]
-    final fun emulateSaveAndRestore() // androidx.compose.ui.test/StateRestorationTester.emulateSaveAndRestore|emulateSaveAndRestore(){}[0]
-    final fun setContent(kotlin/Function0<kotlin/Unit>) // androidx.compose.ui.test/StateRestorationTester.setContent|setContent(kotlin.Function0<kotlin.Unit>){}[0]
-}
 final class androidx.compose.ui.test/TestContext // androidx.compose.ui.test/TestContext|null[0]
-final fun (androidx.compose.ui.test/ComposeUiTest).androidx.compose.ui.test/waitUntilAtLeastOneExists(androidx.compose.ui.test/SemanticsMatcher, kotlin/Long =...) // androidx.compose.ui.test/waitUntilAtLeastOneExists|[email protected](androidx.compose.ui.test.SemanticsMatcher;kotlin.Long){}[0]
-final fun (androidx.compose.ui.test/ComposeUiTest).androidx.compose.ui.test/waitUntilDoesNotExist(androidx.compose.ui.test/SemanticsMatcher, kotlin/Long =...) // androidx.compose.ui.test/waitUntilDoesNotExist|[email protected](androidx.compose.ui.test.SemanticsMatcher;kotlin.Long){}[0]
-final fun (androidx.compose.ui.test/ComposeUiTest).androidx.compose.ui.test/waitUntilExactlyOneExists(androidx.compose.ui.test/SemanticsMatcher, kotlin/Long =...) // androidx.compose.ui.test/waitUntilExactlyOneExists|[email protected](androidx.compose.ui.test.SemanticsMatcher;kotlin.Long){}[0]
-final fun (androidx.compose.ui.test/ComposeUiTest).androidx.compose.ui.test/waitUntilNodeCount(androidx.compose.ui.test/SemanticsMatcher, kotlin/Int, kotlin/Long =...) // androidx.compose.ui.test/waitUntilNodeCount|[email protected](androidx.compose.ui.test.SemanticsMatcher;kotlin.Int;kotlin.Long){}[0]
 final fun (androidx.compose.ui.test/DeviceConfigurationOverride).androidx.compose.ui.test/then(androidx.compose.ui.test/DeviceConfigurationOverride): androidx.compose.ui.test/DeviceConfigurationOverride // androidx.compose.ui.test/then|[email protected](androidx.compose.ui.test.DeviceConfigurationOverride){}[0]
 final fun (androidx.compose.ui.test/DeviceConfigurationOverride.Companion).androidx.compose.ui.test/FontScale(kotlin/Float): androidx.compose.ui.test/DeviceConfigurationOverride // androidx.compose.ui.test/FontScale|FontScale@androidx.compose.ui.test.DeviceConfigurationOverride.Companion(kotlin.Float){}[0]
 final fun (androidx.compose.ui.test/DeviceConfigurationOverride.Companion).androidx.compose.ui.test/ForcedSize(androidx.compose.ui.unit/DpSize): androidx.compose.ui.test/DeviceConfigurationOverride // androidx.compose.ui.test/ForcedSize|ForcedSize@androidx.compose.ui.test.DeviceConfigurationOverride.Companion(androidx.compose.ui.unit.DpSize){}[0]
 final fun (androidx.compose.ui.test/DeviceConfigurationOverride.Companion).androidx.compose.ui.test/LayoutDirection(androidx.compose.ui.unit/LayoutDirection): androidx.compose.ui.test/DeviceConfigurationOverride // androidx.compose.ui.test/LayoutDirection|LayoutDirection@androidx.compose.ui.test.DeviceConfigurationOverride.Companion(androidx.compose.ui.unit.LayoutDirection){}[0]
-final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/advanceEventTime(kotlin/Long) // androidx.compose.ui.test/advanceEventTime|[email protected](kotlin.Long){}[0]
 final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/cancel() // androidx.compose.ui.test/cancel|[email protected](){}[0]
 final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/click(androidx.compose.ui.geometry/Offset =...) // androidx.compose.ui.test/click|[email protected](androidx.compose.ui.geometry.Offset){}[0]
 final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/doubleClick(androidx.compose.ui.geometry/Offset =..., kotlin/Long =...) // androidx.compose.ui.test/doubleClick|[email protected](androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
@@ -214,13 +172,9 @@
 final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/pinch(androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset, kotlin/Long =...) // androidx.compose.ui.test/pinch|[email protected](androidx.compose.ui.geometry.Offset;androidx.compose.ui.geometry.Offset;androidx.compose.ui.geometry.Offset;androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
 final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/swipe(androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset, kotlin/Long =...) // androidx.compose.ui.test/swipe|[email protected](androidx.compose.ui.geometry.Offset;androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
 final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/swipeDown() // androidx.compose.ui.test/swipeDown|[email protected](){}[0]
-final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/swipeDown(kotlin/Float =..., kotlin/Float =..., kotlin/Long =...) // androidx.compose.ui.test/swipeDown|[email protected](kotlin.Float;kotlin.Float;kotlin.Long){}[0]
 final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/swipeLeft() // androidx.compose.ui.test/swipeLeft|[email protected](){}[0]
-final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/swipeLeft(kotlin/Float =..., kotlin/Float =..., kotlin/Long =...) // androidx.compose.ui.test/swipeLeft|[email protected](kotlin.Float;kotlin.Float;kotlin.Long){}[0]
 final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/swipeRight() // androidx.compose.ui.test/swipeRight|[email protected](){}[0]
-final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/swipeRight(kotlin/Float =..., kotlin/Float =..., kotlin/Long =...) // androidx.compose.ui.test/swipeRight|[email protected](kotlin.Float;kotlin.Float;kotlin.Long){}[0]
 final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/swipeUp() // androidx.compose.ui.test/swipeUp|[email protected](){}[0]
-final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/swipeUp(kotlin/Float =..., kotlin/Float =..., kotlin/Long =...) // androidx.compose.ui.test/swipeUp|[email protected](kotlin.Float;kotlin.Float;kotlin.Long){}[0]
 final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/swipeWithVelocity(androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset, kotlin/Float, kotlin/Long =...) // androidx.compose.ui.test/swipeWithVelocity|[email protected](androidx.compose.ui.geometry.Offset;androidx.compose.ui.geometry.Offset;kotlin.Float;kotlin.Long){}[0]
 final fun (androidx.compose.ui.test/GestureScope).androidx.compose.ui.test/up(kotlin/Int =...) // androidx.compose.ui.test/up|[email protected](kotlin.Int){}[0]
 final fun (androidx.compose.ui.test/KeyInjectionScope).androidx.compose.ui.test/pressKey(androidx.compose.ui.input.key/Key, kotlin/Long =...) // androidx.compose.ui.test/pressKey|[email protected](androidx.compose.ui.input.key.Key;kotlin.Long){}[0]
@@ -228,21 +182,6 @@
 final fun (androidx.compose.ui.test/KeyInjectionScope).androidx.compose.ui.test/withKeyToggled(androidx.compose.ui.input.key/Key, kotlin/Function1<androidx.compose.ui.test/KeyInjectionScope, kotlin/Unit>) // androidx.compose.ui.test/withKeyToggled|[email protected](androidx.compose.ui.input.key.Key;kotlin.Function1<androidx.compose.ui.test.KeyInjectionScope,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui.test/KeyInjectionScope).androidx.compose.ui.test/withKeysDown(kotlin.collections/List<androidx.compose.ui.input.key/Key>, kotlin/Function1<androidx.compose.ui.test/KeyInjectionScope, kotlin/Unit>) // androidx.compose.ui.test/withKeysDown|[email protected](kotlin.collections.List<androidx.compose.ui.input.key.Key>;kotlin.Function1<androidx.compose.ui.test.KeyInjectionScope,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui.test/KeyInjectionScope).androidx.compose.ui.test/withKeysToggled(kotlin.collections/List<androidx.compose.ui.input.key/Key>, kotlin/Function1<androidx.compose.ui.test/KeyInjectionScope, kotlin/Unit>) // androidx.compose.ui.test/withKeysToggled|[email protected](kotlin.collections.List<androidx.compose.ui.input.key.Key>;kotlin.Function1<androidx.compose.ui.test.KeyInjectionScope,kotlin.Unit>){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/animateAlong(kotlin/Function1<kotlin/Long, androidx.compose.ui.geometry/Offset>, kotlin/Long =...) // androidx.compose.ui.test/animateAlong|[email protected](kotlin.Function1<kotlin.Long,androidx.compose.ui.geometry.Offset>;kotlin.Long){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/animateBy(androidx.compose.ui.geometry/Offset, kotlin/Long =...) // androidx.compose.ui.test/animateBy|[email protected](androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/animateTo(androidx.compose.ui.geometry/Offset, kotlin/Long =...) // androidx.compose.ui.test/animateTo|[email protected](androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/click(androidx.compose.ui.geometry/Offset =...) // androidx.compose.ui.test/click|[email protected](androidx.compose.ui.geometry.Offset){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/click(androidx.compose.ui.geometry/Offset =..., androidx.compose.ui.test/MouseButton =...) // androidx.compose.ui.test/click|[email protected](androidx.compose.ui.geometry.Offset;androidx.compose.ui.test.MouseButton){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/doubleClick(androidx.compose.ui.geometry/Offset =...) // androidx.compose.ui.test/doubleClick|[email protected](androidx.compose.ui.geometry.Offset){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/doubleClick(androidx.compose.ui.geometry/Offset =..., androidx.compose.ui.test/MouseButton =...) // androidx.compose.ui.test/doubleClick|[email protected](androidx.compose.ui.geometry.Offset;androidx.compose.ui.test.MouseButton){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/dragAndDrop(androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset, androidx.compose.ui.test/MouseButton =..., kotlin/Long =...) // androidx.compose.ui.test/dragAndDrop|[email protected](androidx.compose.ui.geometry.Offset;androidx.compose.ui.geometry.Offset;androidx.compose.ui.test.MouseButton;kotlin.Long){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/dragAndDrop(androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset, kotlin/Long =...) // androidx.compose.ui.test/dragAndDrop|[email protected](androidx.compose.ui.geometry.Offset;androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/longClick(androidx.compose.ui.geometry/Offset =...) // androidx.compose.ui.test/longClick|[email protected](androidx.compose.ui.geometry.Offset){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/longClick(androidx.compose.ui.geometry/Offset =..., androidx.compose.ui.test/MouseButton =...) // androidx.compose.ui.test/longClick|[email protected](androidx.compose.ui.geometry.Offset;androidx.compose.ui.test.MouseButton){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/rightClick(androidx.compose.ui.geometry/Offset =...) // androidx.compose.ui.test/rightClick|[email protected](androidx.compose.ui.geometry.Offset){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/smoothScroll(kotlin/Float, kotlin/Long =..., androidx.compose.ui.test/ScrollWheel =...) // androidx.compose.ui.test/smoothScroll|[email protected](kotlin.Float;kotlin.Long;androidx.compose.ui.test.ScrollWheel){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/tripleClick(androidx.compose.ui.geometry/Offset =...) // androidx.compose.ui.test/tripleClick|[email protected](androidx.compose.ui.geometry.Offset){}[0]
-final fun (androidx.compose.ui.test/MouseInjectionScope).androidx.compose.ui.test/tripleClick(androidx.compose.ui.geometry/Offset =..., androidx.compose.ui.test/MouseButton =...) // androidx.compose.ui.test/tripleClick|[email protected](androidx.compose.ui.geometry.Offset;androidx.compose.ui.test.MouseButton){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/assert(androidx.compose.ui.test/SemanticsMatcher, kotlin/Function0<kotlin/String>? =...): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/assert|[email protected](androidx.compose.ui.test.SemanticsMatcher;kotlin.Function0<kotlin.String>?){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/assertContentDescriptionContains(kotlin/String, kotlin/Boolean =..., kotlin/Boolean =...): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/assertContentDescriptionContains|assertContentDescriptionContains@androidx.compose.ui.test.SemanticsNodeInteraction(kotlin.String;kotlin.Boolean;kotlin.Boolean){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/assertContentDescriptionEquals(kotlin/Array<out kotlin/String>...): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/assertContentDescriptionEquals|assertContentDescriptionEquals@androidx.compose.ui.test.SemanticsNodeInteraction(kotlin.Array<out|kotlin.String>...){}[0]
@@ -276,7 +215,6 @@
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/getAlignmentLinePosition(androidx.compose.ui.layout/AlignmentLine): androidx.compose.ui.unit/Dp // androidx.compose.ui.test/getAlignmentLinePosition|getAlignmentLinePosition@androidx.compose.ui.test.SemanticsNodeInteraction(androidx.compose.ui.layout.AlignmentLine){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/getBoundsInRoot(): androidx.compose.ui.unit/DpRect // androidx.compose.ui.test/getBoundsInRoot|getBoundsInRoot@androidx.compose.ui.test.SemanticsNodeInteraction(){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/getUnclippedBoundsInRoot(): androidx.compose.ui.unit/DpRect // androidx.compose.ui.test/getUnclippedBoundsInRoot|getUnclippedBoundsInRoot@androidx.compose.ui.test.SemanticsNodeInteraction(){}[0]
-final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/invokeGlobalAssertions(): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/invokeGlobalAssertions|invokeGlobalAssertions@androidx.compose.ui.test.SemanticsNodeInteraction(){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/isDisplayed(): kotlin/Boolean // androidx.compose.ui.test/isDisplayed|[email protected](){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/isNotDisplayed(): kotlin/Boolean // androidx.compose.ui.test/isNotDisplayed|[email protected](){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/onAncestors(): androidx.compose.ui.test/SemanticsNodeInteractionCollection // androidx.compose.ui.test/onAncestors|[email protected](){}[0]
@@ -287,15 +225,10 @@
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/onSibling(): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/onSibling|[email protected](){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/onSiblings(): androidx.compose.ui.test/SemanticsNodeInteractionCollection // androidx.compose.ui.test/onSiblings|[email protected](){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performClick(): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/performClick|[email protected](){}[0]
-final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performCustomAccessibilityActionWithLabel(kotlin/String): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/performCustomAccessibilityActionWithLabel|performCustomAccessibilityActionWithLabel@androidx.compose.ui.test.SemanticsNodeInteraction(kotlin.String){}[0]
-final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performCustomAccessibilityActionWithLabelMatching(kotlin/String? =..., kotlin/Function1<kotlin/String, kotlin/Boolean>): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/performCustomAccessibilityActionWithLabelMatching|performCustomAccessibilityActionWithLabelMatching@androidx.compose.ui.test.SemanticsNodeInteraction(kotlin.String?;kotlin.Function1<kotlin.String,kotlin.Boolean>){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performGesture(kotlin/Function1<androidx.compose.ui.test/GestureScope, kotlin/Unit>): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/performGesture|[email protected](kotlin.Function1<androidx.compose.ui.test.GestureScope,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performImeAction() // androidx.compose.ui.test/performImeAction|performImeAction@androidx.compose.ui.test.SemanticsNodeInteraction(){}[0]
-final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performKeyInput(kotlin/Function1<androidx.compose.ui.test/KeyInjectionScope, kotlin/Unit>): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/performKeyInput|performKeyInput@androidx.compose.ui.test.SemanticsNodeInteraction(kotlin.Function1<androidx.compose.ui.test.KeyInjectionScope,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performKeyPress(androidx.compose.ui.input.key/KeyEvent): kotlin/Boolean // androidx.compose.ui.test/performKeyPress|performKeyPress@androidx.compose.ui.test.SemanticsNodeInteraction(androidx.compose.ui.input.key.KeyEvent){}[0]
-final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performMouseInput(kotlin/Function1<androidx.compose.ui.test/MouseInjectionScope, kotlin/Unit>): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/performMouseInput|performMouseInput@androidx.compose.ui.test.SemanticsNodeInteraction(kotlin.Function1<androidx.compose.ui.test.MouseInjectionScope,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performMultiModalInput(kotlin/Function1<androidx.compose.ui.test/MultiModalInjectionScope, kotlin/Unit>): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/performMultiModalInput|performMultiModalInput@androidx.compose.ui.test.SemanticsNodeInteraction(kotlin.Function1<androidx.compose.ui.test.MultiModalInjectionScope,kotlin.Unit>){}[0]
-final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performRotaryScrollInput(kotlin/Function1<androidx.compose.ui.test/RotaryInjectionScope, kotlin/Unit>): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/performRotaryScrollInput|performRotaryScrollInput@androidx.compose.ui.test.SemanticsNodeInteraction(kotlin.Function1<androidx.compose.ui.test.RotaryInjectionScope,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performScrollTo(): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/performScrollTo|performScrollTo@androidx.compose.ui.test.SemanticsNodeInteraction(){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performScrollToIndex(kotlin/Int): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/performScrollToIndex|performScrollToIndex@androidx.compose.ui.test.SemanticsNodeInteraction(kotlin.Int){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performScrollToKey(kotlin/Any): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/performScrollToKey|performScrollToKey@androidx.compose.ui.test.SemanticsNodeInteraction(kotlin.Any){}[0]
@@ -304,7 +237,6 @@
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performSemanticsActionUnit(androidx.compose.ui.semantics/SemanticsPropertyKey<androidx.compose.ui.semantics/AccessibilityAction<kotlin/Function0<kotlin/Boolean>>>) // androidx.compose.ui.test/performSemanticsActionUnit|performSemanticsActionUnit@androidx.compose.ui.test.SemanticsNodeInteraction(androidx.compose.ui.semantics.SemanticsPropertyKey<androidx.compose.ui.semantics.AccessibilityAction<kotlin.Function0<kotlin.Boolean>>>){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performTextClearance() // androidx.compose.ui.test/performTextClearance|performTextClearance@androidx.compose.ui.test.SemanticsNodeInteraction(){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performTextInput(kotlin/String) // androidx.compose.ui.test/performTextInput|performTextInput@androidx.compose.ui.test.SemanticsNodeInteraction(kotlin.String){}[0]
-final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performTextInputSelection(androidx.compose.ui.text/TextRange) // androidx.compose.ui.test/performTextInputSelection|performTextInputSelection@androidx.compose.ui.test.SemanticsNodeInteraction(androidx.compose.ui.text.TextRange){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performTextReplacement(kotlin/String) // androidx.compose.ui.test/performTextReplacement|performTextReplacement@androidx.compose.ui.test.SemanticsNodeInteraction(kotlin.String){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performTouchInput(kotlin/Function1<androidx.compose.ui.test/TouchInjectionScope, kotlin/Unit>): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/performTouchInput|performTouchInput@androidx.compose.ui.test.SemanticsNodeInteraction(kotlin.Function1<androidx.compose.ui.test.TouchInjectionScope,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/printToLog(kotlin/String, kotlin/Int =...) // androidx.compose.ui.test/printToLog|[email protected](kotlin.String;kotlin.Int){}[0]
@@ -315,7 +247,6 @@
 final fun (androidx.compose.ui.test/SemanticsNodeInteractionCollection).androidx.compose.ui.test/assertCountEquals(kotlin/Int): androidx.compose.ui.test/SemanticsNodeInteractionCollection // androidx.compose.ui.test/assertCountEquals|assertCountEquals@androidx.compose.ui.test.SemanticsNodeInteractionCollection(kotlin.Int){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteractionCollection).androidx.compose.ui.test/filter(androidx.compose.ui.test/SemanticsMatcher): androidx.compose.ui.test/SemanticsNodeInteractionCollection // androidx.compose.ui.test/filter|filter@androidx.compose.ui.test.SemanticsNodeInteractionCollection(androidx.compose.ui.test.SemanticsMatcher){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteractionCollection).androidx.compose.ui.test/filterToOne(androidx.compose.ui.test/SemanticsMatcher): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/filterToOne|filterToOne@androidx.compose.ui.test.SemanticsNodeInteractionCollection(androidx.compose.ui.test.SemanticsMatcher){}[0]
-final fun (androidx.compose.ui.test/SemanticsNodeInteractionCollection).androidx.compose.ui.test/invokeGlobalAssertions(): androidx.compose.ui.test/SemanticsNodeInteractionCollection // androidx.compose.ui.test/invokeGlobalAssertions|invokeGlobalAssertions@androidx.compose.ui.test.SemanticsNodeInteractionCollection(){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteractionCollection).androidx.compose.ui.test/onFirst(): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/onFirst|onFirst@androidx.compose.ui.test.SemanticsNodeInteractionCollection(){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteractionCollection).androidx.compose.ui.test/onLast(): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/onLast|onLast@androidx.compose.ui.test.SemanticsNodeInteractionCollection(){}[0]
 final fun (androidx.compose.ui.test/SemanticsNodeInteractionCollection).androidx.compose.ui.test/printToLog(kotlin/String, kotlin/Int =...) // androidx.compose.ui.test/printToLog|printToLog@androidx.compose.ui.test.SemanticsNodeInteractionCollection(kotlin.String;kotlin.Int){}[0]
@@ -330,7 +261,6 @@
 final fun (androidx.compose.ui.test/TouchInjectionScope).androidx.compose.ui.test/click(androidx.compose.ui.geometry/Offset =...) // androidx.compose.ui.test/click|[email protected](androidx.compose.ui.geometry.Offset){}[0]
 final fun (androidx.compose.ui.test/TouchInjectionScope).androidx.compose.ui.test/doubleClick(androidx.compose.ui.geometry/Offset =..., kotlin/Long =...) // androidx.compose.ui.test/doubleClick|[email protected](androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
 final fun (androidx.compose.ui.test/TouchInjectionScope).androidx.compose.ui.test/longClick(androidx.compose.ui.geometry/Offset =..., kotlin/Long =...) // androidx.compose.ui.test/longClick|[email protected](androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
-final fun (androidx.compose.ui.test/TouchInjectionScope).androidx.compose.ui.test/multiTouchSwipe(kotlin.collections/List<kotlin/Function1<kotlin/Long, androidx.compose.ui.geometry/Offset>>, kotlin/Long =..., kotlin.collections/List<kotlin/Long> =...) // androidx.compose.ui.test/multiTouchSwipe|[email protected](kotlin.collections.List<kotlin.Function1<kotlin.Long,androidx.compose.ui.geometry.Offset>>;kotlin.Long;kotlin.collections.List<kotlin.Long>){}[0]
 final fun (androidx.compose.ui.test/TouchInjectionScope).androidx.compose.ui.test/pinch(androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset, kotlin/Long =...) // androidx.compose.ui.test/pinch|[email protected](androidx.compose.ui.geometry.Offset;androidx.compose.ui.geometry.Offset;androidx.compose.ui.geometry.Offset;androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
 final fun (androidx.compose.ui.test/TouchInjectionScope).androidx.compose.ui.test/swipe(androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset, kotlin/Long =...) // androidx.compose.ui.test/swipe|[email protected](androidx.compose.ui.geometry.Offset;androidx.compose.ui.geometry.Offset;kotlin.Long){}[0]
 final fun (androidx.compose.ui.test/TouchInjectionScope).androidx.compose.ui.test/swipe(kotlin/Function1<kotlin/Long, androidx.compose.ui.geometry/Offset>, kotlin/Long =..., kotlin.collections/List<kotlin/Long> =...) // androidx.compose.ui.test/swipe|[email protected](kotlin.Function1<kotlin.Long,androidx.compose.ui.geometry.Offset>;kotlin.Long;kotlin.collections.List<kotlin.Long>){}[0]
@@ -343,9 +273,6 @@
 final fun <#A: kotlin/Function<kotlin/Boolean>> (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performSemanticsAction(androidx.compose.ui.semantics/SemanticsPropertyKey<androidx.compose.ui.semantics/AccessibilityAction<#A>>, kotlin/Function1<#A, kotlin/Unit>): androidx.compose.ui.test/SemanticsNodeInteraction // androidx.compose.ui.test/performSemanticsAction|performSemanticsAction@androidx.compose.ui.test.SemanticsNodeInteraction(androidx.compose.ui.semantics.SemanticsPropertyKey<androidx.compose.ui.semantics.AccessibilityAction<0:0>>;kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Function<kotlin.Boolean>>}[0]
 final fun <#A: kotlin/Function<kotlin/Boolean>> (androidx.compose.ui.test/SemanticsNodeInteraction).androidx.compose.ui.test/performSemanticsActionUnit(androidx.compose.ui.semantics/SemanticsPropertyKey<androidx.compose.ui.semantics/AccessibilityAction<#A>>, kotlin/Function1<#A, kotlin/Unit>) // androidx.compose.ui.test/performSemanticsActionUnit|performSemanticsActionUnit@androidx.compose.ui.test.SemanticsNodeInteraction(androidx.compose.ui.semantics.SemanticsPropertyKey<androidx.compose.ui.semantics.AccessibilityAction<0:0>>;kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Function<kotlin.Boolean>>}[0]
 final fun androidx.compose.ui.test/DeviceConfigurationOverride(androidx.compose.ui.test/DeviceConfigurationOverride, kotlin/Function0<kotlin/Unit>) // androidx.compose.ui.test/DeviceConfigurationOverride|DeviceConfigurationOverride(androidx.compose.ui.test.DeviceConfigurationOverride;kotlin.Function0<kotlin.Unit>){}[0]
-final fun androidx.compose.ui.test/PlatformTextInputMethodTestOverride(androidx.compose.ui.platform/PlatformTextInputSession, kotlin/Function0<kotlin/Unit>) // androidx.compose.ui.test/PlatformTextInputMethodTestOverride|PlatformTextInputMethodTestOverride(androidx.compose.ui.platform.PlatformTextInputSession;kotlin.Function0<kotlin.Unit>){}[0]
-final fun androidx.compose.ui.test/addGlobalAssertion(kotlin/String, kotlin/Function1<androidx.compose.ui.test/SemanticsNodeInteraction, kotlin/Unit>) // androidx.compose.ui.test/addGlobalAssertion|addGlobalAssertion(kotlin.String;kotlin.Function1<androidx.compose.ui.test.SemanticsNodeInteraction,kotlin.Unit>){}[0]
-final fun androidx.compose.ui.test/createTestContext(androidx.compose.ui.test/TestOwner): androidx.compose.ui.test/TestContext // androidx.compose.ui.test/createTestContext|createTestContext(androidx.compose.ui.test.TestOwner){}[0]
 final fun androidx.compose.ui.test/hasAnyAncestor(androidx.compose.ui.test/SemanticsMatcher): androidx.compose.ui.test/SemanticsMatcher // androidx.compose.ui.test/hasAnyAncestor|hasAnyAncestor(androidx.compose.ui.test.SemanticsMatcher){}[0]
 final fun androidx.compose.ui.test/hasAnyChild(androidx.compose.ui.test/SemanticsMatcher): androidx.compose.ui.test/SemanticsMatcher // androidx.compose.ui.test/hasAnyChild|hasAnyChild(androidx.compose.ui.test.SemanticsMatcher){}[0]
 final fun androidx.compose.ui.test/hasAnyDescendant(androidx.compose.ui.test/SemanticsMatcher): androidx.compose.ui.test/SemanticsMatcher // androidx.compose.ui.test/hasAnyDescendant|hasAnyDescendant(androidx.compose.ui.test.SemanticsMatcher){}[0]
@@ -387,8 +314,6 @@
 final fun androidx.compose.ui.test/isSelectable(): androidx.compose.ui.test/SemanticsMatcher // androidx.compose.ui.test/isSelectable|isSelectable(){}[0]
 final fun androidx.compose.ui.test/isSelected(): androidx.compose.ui.test/SemanticsMatcher // androidx.compose.ui.test/isSelected|isSelected(){}[0]
 final fun androidx.compose.ui.test/isToggleable(): androidx.compose.ui.test/SemanticsMatcher // androidx.compose.ui.test/isToggleable|isToggleable(){}[0]
-final fun androidx.compose.ui.test/removeGlobalAssertion(kotlin/String) // androidx.compose.ui.test/removeGlobalAssertion|removeGlobalAssertion(kotlin.String){}[0]
-final fun androidx.compose.ui.test/runComposeUiTest(kotlin.coroutines/CoroutineContext =..., kotlin/Function1<androidx.compose.ui.test/ComposeUiTest, kotlin/Unit>) // androidx.compose.ui.test/runComposeUiTest|runComposeUiTest(kotlin.coroutines.CoroutineContext;kotlin.Function1<androidx.compose.ui.test.ComposeUiTest,kotlin.Unit>){}[0]
 final val androidx.compose.ui.test/bottom // androidx.compose.ui.test/bottom|@androidx.compose.ui.test.GestureScope{}bottom[0]
     final inline fun (androidx.compose.ui.test/GestureScope).<get-bottom>(): kotlin/Float // androidx.compose.ui.test/bottom.<get-bottom>|<get-bottom>@androidx.compose.ui.test.GestureScope(){}[0]
 final val androidx.compose.ui.test/bottomCenter // androidx.compose.ui.test/bottomCenter|@androidx.compose.ui.test.GestureScope{}bottomCenter[0]
@@ -449,42 +374,12 @@
     final val buttonId // androidx.compose.ui.test/MouseButton.buttonId|{}buttonId[0]
         final fun <get-buttonId>(): kotlin/Int // androidx.compose.ui.test/MouseButton.buttonId.<get-buttonId>|<get-buttonId>(){}[0]
 }
-final value class androidx.compose.ui.test/ScrollWheel { // androidx.compose.ui.test/ScrollWheel|null[0]
-    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.ui.test/ScrollWheel.equals|equals(kotlin.Any?){}[0]
-    final fun hashCode(): kotlin/Int // androidx.compose.ui.test/ScrollWheel.hashCode|hashCode(){}[0]
-    final fun toString(): kotlin/String // androidx.compose.ui.test/ScrollWheel.toString|toString(){}[0]
-    final object Companion { // androidx.compose.ui.test/ScrollWheel.Companion|null[0]
-        final val Horizontal // androidx.compose.ui.test/ScrollWheel.Companion.Horizontal|{}Horizontal[0]
-            final fun <get-Horizontal>(): androidx.compose.ui.test/ScrollWheel // androidx.compose.ui.test/ScrollWheel.Companion.Horizontal.<get-Horizontal>|<get-Horizontal>(){}[0]
-        final val Vertical // androidx.compose.ui.test/ScrollWheel.Companion.Vertical|{}Vertical[0]
-            final fun <get-Vertical>(): androidx.compose.ui.test/ScrollWheel // androidx.compose.ui.test/ScrollWheel.Companion.Vertical.<get-Vertical>|<get-Vertical>(){}[0]
-    }
-    final val value // androidx.compose.ui.test/ScrollWheel.value|{}value[0]
-        final fun <get-value>(): kotlin/Int // androidx.compose.ui.test/ScrollWheel.value.<get-value>|<get-value>(){}[0]
-}
 open annotation class androidx.compose.ui.test/ExperimentalTestApi : kotlin/Annotation { // androidx.compose.ui.test/ExperimentalTestApi|null[0]
     constructor <init>() // androidx.compose.ui.test/ExperimentalTestApi.<init>|<init>(){}[0]
 }
 open annotation class androidx.compose.ui.test/InternalTestApi : kotlin/Annotation { // androidx.compose.ui.test/InternalTestApi|null[0]
     constructor <init>() // androidx.compose.ui.test/InternalTestApi.<init>|<init>(){}[0]
 }
-sealed interface androidx.compose.ui.test/ComposeUiTest : androidx.compose.ui.test/SemanticsNodeInteractionsProvider { // androidx.compose.ui.test/ComposeUiTest|null[0]
-    abstract fun <#A1: kotlin/Any?> runOnIdle(kotlin/Function0<#A1>): #A1 // androidx.compose.ui.test/ComposeUiTest.runOnIdle|runOnIdle(kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]
-    abstract fun <#A1: kotlin/Any?> runOnUiThread(kotlin/Function0<#A1>): #A1 // androidx.compose.ui.test/ComposeUiTest.runOnUiThread|runOnUiThread(kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]
-    abstract fun registerIdlingResource(androidx.compose.ui.test/IdlingResource) // androidx.compose.ui.test/ComposeUiTest.registerIdlingResource|registerIdlingResource(androidx.compose.ui.test.IdlingResource){}[0]
-    abstract fun setContent(kotlin/Function0<kotlin/Unit>) // androidx.compose.ui.test/ComposeUiTest.setContent|setContent(kotlin.Function0<kotlin.Unit>){}[0]
-    abstract fun unregisterIdlingResource(androidx.compose.ui.test/IdlingResource) // androidx.compose.ui.test/ComposeUiTest.unregisterIdlingResource|unregisterIdlingResource(androidx.compose.ui.test.IdlingResource){}[0]
-    abstract fun waitForIdle() // androidx.compose.ui.test/ComposeUiTest.waitForIdle|waitForIdle(){}[0]
-    abstract fun waitUntil(kotlin/String? =..., kotlin/Long =..., kotlin/Function0<kotlin/Boolean>) // androidx.compose.ui.test/ComposeUiTest.waitUntil|waitUntil(kotlin.String?;kotlin.Long;kotlin.Function0<kotlin.Boolean>){}[0]
-    abstract suspend fun awaitIdle() // androidx.compose.ui.test/ComposeUiTest.awaitIdle|awaitIdle(){}[0]
-    abstract val density // androidx.compose.ui.test/ComposeUiTest.density|{}density[0]
-        abstract fun <get-density>(): androidx.compose.ui.unit/Density // androidx.compose.ui.test/ComposeUiTest.density.<get-density>|<get-density>(){}[0]
-    abstract val mainClock // androidx.compose.ui.test/ComposeUiTest.mainClock|{}mainClock[0]
-        abstract fun <get-mainClock>(): androidx.compose.ui.test/MainTestClock // androidx.compose.ui.test/ComposeUiTest.mainClock.<get-mainClock>|<get-mainClock>(){}[0]
-}
 sealed interface androidx.compose.ui.test/MultiModalInjectionScope : androidx.compose.ui.test/InjectionScope { // androidx.compose.ui.test/MultiModalInjectionScope|null[0]
-    abstract fun key(kotlin/Function1<androidx.compose.ui.test/KeyInjectionScope, kotlin/Unit>) // androidx.compose.ui.test/MultiModalInjectionScope.key|key(kotlin.Function1<androidx.compose.ui.test.KeyInjectionScope,kotlin.Unit>){}[0]
-    abstract fun mouse(kotlin/Function1<androidx.compose.ui.test/MouseInjectionScope, kotlin/Unit>) // androidx.compose.ui.test/MultiModalInjectionScope.mouse|mouse(kotlin.Function1<androidx.compose.ui.test.MouseInjectionScope,kotlin.Unit>){}[0]
-    abstract fun rotary(kotlin/Function1<androidx.compose.ui.test/RotaryInjectionScope, kotlin/Unit>) // androidx.compose.ui.test/MultiModalInjectionScope.rotary|rotary(kotlin.Function1<androidx.compose.ui.test.RotaryInjectionScope,kotlin.Unit>){}[0]
     abstract fun touch(kotlin/Function1<androidx.compose.ui.test/TouchInjectionScope, kotlin/Unit>) // androidx.compose.ui.test/MultiModalInjectionScope.touch|touch(kotlin.Function1<androidx.compose.ui.test.TouchInjectionScope,kotlin.Unit>){}[0]
 }
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/AndroidManifest.xml b/compose/ui/ui-test/src/androidInstrumentedTest/AndroidManifest.xml
index d70ca0d..5ceffbc 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/AndroidManifest.xml
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/AndroidManifest.xml
@@ -16,7 +16,7 @@
   -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
     <application>
-        <activity android:name="androidx.compose.ui.test.ActivityWithActionBar" />
+        <activity android:name="androidx.compose.ui.test.CustomComposeHostActivity" />
         <activity android:name="androidx.compose.ui.test.ClickCounterActivity" />
         <activity android:name="androidx.compose.ui.test.EmptyActivity" />
 
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/BitmapCapturingTest.kt b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/BitmapCapturingTest.kt
index 2120a4c..aaa5e16 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/BitmapCapturingTest.kt
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/BitmapCapturingTest.kt
@@ -63,7 +63,7 @@
         fun createTestSet(): List<TestConfig> =
             listOf(
                 TestConfig(ComponentActivity::class.java),
-                TestConfig(ActivityWithActionBar::class.java)
+                TestConfig(CustomComposeHostActivity::class.java)
             )
     }
 
@@ -239,7 +239,7 @@
 
     private fun setContent(content: @Composable () -> Unit) {
         when (val activity = rule.activity) {
-            is ActivityWithActionBar -> activity.setContent(content)
+            is CustomComposeHostActivity -> activity.setContent(content)
             else -> rule.setContent(content)
         }
     }
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/ActivityWithActionBar.kt b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/CustomComposeHostActivity.kt
similarity index 96%
rename from compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/ActivityWithActionBar.kt
rename to compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/CustomComposeHostActivity.kt
index 4fc309f..f40f330 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/ActivityWithActionBar.kt
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/CustomComposeHostActivity.kt
@@ -25,7 +25,7 @@
 import androidx.compose.ui.platform.ComposeView
 
 // The presence of an ActionBar follows from the theme set in AndroidManifest.xml
-class ActivityWithActionBar : ComponentActivity() {
+class CustomComposeHostActivity : ComponentActivity() {
     private lateinit var composeHolder: ComposeView
 
     override fun onCreate(savedInstanceState: Bundle?) {
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/IsDisplayedTest.kt b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/IsDisplayedTest.kt
index 4311d59..a05ce4c 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/IsDisplayedTest.kt
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/IsDisplayedTest.kt
@@ -70,7 +70,7 @@
         fun createTestSet(): List<TestConfig> =
             listOf(
                 TestConfig(ComponentActivity::class.java),
-                TestConfig(ActivityWithActionBar::class.java)
+                TestConfig(CustomComposeHostActivity::class.java)
             )
     }
 
@@ -314,7 +314,7 @@
 
     private fun setContent(content: @Composable () -> Unit) {
         when (val activity = rule.activity) {
-            is ActivityWithActionBar -> activity.setContent(content)
+            is CustomComposeHostActivity -> activity.setContent(content)
             else -> rule.setContent(content)
         }
     }
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/gesturescope/SendClickTest.kt b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/gesturescope/SendClickTest.kt
index c38fbc1..736a3a9 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/gesturescope/SendClickTest.kt
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/gesturescope/SendClickTest.kt
@@ -24,7 +24,7 @@
 import androidx.compose.ui.input.pointer.PointerInputFilter
 import androidx.compose.ui.input.pointer.PointerInputModifier
 import androidx.compose.ui.input.pointer.changedToUp
-import androidx.compose.ui.test.ActivityWithActionBar
+import androidx.compose.ui.test.CustomComposeHostActivity
 import androidx.compose.ui.test.click
 import androidx.compose.ui.test.junit4.ComposeTestRule
 import androidx.compose.ui.test.junit4.createAndroidComposeRule
@@ -55,11 +55,11 @@
                 for (x in listOf(0.0f, squareSize - 1.0f)) {
                     for (y in listOf(0.0f, squareSize - 1.0f)) {
                         add(TestConfig(Offset(x, y), ComponentActivity::class.java))
-                        add(TestConfig(Offset(x, y), ActivityWithActionBar::class.java))
+                        add(TestConfig(Offset(x, y), CustomComposeHostActivity::class.java))
                     }
                 }
                 add(TestConfig(null, ComponentActivity::class.java))
-                add(TestConfig(null, ActivityWithActionBar::class.java))
+                add(TestConfig(null, CustomComposeHostActivity::class.java))
             }
         }
     }
@@ -89,7 +89,7 @@
         // Given a column of 5 small components
         var contentSet = false
         rule.activityRule.scenario.onActivity {
-            if (it is ActivityWithActionBar) {
+            if (it is CustomComposeHostActivity) {
                 it.setContent { ColumnOfSquares(5) }
                 contentSet = true
             }
diff --git a/compose/ui/ui-text/bcv/native/1.7.0.txt b/compose/ui/ui-text/bcv/native/1.7.0.txt
index a4483cf..60429d0 100644
--- a/compose/ui/ui-text/bcv/native/1.7.0.txt
+++ b/compose/ui/ui-text/bcv/native/1.7.0.txt
@@ -189,18 +189,14 @@
 }
 final class androidx.compose.ui.text.font/ResourceFont : androidx.compose.ui.text.font/Font { // androidx.compose.ui.text.font/ResourceFont|null[0]
     final fun copy(kotlin/Int =..., androidx.compose.ui.text.font/FontWeight =..., androidx.compose.ui.text.font/FontStyle =...): androidx.compose.ui.text.font/ResourceFont // androidx.compose.ui.text.font/ResourceFont.copy|copy(kotlin.Int;androidx.compose.ui.text.font.FontWeight;androidx.compose.ui.text.font.FontStyle){}[0]
-    final fun copy(kotlin/Int =..., androidx.compose.ui.text.font/FontWeight =..., androidx.compose.ui.text.font/FontStyle =..., androidx.compose.ui.text.font/FontLoadingStrategy =..., androidx.compose.ui.text.font/FontVariation.Settings =...): androidx.compose.ui.text.font/ResourceFont // androidx.compose.ui.text.font/ResourceFont.copy|copy(kotlin.Int;androidx.compose.ui.text.font.FontWeight;androidx.compose.ui.text.font.FontStyle;androidx.compose.ui.text.font.FontLoadingStrategy;androidx.compose.ui.text.font.FontVariation.Settings){}[0]
     final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.ui.text.font/ResourceFont.equals|equals(kotlin.Any?){}[0]
     final fun hashCode(): kotlin/Int // androidx.compose.ui.text.font/ResourceFont.hashCode|hashCode(){}[0]
     final fun toString(): kotlin/String // androidx.compose.ui.text.font/ResourceFont.toString|toString(){}[0]
-    final val loadingStrategy // androidx.compose.ui.text.font/ResourceFont.loadingStrategy|{}loadingStrategy[0]
-        final fun <get-loadingStrategy>(): androidx.compose.ui.text.font/FontLoadingStrategy // androidx.compose.ui.text.font/ResourceFont.loadingStrategy.<get-loadingStrategy>|<get-loadingStrategy>(){}[0]
     final val resId // androidx.compose.ui.text.font/ResourceFont.resId|{}resId[0]
         final fun <get-resId>(): kotlin/Int // androidx.compose.ui.text.font/ResourceFont.resId.<get-resId>|<get-resId>(){}[0]
     final val style // androidx.compose.ui.text.font/ResourceFont.style|{}style[0]
         final fun <get-style>(): androidx.compose.ui.text.font/FontStyle // androidx.compose.ui.text.font/ResourceFont.style.<get-style>|<get-style>(){}[0]
     final val variationSettings // androidx.compose.ui.text.font/ResourceFont.variationSettings|{}variationSettings[0]
-        final fun <get-variationSettings>(): androidx.compose.ui.text.font/FontVariation.Settings // androidx.compose.ui.text.font/ResourceFont.variationSettings.<get-variationSettings>|<get-variationSettings>(){}[0]
     final val weight // androidx.compose.ui.text.font/ResourceFont.weight|{}weight[0]
         final fun <get-weight>(): androidx.compose.ui.text.font/FontWeight // androidx.compose.ui.text.font/ResourceFont.weight.<get-weight>|<get-weight>(){}[0]
 }
@@ -309,17 +305,6 @@
     final val amount // androidx.compose.ui.text.input/MoveCursorCommand.amount|{}amount[0]
         final fun <get-amount>(): kotlin/Int // androidx.compose.ui.text.input/MoveCursorCommand.amount.<get-amount>|<get-amount>(){}[0]
 }
-final class androidx.compose.ui.text.input/PartialGapBuffer { // androidx.compose.ui.text.input/PartialGapBuffer|null[0]
-    constructor <init>(kotlin/String) // androidx.compose.ui.text.input/PartialGapBuffer.<init>|<init>(kotlin.String){}[0]
-    final fun get(kotlin/Int): kotlin/Char // androidx.compose.ui.text.input/PartialGapBuffer.get|get(kotlin.Int){}[0]
-    final fun replace(kotlin/Int, kotlin/Int, kotlin/String) // androidx.compose.ui.text.input/PartialGapBuffer.replace|replace(kotlin.Int;kotlin.Int;kotlin.String){}[0]
-    final fun toString(): kotlin/String // androidx.compose.ui.text.input/PartialGapBuffer.toString|toString(){}[0]
-    final val length // androidx.compose.ui.text.input/PartialGapBuffer.length|{}length[0]
-        final fun <get-length>(): kotlin/Int // androidx.compose.ui.text.input/PartialGapBuffer.length.<get-length>|<get-length>(){}[0]
-    final var text // androidx.compose.ui.text.input/PartialGapBuffer.text|{}text[0]
-        final fun <get-text>(): kotlin/String // androidx.compose.ui.text.input/PartialGapBuffer.text.<get-text>|<get-text>(){}[0]
-        final fun <set-text>(kotlin/String) // androidx.compose.ui.text.input/PartialGapBuffer.text.<set-text>|<set-text>(kotlin.String){}[0]
-}
 final class androidx.compose.ui.text.input/PasswordVisualTransformation : androidx.compose.ui.text.input/VisualTransformation { // androidx.compose.ui.text.input/PasswordVisualTransformation|null[0]
     constructor <init>(kotlin/Char =...) // androidx.compose.ui.text.input/PasswordVisualTransformation.<init>|<init>(kotlin.Char){}[0]
     final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.ui.text.input/PasswordVisualTransformation.equals|equals(kotlin.Any?){}[0]
@@ -586,8 +571,6 @@
         final fun addStringAnnotation(kotlin/String, kotlin/String, kotlin/Int, kotlin/Int) // androidx.compose.ui.text/AnnotatedString.Builder.addStringAnnotation|addStringAnnotation(kotlin.String;kotlin.String;kotlin.Int;kotlin.Int){}[0]
         final fun addStyle(androidx.compose.ui.text/ParagraphStyle, kotlin/Int, kotlin/Int) // androidx.compose.ui.text/AnnotatedString.Builder.addStyle|addStyle(androidx.compose.ui.text.ParagraphStyle;kotlin.Int;kotlin.Int){}[0]
         final fun addStyle(androidx.compose.ui.text/SpanStyle, kotlin/Int, kotlin/Int) // androidx.compose.ui.text/AnnotatedString.Builder.addStyle|addStyle(androidx.compose.ui.text.SpanStyle;kotlin.Int;kotlin.Int){}[0]
-        final fun addTtsAnnotation(androidx.compose.ui.text/TtsAnnotation, kotlin/Int, kotlin/Int) // androidx.compose.ui.text/AnnotatedString.Builder.addTtsAnnotation|addTtsAnnotation(androidx.compose.ui.text.TtsAnnotation;kotlin.Int;kotlin.Int){}[0]
-        final fun addUrlAnnotation(androidx.compose.ui.text/UrlAnnotation, kotlin/Int, kotlin/Int) // androidx.compose.ui.text/AnnotatedString.Builder.addUrlAnnotation|addUrlAnnotation(androidx.compose.ui.text.UrlAnnotation;kotlin.Int;kotlin.Int){}[0]
         final fun append(androidx.compose.ui.text/AnnotatedString) // androidx.compose.ui.text/AnnotatedString.Builder.append|append(androidx.compose.ui.text.AnnotatedString){}[0]
         final fun append(androidx.compose.ui.text/AnnotatedString, kotlin/Int, kotlin/Int) // androidx.compose.ui.text/AnnotatedString.Builder.append|append(androidx.compose.ui.text.AnnotatedString;kotlin.Int;kotlin.Int){}[0]
         final fun append(kotlin/Char): androidx.compose.ui.text/AnnotatedString.Builder // androidx.compose.ui.text/AnnotatedString.Builder.append|append(kotlin.Char){}[0]
@@ -602,7 +585,6 @@
         final fun pushStyle(androidx.compose.ui.text/ParagraphStyle): kotlin/Int // androidx.compose.ui.text/AnnotatedString.Builder.pushStyle|pushStyle(androidx.compose.ui.text.ParagraphStyle){}[0]
         final fun pushStyle(androidx.compose.ui.text/SpanStyle): kotlin/Int // androidx.compose.ui.text/AnnotatedString.Builder.pushStyle|pushStyle(androidx.compose.ui.text.SpanStyle){}[0]
         final fun pushTtsAnnotation(androidx.compose.ui.text/TtsAnnotation): kotlin/Int // androidx.compose.ui.text/AnnotatedString.Builder.pushTtsAnnotation|pushTtsAnnotation(androidx.compose.ui.text.TtsAnnotation){}[0]
-        final fun pushUrlAnnotation(androidx.compose.ui.text/UrlAnnotation): kotlin/Int // androidx.compose.ui.text/AnnotatedString.Builder.pushUrlAnnotation|pushUrlAnnotation(androidx.compose.ui.text.UrlAnnotation){}[0]
         final fun toAnnotatedString(): androidx.compose.ui.text/AnnotatedString // androidx.compose.ui.text/AnnotatedString.Builder.toAnnotatedString|toAnnotatedString(){}[0]
         final val length // androidx.compose.ui.text/AnnotatedString.Builder.length|{}length[0]
             final fun <get-length>(): kotlin/Int // androidx.compose.ui.text/AnnotatedString.Builder.length.<get-length>|<get-length>(){}[0]
@@ -613,7 +595,6 @@
     final fun getStringAnnotations(kotlin/Int, kotlin/Int): kotlin.collections/List<androidx.compose.ui.text/AnnotatedString.Range<kotlin/String>> // androidx.compose.ui.text/AnnotatedString.getStringAnnotations|getStringAnnotations(kotlin.Int;kotlin.Int){}[0]
     final fun getStringAnnotations(kotlin/String, kotlin/Int, kotlin/Int): kotlin.collections/List<androidx.compose.ui.text/AnnotatedString.Range<kotlin/String>> // androidx.compose.ui.text/AnnotatedString.getStringAnnotations|getStringAnnotations(kotlin.String;kotlin.Int;kotlin.Int){}[0]
     final fun getTtsAnnotations(kotlin/Int, kotlin/Int): kotlin.collections/List<androidx.compose.ui.text/AnnotatedString.Range<androidx.compose.ui.text/TtsAnnotation>> // androidx.compose.ui.text/AnnotatedString.getTtsAnnotations|getTtsAnnotations(kotlin.Int;kotlin.Int){}[0]
-    final fun getUrlAnnotations(kotlin/Int, kotlin/Int): kotlin.collections/List<androidx.compose.ui.text/AnnotatedString.Range<androidx.compose.ui.text/UrlAnnotation>> // androidx.compose.ui.text/AnnotatedString.getUrlAnnotations|getUrlAnnotations(kotlin.Int;kotlin.Int){}[0]
     final fun hasEqualAnnotations(androidx.compose.ui.text/AnnotatedString): kotlin/Boolean // androidx.compose.ui.text/AnnotatedString.hasEqualAnnotations|hasEqualAnnotations(androidx.compose.ui.text.AnnotatedString){}[0]
     final fun hasLinkAnnotations(kotlin/Int, kotlin/Int): kotlin/Boolean // androidx.compose.ui.text/AnnotatedString.hasLinkAnnotations|hasLinkAnnotations(kotlin.Int;kotlin.Int){}[0]
     final fun hasStringAnnotations(kotlin/String, kotlin/Int, kotlin/Int): kotlin/Boolean // androidx.compose.ui.text/AnnotatedString.hasStringAnnotations|hasStringAnnotations(kotlin.String;kotlin.Int;kotlin.Int){}[0]
@@ -1021,14 +1002,6 @@
     final val textMotion // androidx.compose.ui.text/TextStyle.textMotion|<get-textMotion>(){}[0]
         final fun <get-textMotion>(): androidx.compose.ui.text.style/TextMotion? // androidx.compose.ui.text/TextStyle.textMotion.<get-textMotion>|<get-textMotion>(){}[0]
 }
-final class androidx.compose.ui.text/UrlAnnotation { // androidx.compose.ui.text/UrlAnnotation|null[0]
-    constructor <init>(kotlin/String) // androidx.compose.ui.text/UrlAnnotation.<init>|<init>(kotlin.String){}[0]
-    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.ui.text/UrlAnnotation.equals|equals(kotlin.Any?){}[0]
-    final fun hashCode(): kotlin/Int // androidx.compose.ui.text/UrlAnnotation.hashCode|hashCode(){}[0]
-    final fun toString(): kotlin/String // androidx.compose.ui.text/UrlAnnotation.toString|toString(){}[0]
-    final val url // androidx.compose.ui.text/UrlAnnotation.url|{}url[0]
-        final fun <get-url>(): kotlin/String // androidx.compose.ui.text/UrlAnnotation.url.<get-url>|<get-url>(){}[0]
-}
 final class androidx.compose.ui.text/VerbatimTtsAnnotation : androidx.compose.ui.text/TtsAnnotation { // androidx.compose.ui.text/VerbatimTtsAnnotation|null[0]
     constructor <init>(kotlin/String) // androidx.compose.ui.text/VerbatimTtsAnnotation.<init>|<init>(kotlin.String){}[0]
     final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.ui.text/VerbatimTtsAnnotation.equals|equals(kotlin.Any?){}[0]
@@ -1068,7 +1041,6 @@
 final fun (kotlin/String).androidx.compose.ui.text/toUpperCase(androidx.compose.ui.text.intl/LocaleList): kotlin/String // androidx.compose.ui.text/toUpperCase|[email protected](androidx.compose.ui.text.intl.LocaleList){}[0]
 final fun androidx.compose.ui.text.font/Font(kotlin/Int, androidx.compose.ui.text.font/FontWeight =..., androidx.compose.ui.text.font/FontStyle =...): androidx.compose.ui.text.font/Font // androidx.compose.ui.text.font/Font|Font(kotlin.Int;androidx.compose.ui.text.font.FontWeight;androidx.compose.ui.text.font.FontStyle){}[0]
 final fun androidx.compose.ui.text.font/Font(kotlin/Int, androidx.compose.ui.text.font/FontWeight =..., androidx.compose.ui.text.font/FontStyle =..., androidx.compose.ui.text.font/FontLoadingStrategy =...): androidx.compose.ui.text.font/Font // androidx.compose.ui.text.font/Font|Font(kotlin.Int;androidx.compose.ui.text.font.FontWeight;androidx.compose.ui.text.font.FontStyle;androidx.compose.ui.text.font.FontLoadingStrategy){}[0]
-final fun androidx.compose.ui.text.font/Font(kotlin/Int, androidx.compose.ui.text.font/FontWeight =..., androidx.compose.ui.text.font/FontStyle =..., androidx.compose.ui.text.font/FontLoadingStrategy =..., androidx.compose.ui.text.font/FontVariation.Settings =...): androidx.compose.ui.text.font/Font // androidx.compose.ui.text.font/Font|Font(kotlin.Int;androidx.compose.ui.text.font.FontWeight;androidx.compose.ui.text.font.FontStyle;androidx.compose.ui.text.font.FontLoadingStrategy;androidx.compose.ui.text.font.FontVariation.Settings){}[0]
 final fun androidx.compose.ui.text.font/FontFamily(androidx.compose.ui.text.font/Typeface): androidx.compose.ui.text.font/FontFamily // androidx.compose.ui.text.font/FontFamily|FontFamily(androidx.compose.ui.text.font.Typeface){}[0]
 final fun androidx.compose.ui.text.font/FontFamily(kotlin.collections/List<androidx.compose.ui.text.font/Font>): androidx.compose.ui.text.font/FontFamily // androidx.compose.ui.text.font/FontFamily|FontFamily(kotlin.collections.List<androidx.compose.ui.text.font.Font>){}[0]
 final fun androidx.compose.ui.text.font/FontFamily(kotlin/Array<out androidx.compose.ui.text.font/Font>...): androidx.compose.ui.text.font/FontFamily // androidx.compose.ui.text.font/FontFamily|FontFamily(kotlin.Array<out|androidx.compose.ui.text.font.Font>...){}[0]
@@ -1093,9 +1065,6 @@
 final fun androidx.compose.ui.text/lerp(androidx.compose.ui.text/SpanStyle, androidx.compose.ui.text/SpanStyle, kotlin/Float): androidx.compose.ui.text/SpanStyle // androidx.compose.ui.text/lerp|lerp(androidx.compose.ui.text.SpanStyle;androidx.compose.ui.text.SpanStyle;kotlin.Float){}[0]
 final fun androidx.compose.ui.text/lerp(androidx.compose.ui.text/TextStyle, androidx.compose.ui.text/TextStyle, kotlin/Float): androidx.compose.ui.text/TextStyle // androidx.compose.ui.text/lerp|lerp(androidx.compose.ui.text.TextStyle;androidx.compose.ui.text.TextStyle;kotlin.Float){}[0]
 final fun androidx.compose.ui.text/resolveDefaults(androidx.compose.ui.text/TextStyle, androidx.compose.ui.unit/LayoutDirection): androidx.compose.ui.text/TextStyle // androidx.compose.ui.text/resolveDefaults|resolveDefaults(androidx.compose.ui.text.TextStyle;androidx.compose.ui.unit.LayoutDirection){}[0]
-final inline fun <#A: kotlin/Any> (androidx.compose.ui.text/AnnotatedString.Builder).androidx.compose.ui.text/withAnnotation(androidx.compose.ui.text/TtsAnnotation, crossinline kotlin/Function1<androidx.compose.ui.text/AnnotatedString.Builder, #A>): #A // androidx.compose.ui.text/withAnnotation|[email protected](androidx.compose.ui.text.TtsAnnotation;kotlin.Function1<androidx.compose.ui.text.AnnotatedString.Builder,0:0>){0§<kotlin.Any>}[0]
-final inline fun <#A: kotlin/Any> (androidx.compose.ui.text/AnnotatedString.Builder).androidx.compose.ui.text/withAnnotation(androidx.compose.ui.text/UrlAnnotation, crossinline kotlin/Function1<androidx.compose.ui.text/AnnotatedString.Builder, #A>): #A // androidx.compose.ui.text/withAnnotation|[email protected](androidx.compose.ui.text.UrlAnnotation;kotlin.Function1<androidx.compose.ui.text.AnnotatedString.Builder,0:0>){0§<kotlin.Any>}[0]
-final inline fun <#A: kotlin/Any> (androidx.compose.ui.text/AnnotatedString.Builder).androidx.compose.ui.text/withAnnotation(kotlin/String, kotlin/String, crossinline kotlin/Function1<androidx.compose.ui.text/AnnotatedString.Builder, #A>): #A // androidx.compose.ui.text/withAnnotation|[email protected](kotlin.String;kotlin.String;kotlin.Function1<androidx.compose.ui.text.AnnotatedString.Builder,0:0>){0§<kotlin.Any>}[0]
 final inline fun <#A: kotlin/Any> (androidx.compose.ui.text/AnnotatedString.Builder).androidx.compose.ui.text/withLink(androidx.compose.ui.text/LinkAnnotation, kotlin/Function1<androidx.compose.ui.text/AnnotatedString.Builder, #A>): #A // androidx.compose.ui.text/withLink|[email protected](androidx.compose.ui.text.LinkAnnotation;kotlin.Function1<androidx.compose.ui.text.AnnotatedString.Builder,0:0>){0§<kotlin.Any>}[0]
 final inline fun <#A: kotlin/Any> (androidx.compose.ui.text/AnnotatedString.Builder).androidx.compose.ui.text/withStyle(androidx.compose.ui.text/ParagraphStyle, crossinline kotlin/Function1<androidx.compose.ui.text/AnnotatedString.Builder, #A>): #A // androidx.compose.ui.text/withStyle|[email protected](androidx.compose.ui.text.ParagraphStyle;kotlin.Function1<androidx.compose.ui.text.AnnotatedString.Builder,0:0>){0§<kotlin.Any>}[0]
 final inline fun <#A: kotlin/Any> (androidx.compose.ui.text/AnnotatedString.Builder).androidx.compose.ui.text/withStyle(androidx.compose.ui.text/SpanStyle, kotlin/Function1<androidx.compose.ui.text/AnnotatedString.Builder, #A>): #A // androidx.compose.ui.text/withStyle|[email protected](androidx.compose.ui.text.SpanStyle;kotlin.Function1<androidx.compose.ui.text.AnnotatedString.Builder,0:0>){0§<kotlin.Any>}[0]
@@ -1408,8 +1377,6 @@
     constructor <init>(androidx.compose.ui.text.input/PlatformTextInputService) // androidx.compose.ui.text.input/TextInputService.<init>|<init>(androidx.compose.ui.text.input.PlatformTextInputService){}[0]
     final fun hideSoftwareKeyboard() // androidx.compose.ui.text.input/TextInputService.hideSoftwareKeyboard|hideSoftwareKeyboard(){}[0]
     final fun showSoftwareKeyboard() // androidx.compose.ui.text.input/TextInputService.showSoftwareKeyboard|showSoftwareKeyboard(){}[0]
-    final fun startInput() // androidx.compose.ui.text.input/TextInputService.startInput|startInput(){}[0]
-    final fun stopInput() // androidx.compose.ui.text.input/TextInputService.stopInput|stopInput(){}[0]
     open fun startInput(androidx.compose.ui.text.input/TextFieldValue, androidx.compose.ui.text.input/ImeOptions, kotlin/Function1<kotlin.collections/List<androidx.compose.ui.text.input/EditCommand>, kotlin/Unit>, kotlin/Function1<androidx.compose.ui.text.input/ImeAction, kotlin/Unit>): androidx.compose.ui.text.input/TextInputSession // androidx.compose.ui.text.input/TextInputService.startInput|startInput(androidx.compose.ui.text.input.TextFieldValue;androidx.compose.ui.text.input.ImeOptions;kotlin.Function1<kotlin.collections.List<androidx.compose.ui.text.input.EditCommand>,kotlin.Unit>;kotlin.Function1<androidx.compose.ui.text.input.ImeAction,kotlin.Unit>){}[0]
     open fun stopInput(androidx.compose.ui.text.input/TextInputSession) // androidx.compose.ui.text.input/TextInputService.stopInput|stopInput(androidx.compose.ui.text.input.TextInputSession){}[0]
 }
diff --git a/compose/ui/ui-unit/bcv/native/1.7.0.txt b/compose/ui/ui-unit/bcv/native/1.7.0.txt
index 047cb1e..70fab01f 100644
--- a/compose/ui/ui-unit/bcv/native/1.7.0.txt
+++ b/compose/ui/ui-unit/bcv/native/1.7.0.txt
@@ -231,7 +231,6 @@
         final fun fixed(kotlin/Int, kotlin/Int): androidx.compose.ui.unit/Constraints // androidx.compose.ui.unit/Constraints.Companion.fixed|fixed(kotlin.Int;kotlin.Int){}[0]
         final fun fixedHeight(kotlin/Int): androidx.compose.ui.unit/Constraints // androidx.compose.ui.unit/Constraints.Companion.fixedHeight|fixedHeight(kotlin.Int){}[0]
         final fun fixedWidth(kotlin/Int): androidx.compose.ui.unit/Constraints // androidx.compose.ui.unit/Constraints.Companion.fixedWidth|fixedWidth(kotlin.Int){}[0]
-        final fun restrictConstraints(kotlin/Int, kotlin/Int, kotlin/Int, kotlin/Int, kotlin/Boolean =...): androidx.compose.ui.unit/Constraints // androidx.compose.ui.unit/Constraints.Companion.restrictConstraints|restrictConstraints(kotlin.Int;kotlin.Int;kotlin.Int;kotlin.Int;kotlin.Boolean){}[0]
     }
     final val hasBoundedHeight // androidx.compose.ui.unit/Constraints.hasBoundedHeight|{}hasBoundedHeight[0]
         final fun <get-hasBoundedHeight>(): kotlin/Boolean // androidx.compose.ui.unit/Constraints.hasBoundedHeight.<get-hasBoundedHeight>|<get-hasBoundedHeight>(){}[0]
diff --git a/compose/ui/ui-unit/build.gradle b/compose/ui/ui-unit/build.gradle
index ce761f72..9cd6331 100644
--- a/compose/ui/ui-unit/build.gradle
+++ b/compose/ui/ui-unit/build.gradle
@@ -28,27 +28,12 @@
 
 plugins {
     id("AndroidXPlugin")
+    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    androidLibrary {
-        namespace = "androidx.compose.ui.unit"
-        withAndroidTestOnDeviceBuilder {
-            it.compilationName = "instrumentedTest"
-            it.defaultSourceSetName = "androidInstrumentedTest"
-            it.sourceSetTreeName = "test"
-        }
-        withAndroidTestOnJvmBuilder {
-            it.defaultSourceSetName = "androidUnitTest"
-        }
-        optimization {
-            it.consumerKeepRules.publish = true
-            it.consumerKeepRules.files.add(
-                    new File(project.projectDir, "proguard-rules.pro")
-            )
-        }
-    }
+    android()
     jvmStubs()
     linuxX64Stubs()
 
@@ -131,3 +116,9 @@
     kotlinTarget = KotlinTarget.KOTLIN_1_9
 }
 
+android {
+    namespace "androidx.compose.ui.unit"
+    buildTypes.configureEach {
+        consumerProguardFiles("proguard-rules.pro")
+    }
+}
diff --git a/compose/ui/ui-util/bcv/native/1.7.0.txt b/compose/ui/ui-util/bcv/native/1.7.0.txt
new file mode 100644
index 0000000..f39dd8c
--- /dev/null
+++ b/compose/ui/ui-util/bcv/native/1.7.0.txt
@@ -0,0 +1,65 @@
+// Klib ABI Dump
+// Targets: [linuxX64.linuxx64Stubs]
+// Rendering settings:
+// - Signature version: 2
+// - Show manifest properties: true
+// - Show declarations: true
+
+// Library unique name: <androidx.compose.ui:ui-util>
+final fun (kotlin/Double).androidx.compose.ui.util/fastRoundToInt(): kotlin/Int // androidx.compose.ui.util/fastRoundToInt|[email protected](){}[0]
+final fun (kotlin/Float).androidx.compose.ui.util/fastRoundToInt(): kotlin/Int // androidx.compose.ui.util/fastRoundToInt|[email protected](){}[0]
+final fun <#A: kotlin/Any> (kotlin.collections/List<#A?>).androidx.compose.ui.util/fastFilterNotNull(): kotlin.collections/List<#A> // androidx.compose.ui.util/fastFilterNotNull|[email protected]<0:0?>(){0§<kotlin.Any>}[0]
+final fun <#A: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastJoinToString(kotlin/CharSequence =..., kotlin/CharSequence =..., kotlin/CharSequence =..., kotlin/Int =..., kotlin/CharSequence =..., kotlin/Function1<#A, kotlin/CharSequence>? =...): kotlin/String // androidx.compose.ui.util/fastJoinToString|[email protected]<0:0>(kotlin.CharSequence;kotlin.CharSequence;kotlin.CharSequence;kotlin.Int;kotlin.CharSequence;kotlin.Function1<0:0,kotlin.CharSequence>?){0§<kotlin.Any?>}[0]
+final fun androidx.compose.ui.util/doubleFromBits(kotlin/Long): kotlin/Double // androidx.compose.ui.util/doubleFromBits|doubleFromBits(kotlin.Long){}[0]
+final fun androidx.compose.ui.util/fastCbrt(kotlin/Float): kotlin/Float // androidx.compose.ui.util/fastCbrt|fastCbrt(kotlin.Float){}[0]
+final fun androidx.compose.ui.util/floatFromBits(kotlin/Int): kotlin/Float // androidx.compose.ui.util/floatFromBits|floatFromBits(kotlin.Int){}[0]
+final fun androidx.compose.ui.util/lerp(kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.ui.util/lerp|lerp(kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+final fun androidx.compose.ui.util/lerp(kotlin/Int, kotlin/Int, kotlin/Float): kotlin/Int // androidx.compose.ui.util/lerp|lerp(kotlin.Int;kotlin.Int;kotlin.Float){}[0]
+final fun androidx.compose.ui.util/lerp(kotlin/Long, kotlin/Long, kotlin/Float): kotlin/Long // androidx.compose.ui.util/lerp|lerp(kotlin.Long;kotlin.Long;kotlin.Float){}[0]
+final inline fun (kotlin/Double).androidx.compose.ui.util/fastCoerceAtLeast(kotlin/Double): kotlin/Double // androidx.compose.ui.util/fastCoerceAtLeast|[email protected](kotlin.Double){}[0]
+final inline fun (kotlin/Double).androidx.compose.ui.util/fastCoerceAtMost(kotlin/Double): kotlin/Double // androidx.compose.ui.util/fastCoerceAtMost|[email protected](kotlin.Double){}[0]
+final inline fun (kotlin/Double).androidx.compose.ui.util/fastCoerceIn(kotlin/Double, kotlin/Double): kotlin/Double // androidx.compose.ui.util/fastCoerceIn|[email protected](kotlin.Double;kotlin.Double){}[0]
+final inline fun (kotlin/Float).androidx.compose.ui.util/fastCoerceAtLeast(kotlin/Float): kotlin/Float // androidx.compose.ui.util/fastCoerceAtLeast|[email protected](kotlin.Float){}[0]
+final inline fun (kotlin/Float).androidx.compose.ui.util/fastCoerceAtMost(kotlin/Float): kotlin/Float // androidx.compose.ui.util/fastCoerceAtMost|[email protected](kotlin.Float){}[0]
+final inline fun (kotlin/Float).androidx.compose.ui.util/fastCoerceIn(kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.ui.util/fastCoerceIn|[email protected](kotlin.Float;kotlin.Float){}[0]
+final inline fun <#A: kotlin/Any?, #B: #A> (kotlin.collections/List<#B>).androidx.compose.ui.util/fastReduce(kotlin/Function2<#A, #B, #A>): #A // androidx.compose.ui.util/fastReduce|[email protected]<0:1>(kotlin.Function2<0:0,0:1,0:0>){0§<kotlin.Any?>;1§<0:0>}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin.collections/MutableCollection<in #B>> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastMapTo(#C, kotlin/Function1<#A, #B>): #C // androidx.compose.ui.util/fastMapTo|[email protected]<0:0>(0:2;kotlin.Function1<0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<kotlin.collections.MutableCollection<in|0:1>>}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastZip(kotlin.collections/List<#B>, kotlin/Function2<#A, #B, #C>): kotlin.collections/List<#C> // androidx.compose.ui.util/fastZip|[email protected]<0:0>(kotlin.collections.List<0:1>;kotlin.Function2<0:0,0:1,0:2>){0§<kotlin.Any?>;1§<kotlin.Any?>;2§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastDistinctBy(kotlin/Function1<#A, #B>): kotlin.collections/List<#A> // androidx.compose.ui.util/fastDistinctBy|[email protected]<0:0>(kotlin.Function1<0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastFlatMap(kotlin/Function1<#A, kotlin.collections/Iterable<#B>>): kotlin.collections/List<#B> // androidx.compose.ui.util/fastFlatMap|[email protected]<0:0>(kotlin.Function1<0:0,kotlin.collections.Iterable<0:1>>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastFold(#B, kotlin/Function2<#B, #A, #B>): #B // androidx.compose.ui.util/fastFold|[email protected]<0:0>(0:1;kotlin.Function2<0:1,0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastMap(kotlin/Function1<#A, #B>): kotlin.collections/List<#B> // androidx.compose.ui.util/fastMap|[email protected]<0:0>(kotlin.Function1<0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastMapIndexed(kotlin/Function2<kotlin/Int, #A, #B>): kotlin.collections/List<#B> // androidx.compose.ui.util/fastMapIndexed|[email protected]<0:0>(kotlin.Function2<kotlin.Int,0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastMapIndexedNotNull(kotlin/Function2<kotlin/Int, #A, #B?>): kotlin.collections/List<#B> // androidx.compose.ui.util/fastMapIndexedNotNull|[email protected]<0:0>(kotlin.Function2<kotlin.Int,0:0,0:1?>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastMapNotNull(kotlin/Function1<#A, #B?>): kotlin.collections/List<#B> // androidx.compose.ui.util/fastMapNotNull|[email protected]<0:0>(kotlin.Function1<0:0,0:1?>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastZipWithNext(kotlin/Function2<#A, #A, #B>): kotlin.collections/List<#B> // androidx.compose.ui.util/fastZipWithNext|[email protected]<0:0>(kotlin.Function2<0:0,0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Comparable<#B>> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastMaxBy(kotlin/Function1<#A, #B>): #A? // androidx.compose.ui.util/fastMaxBy|[email protected]<0:0>(kotlin.Function1<0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Comparable<0:1>>}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Comparable<#B>> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastMaxOfOrNull(kotlin/Function1<#A, #B>): #B? // androidx.compose.ui.util/fastMaxOfOrNull|[email protected]<0:0>(kotlin.Function1<0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Comparable<0:1>>}[0]
+final inline fun <#A: kotlin/Any?, #B: kotlin/Comparable<#B>> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastMinByOrNull(kotlin/Function1<#A, #B>): #A? // androidx.compose.ui.util/fastMinByOrNull|[email protected]<0:0>(kotlin.Function1<0:0,0:1>){0§<kotlin.Any?>;1§<kotlin.Comparable<0:1>>}[0]
+final inline fun <#A: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastAll(kotlin/Function1<#A, kotlin/Boolean>): kotlin/Boolean // androidx.compose.ui.util/fastAll|[email protected]<0:0>(kotlin.Function1<0:0,kotlin.Boolean>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastAny(kotlin/Function1<#A, kotlin/Boolean>): kotlin/Boolean // androidx.compose.ui.util/fastAny|[email protected]<0:0>(kotlin.Function1<0:0,kotlin.Boolean>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastFilter(kotlin/Function1<#A, kotlin/Boolean>): kotlin.collections/List<#A> // androidx.compose.ui.util/fastFilter|[email protected]<0:0>(kotlin.Function1<0:0,kotlin.Boolean>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastFirst(kotlin/Function1<#A, kotlin/Boolean>): #A // androidx.compose.ui.util/fastFirst|[email protected]<0:0>(kotlin.Function1<0:0,kotlin.Boolean>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastFirstOrNull(kotlin/Function1<#A, kotlin/Boolean>): #A? // androidx.compose.ui.util/fastFirstOrNull|[email protected]<0:0>(kotlin.Function1<0:0,kotlin.Boolean>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastForEach(kotlin/Function1<#A, kotlin/Unit>) // androidx.compose.ui.util/fastForEach|[email protected]<0:0>(kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastForEachIndexed(kotlin/Function2<kotlin/Int, #A, kotlin/Unit>) // androidx.compose.ui.util/fastForEachIndexed|[email protected]<0:0>(kotlin.Function2<kotlin.Int,0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastForEachReversed(kotlin/Function1<#A, kotlin/Unit>) // androidx.compose.ui.util/fastForEachReversed|[email protected]<0:0>(kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastLastOrNull(kotlin/Function1<#A, kotlin/Boolean>): #A? // androidx.compose.ui.util/fastLastOrNull|[email protected]<0:0>(kotlin.Function1<0:0,kotlin.Boolean>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> (kotlin.collections/List<#A>).androidx.compose.ui.util/fastSumBy(kotlin/Function1<#A, kotlin/Int>): kotlin/Int // androidx.compose.ui.util/fastSumBy|[email protected]<0:0>(kotlin.Function1<0:0,kotlin.Int>){0§<kotlin.Any?>}[0]
+final inline fun <#A: kotlin/Any?> androidx.compose.ui.util/trace(kotlin/String, kotlin/Function0<#A>): #A // androidx.compose.ui.util/trace|trace(kotlin.String;kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]
+final inline fun androidx.compose.ui.util/fastMaxOf(kotlin/Float, kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.ui.util/fastMaxOf|fastMaxOf(kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+final inline fun androidx.compose.ui.util/fastMinOf(kotlin/Float, kotlin/Float, kotlin/Float, kotlin/Float): kotlin/Float // androidx.compose.ui.util/fastMinOf|fastMinOf(kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float){}[0]
+final inline fun androidx.compose.ui.util/packFloats(kotlin/Float, kotlin/Float): kotlin/Long // androidx.compose.ui.util/packFloats|packFloats(kotlin.Float;kotlin.Float){}[0]
+final inline fun androidx.compose.ui.util/packInts(kotlin/Int, kotlin/Int): kotlin/Long // androidx.compose.ui.util/packInts|packInts(kotlin.Int;kotlin.Int){}[0]
+final inline fun androidx.compose.ui.util/unpackAbsFloat1(kotlin/Long): kotlin/Float // androidx.compose.ui.util/unpackAbsFloat1|unpackAbsFloat1(kotlin.Long){}[0]
+final inline fun androidx.compose.ui.util/unpackAbsFloat2(kotlin/Long): kotlin/Float // androidx.compose.ui.util/unpackAbsFloat2|unpackAbsFloat2(kotlin.Long){}[0]
+final inline fun androidx.compose.ui.util/unpackFloat1(kotlin/Long): kotlin/Float // androidx.compose.ui.util/unpackFloat1|unpackFloat1(kotlin.Long){}[0]
+final inline fun androidx.compose.ui.util/unpackFloat2(kotlin/Long): kotlin/Float // androidx.compose.ui.util/unpackFloat2|unpackFloat2(kotlin.Long){}[0]
+final inline fun androidx.compose.ui.util/unpackInt1(kotlin/Long): kotlin/Int // androidx.compose.ui.util/unpackInt1|unpackInt1(kotlin.Long){}[0]
+final inline fun androidx.compose.ui.util/unpackInt2(kotlin/Long): kotlin/Int // androidx.compose.ui.util/unpackInt2|unpackInt2(kotlin.Long){}[0]
+open annotation class androidx.compose.ui/ExperimentalComposeUiApi : kotlin/Annotation { // androidx.compose.ui/ExperimentalComposeUiApi|null[0]
+    constructor <init>() // androidx.compose.ui/ExperimentalComposeUiApi.<init>|<init>(){}[0]
+}
+open annotation class androidx.compose.ui/InternalComposeUiApi : kotlin/Annotation { // androidx.compose.ui/InternalComposeUiApi|null[0]
+    constructor <init>() // androidx.compose.ui/InternalComposeUiApi.<init>|<init>(){}[0]
+}
diff --git a/compose/ui/ui-util/build.gradle b/compose/ui/ui-util/build.gradle
index e2285aa..3a6444a 100644
--- a/compose/ui/ui-util/build.gradle
+++ b/compose/ui/ui-util/build.gradle
@@ -27,27 +27,12 @@
 
 plugins {
     id("AndroidXPlugin")
+    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    androidLibrary {
-        namespace = "androidx.compose.ui.util"
-        withAndroidTestOnDeviceBuilder {
-            it.compilationName = "instrumentedTest"
-            it.defaultSourceSetName = "androidInstrumentedTest"
-            it.sourceSetTreeName = "test"
-        }
-        withAndroidTestOnJvmBuilder {
-            it.defaultSourceSetName = "androidUnitTest"
-        }
-        optimization {
-            it.consumerKeepRules.publish = true
-            it.consumerKeepRules.files.add(
-                    new File(project.projectDir, "proguard-rules.pro")
-            )
-        }
-    }
+    android()
     jvmStubs()
     linuxX64Stubs()
 
@@ -119,3 +104,9 @@
     composeCompilerPluginEnabled = false
 }
 
+android {
+    namespace "androidx.compose.ui.util"
+    buildTypes.configureEach {
+        consumerProguardFiles("proguard-rules.pro")
+    }
+}
diff --git a/compose/ui/ui/api/current.txt b/compose/ui/ui/api/current.txt
index 544b142..7caf96e 100644
--- a/compose/ui/ui/api/current.txt
+++ b/compose/ui/ui/api/current.txt
@@ -135,11 +135,13 @@
     property public final boolean NewNestedScrollFlingDispatchingEnabled;
     property public final boolean isRectTrackingEnabled;
     property public final boolean isSemanticAutofillEnabled;
+    property public final boolean isTrackFocusEnabled;
     property public final boolean isViewFocusFixEnabled;
     field public static final androidx.compose.ui.ComposeUiFlags INSTANCE;
     field public static boolean NewNestedScrollFlingDispatchingEnabled;
     field public static boolean isRectTrackingEnabled;
     field public static boolean isSemanticAutofillEnabled;
+    field public static boolean isTrackFocusEnabled;
     field public static boolean isViewFocusFixEnabled;
   }
 
@@ -2197,8 +2199,8 @@
     method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, Object? key2, androidx.compose.ui.input.pointer.PointerInputEventHandler block);
     method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, Object? key2, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
     method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
-    method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, java.lang.Object?... keys, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
     method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object?[] keys, androidx.compose.ui.input.pointer.PointerInputEventHandler block);
+    method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object?[] keys, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
     method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
   }
 
diff --git a/compose/ui/ui/api/restricted_current.txt b/compose/ui/ui/api/restricted_current.txt
index 310d0f0..a9d48f4 100644
--- a/compose/ui/ui/api/restricted_current.txt
+++ b/compose/ui/ui/api/restricted_current.txt
@@ -135,11 +135,13 @@
     property public final boolean NewNestedScrollFlingDispatchingEnabled;
     property public final boolean isRectTrackingEnabled;
     property public final boolean isSemanticAutofillEnabled;
+    property public final boolean isTrackFocusEnabled;
     property public final boolean isViewFocusFixEnabled;
     field public static final androidx.compose.ui.ComposeUiFlags INSTANCE;
     field public static boolean NewNestedScrollFlingDispatchingEnabled;
     field public static boolean isRectTrackingEnabled;
     field public static boolean isSemanticAutofillEnabled;
+    field public static boolean isTrackFocusEnabled;
     field public static boolean isViewFocusFixEnabled;
   }
 
@@ -2198,8 +2200,8 @@
     method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, Object? key2, androidx.compose.ui.input.pointer.PointerInputEventHandler block);
     method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, Object? key2, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
     method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object? key1, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
-    method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, java.lang.Object?... keys, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
     method public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object?[] keys, androidx.compose.ui.input.pointer.PointerInputEventHandler block);
+    method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, Object?[] keys, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
     method @Deprecated public static androidx.compose.ui.Modifier pointerInput(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function2<? super androidx.compose.ui.input.pointer.PointerInputScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,? extends java.lang.Object?> block);
   }
 
diff --git a/compose/ui/ui/bcv/native/1.7.0.txt b/compose/ui/ui/bcv/native/1.7.0.txt
index bfa44e9..b01201a 100644
--- a/compose/ui/ui/bcv/native/1.7.0.txt
+++ b/compose/ui/ui/bcv/native/1.7.0.txt
@@ -103,9 +103,6 @@
     open fun (androidx.compose.ui.layout/IntrinsicMeasureScope).minIntrinsicHeight(kotlin.collections/List<kotlin.collections/List<androidx.compose.ui.layout/IntrinsicMeasurable>>, kotlin/Int): kotlin/Int // androidx.compose.ui.layout/MultiContentMeasurePolicy.minIntrinsicHeight|minIntrinsicHeight@androidx.compose.ui.layout.IntrinsicMeasureScope(kotlin.collections.List<kotlin.collections.List<androidx.compose.ui.layout.IntrinsicMeasurable>>;kotlin.Int){}[0]
     open fun (androidx.compose.ui.layout/IntrinsicMeasureScope).minIntrinsicWidth(kotlin.collections/List<kotlin.collections/List<androidx.compose.ui.layout/IntrinsicMeasurable>>, kotlin/Int): kotlin/Int // androidx.compose.ui.layout/MultiContentMeasurePolicy.minIntrinsicWidth|minIntrinsicWidth@androidx.compose.ui.layout.IntrinsicMeasureScope(kotlin.collections.List<kotlin.collections.List<androidx.compose.ui.layout.IntrinsicMeasurable>>;kotlin.Int){}[0]
 }
-abstract fun interface androidx.compose.ui.platform/PlatformTextInputInterceptor { // androidx.compose.ui.platform/PlatformTextInputInterceptor|null[0]
-    abstract suspend fun interceptStartInputMethod(androidx.compose.ui.platform/PlatformTextInputMethodRequest, androidx.compose.ui.platform/PlatformTextInputSession): kotlin/Nothing // androidx.compose.ui.platform/PlatformTextInputInterceptor.interceptStartInputMethod|interceptStartInputMethod(androidx.compose.ui.platform.PlatformTextInputMethodRequest;androidx.compose.ui.platform.PlatformTextInputSession){}[0]
-}
 abstract fun interface androidx.compose.ui/Alignment { // androidx.compose.ui/Alignment|null[0]
     abstract fun align(androidx.compose.ui.unit/IntSize, androidx.compose.ui.unit/IntSize, androidx.compose.ui.unit/LayoutDirection): androidx.compose.ui.unit/IntOffset // androidx.compose.ui/Alignment.align|align(androidx.compose.ui.unit.IntSize;androidx.compose.ui.unit.IntSize;androidx.compose.ui.unit.LayoutDirection){}[0]
     abstract fun interface Horizontal { // androidx.compose.ui/Alignment.Horizontal|null[0]
@@ -153,10 +150,6 @@
     abstract val value // androidx.compose.ui.modifier/ModifierLocalProvider.value|{}value[0]
         abstract fun <get-value>(): #A // androidx.compose.ui.modifier/ModifierLocalProvider.value.<get-value>|<get-value>(){}[0]
 }
-abstract interface androidx.compose.ui.autofill/Autofill { // androidx.compose.ui.autofill/Autofill|null[0]
-    abstract fun cancelAutofillForNode(androidx.compose.ui.autofill/AutofillNode) // androidx.compose.ui.autofill/Autofill.cancelAutofillForNode|cancelAutofillForNode(androidx.compose.ui.autofill.AutofillNode){}[0]
-    abstract fun requestAutofillForNode(androidx.compose.ui.autofill/AutofillNode) // androidx.compose.ui.autofill/Autofill.requestAutofillForNode|requestAutofillForNode(androidx.compose.ui.autofill.AutofillNode){}[0]
-}
 abstract interface androidx.compose.ui.draganddrop/DragAndDropModifierNode : androidx.compose.ui.draganddrop/DragAndDropTarget, androidx.compose.ui.node/DelegatableNode { // androidx.compose.ui.draganddrop/DragAndDropModifierNode|null[0]
     abstract fun acceptDragAndDropTransfer(androidx.compose.ui.draganddrop/DragAndDropEvent): kotlin/Boolean // androidx.compose.ui.draganddrop/DragAndDropModifierNode.acceptDragAndDropTransfer|acceptDragAndDropTransfer(androidx.compose.ui.draganddrop.DragAndDropEvent){}[0]
     abstract fun drag(androidx.compose.ui.draganddrop/DragAndDropTransferData, androidx.compose.ui.geometry/Size, kotlin/Function1<androidx.compose.ui.graphics.drawscope/DrawScope, kotlin/Unit>) // androidx.compose.ui.draganddrop/DragAndDropModifierNode.drag|drag(androidx.compose.ui.draganddrop.DragAndDropTransferData;androidx.compose.ui.geometry.Size;kotlin.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit>){}[0]
@@ -207,12 +200,6 @@
     open var end // androidx.compose.ui.focus/FocusProperties.end|{}end[0]
         open fun <get-end>(): androidx.compose.ui.focus/FocusRequester // androidx.compose.ui.focus/FocusProperties.end.<get-end>|<get-end>(){}[0]
         open fun <set-end>(androidx.compose.ui.focus/FocusRequester) // androidx.compose.ui.focus/FocusProperties.end.<set-end>|<set-end>(androidx.compose.ui.focus.FocusRequester){}[0]
-    open var enter // androidx.compose.ui.focus/FocusProperties.enter|{}enter[0]
-        open fun <get-enter>(): kotlin/Function1<androidx.compose.ui.focus/FocusDirection, androidx.compose.ui.focus/FocusRequester> // androidx.compose.ui.focus/FocusProperties.enter.<get-enter>|<get-enter>(){}[0]
-        open fun <set-enter>(kotlin/Function1<androidx.compose.ui.focus/FocusDirection, androidx.compose.ui.focus/FocusRequester>) // androidx.compose.ui.focus/FocusProperties.enter.<set-enter>|<set-enter>(kotlin.Function1<androidx.compose.ui.focus.FocusDirection,androidx.compose.ui.focus.FocusRequester>){}[0]
-    open var exit // androidx.compose.ui.focus/FocusProperties.exit|{}exit[0]
-        open fun <get-exit>(): kotlin/Function1<androidx.compose.ui.focus/FocusDirection, androidx.compose.ui.focus/FocusRequester> // androidx.compose.ui.focus/FocusProperties.exit.<get-exit>|<get-exit>(){}[0]
-        open fun <set-exit>(kotlin/Function1<androidx.compose.ui.focus/FocusDirection, androidx.compose.ui.focus/FocusRequester>) // androidx.compose.ui.focus/FocusProperties.exit.<set-exit>|<set-exit>(kotlin.Function1<androidx.compose.ui.focus.FocusDirection,androidx.compose.ui.focus.FocusRequester>){}[0]
     open var left // androidx.compose.ui.focus/FocusProperties.left|{}left[0]
         open fun <get-left>(): androidx.compose.ui.focus/FocusRequester // androidx.compose.ui.focus/FocusProperties.left.<get-left>|<get-left>(){}[0]
         open fun <set-left>(androidx.compose.ui.focus/FocusRequester) // androidx.compose.ui.focus/FocusProperties.left.<set-left>|<set-left>(androidx.compose.ui.focus.FocusRequester){}[0]
@@ -313,10 +300,6 @@
     abstract fun onKeyEvent(androidx.compose.ui.input.key/KeyEvent): kotlin/Boolean // androidx.compose.ui.input.key/KeyInputModifierNode.onKeyEvent|onKeyEvent(androidx.compose.ui.input.key.KeyEvent){}[0]
     abstract fun onPreKeyEvent(androidx.compose.ui.input.key/KeyEvent): kotlin/Boolean // androidx.compose.ui.input.key/KeyInputModifierNode.onPreKeyEvent|onPreKeyEvent(androidx.compose.ui.input.key.KeyEvent){}[0]
 }
-abstract interface androidx.compose.ui.input.key/SoftKeyboardInterceptionModifierNode : androidx.compose.ui.node/DelegatableNode { // androidx.compose.ui.input.key/SoftKeyboardInterceptionModifierNode|null[0]
-    abstract fun onInterceptKeyBeforeSoftKeyboard(androidx.compose.ui.input.key/KeyEvent): kotlin/Boolean // androidx.compose.ui.input.key/SoftKeyboardInterceptionModifierNode.onInterceptKeyBeforeSoftKeyboard|onInterceptKeyBeforeSoftKeyboard(androidx.compose.ui.input.key.KeyEvent){}[0]
-    abstract fun onPreInterceptKeyBeforeSoftKeyboard(androidx.compose.ui.input.key/KeyEvent): kotlin/Boolean // androidx.compose.ui.input.key/SoftKeyboardInterceptionModifierNode.onPreInterceptKeyBeforeSoftKeyboard|onPreInterceptKeyBeforeSoftKeyboard(androidx.compose.ui.input.key.KeyEvent){}[0]
-}
 abstract interface androidx.compose.ui.input.nestedscroll/NestedScrollConnection { // androidx.compose.ui.input.nestedscroll/NestedScrollConnection|null[0]
     open fun onPostScroll(androidx.compose.ui.geometry/Offset, androidx.compose.ui.geometry/Offset, androidx.compose.ui.input.nestedscroll/NestedScrollSource): androidx.compose.ui.geometry/Offset // androidx.compose.ui.input.nestedscroll/NestedScrollConnection.onPostScroll|onPostScroll(androidx.compose.ui.geometry.Offset;androidx.compose.ui.geometry.Offset;androidx.compose.ui.input.nestedscroll.NestedScrollSource){}[0]
     open fun onPreScroll(androidx.compose.ui.geometry/Offset, androidx.compose.ui.input.nestedscroll/NestedScrollSource): androidx.compose.ui.geometry/Offset // androidx.compose.ui.input.nestedscroll/NestedScrollConnection.onPreScroll|onPreScroll(androidx.compose.ui.geometry.Offset;androidx.compose.ui.input.nestedscroll.NestedScrollSource){}[0]
@@ -369,7 +352,6 @@
     abstract fun onRotaryScrollEvent(androidx.compose.ui.input.rotary/RotaryScrollEvent): kotlin/Boolean // androidx.compose.ui.input.rotary/RotaryInputModifierNode.onRotaryScrollEvent|onRotaryScrollEvent(androidx.compose.ui.input.rotary.RotaryScrollEvent){}[0]
 }
 abstract interface androidx.compose.ui.input/InputModeManager { // androidx.compose.ui.input/InputModeManager|null[0]
-    abstract fun requestInputMode(androidx.compose.ui.input/InputMode): kotlin/Boolean // androidx.compose.ui.input/InputModeManager.requestInputMode|requestInputMode(androidx.compose.ui.input.InputMode){}[0]
     abstract val inputMode // androidx.compose.ui.input/InputModeManager.inputMode|{}inputMode[0]
         abstract fun <get-inputMode>(): androidx.compose.ui.input/InputMode // androidx.compose.ui.input/InputModeManager.inputMode.<get-inputMode>|<get-inputMode>(){}[0]
 }
@@ -602,9 +584,6 @@
         abstract fun <#A2: kotlin/Any?> (androidx.compose.ui.modifier/ModifierLocal<#A2>).<get-current>(): #A2 // androidx.compose.ui.modifier/ModifierLocalReadScope.current.<get-current>|<get-current>@androidx.compose.ui.modifier.ModifierLocal<0:0>(){0§<kotlin.Any?>}[0]
 }
 abstract interface androidx.compose.ui.node/ComposeUiNode { // androidx.compose.ui.node/ComposeUiNode|null[0]
-    abstract var compositeKeyHash // androidx.compose.ui.node/ComposeUiNode.compositeKeyHash|{}compositeKeyHash[0]
-        abstract fun <get-compositeKeyHash>(): kotlin/Int // androidx.compose.ui.node/ComposeUiNode.compositeKeyHash.<get-compositeKeyHash>|<get-compositeKeyHash>(){}[0]
-        abstract fun <set-compositeKeyHash>(kotlin/Int) // androidx.compose.ui.node/ComposeUiNode.compositeKeyHash.<set-compositeKeyHash>|<set-compositeKeyHash>(kotlin.Int){}[0]
     abstract var compositionLocalMap // androidx.compose.ui.node/ComposeUiNode.compositionLocalMap|{}compositionLocalMap[0]
         abstract fun <get-compositionLocalMap>(): androidx.compose.runtime/CompositionLocalMap // androidx.compose.ui.node/ComposeUiNode.compositionLocalMap.<get-compositionLocalMap>|<get-compositionLocalMap>(){}[0]
         abstract fun <set-compositionLocalMap>(androidx.compose.runtime/CompositionLocalMap) // androidx.compose.ui.node/ComposeUiNode.compositionLocalMap.<set-compositionLocalMap>|<set-compositionLocalMap>(androidx.compose.runtime.CompositionLocalMap){}[0]
@@ -626,8 +605,6 @@
     final object Companion { // androidx.compose.ui.node/ComposeUiNode.Companion|null[0]
         final val Constructor // androidx.compose.ui.node/ComposeUiNode.Companion.Constructor|{}Constructor[0]
             final fun <get-Constructor>(): kotlin/Function0<androidx.compose.ui.node/ComposeUiNode> // androidx.compose.ui.node/ComposeUiNode.Companion.Constructor.<get-Constructor>|<get-Constructor>(){}[0]
-        final val SetCompositeKeyHash // androidx.compose.ui.node/ComposeUiNode.Companion.SetCompositeKeyHash|{}SetCompositeKeyHash[0]
-            final fun <get-SetCompositeKeyHash>(): kotlin/Function2<androidx.compose.ui.node/ComposeUiNode, kotlin/Int, kotlin/Unit> // androidx.compose.ui.node/ComposeUiNode.Companion.SetCompositeKeyHash.<get-SetCompositeKeyHash>|<get-SetCompositeKeyHash>(){}[0]
         final val SetDensity // androidx.compose.ui.node/ComposeUiNode.Companion.SetDensity|{}SetDensity[0]
             final fun <get-SetDensity>(): kotlin/Function2<androidx.compose.ui.node/ComposeUiNode, androidx.compose.ui.unit/Density, kotlin/Unit> // androidx.compose.ui.node/ComposeUiNode.Companion.SetDensity.<get-SetDensity>|<get-SetDensity>(){}[0]
         final val SetLayoutDirection // androidx.compose.ui.node/ComposeUiNode.Companion.SetLayoutDirection|{}SetLayoutDirection[0]
@@ -689,9 +666,6 @@
         abstract fun <get-semanticsOwner>(): androidx.compose.ui.semantics/SemanticsOwner // androidx.compose.ui.node/RootForTest.semanticsOwner.<get-semanticsOwner>|<get-semanticsOwner>(){}[0]
     abstract val textInputService // androidx.compose.ui.node/RootForTest.textInputService|{}textInputService[0]
         abstract fun <get-textInputService>(): androidx.compose.ui.text.input/TextInputService // androidx.compose.ui.node/RootForTest.textInputService.<get-textInputService>|<get-textInputService>(){}[0]
-    open fun forceAccessibilityForTesting(kotlin/Boolean) // androidx.compose.ui.node/RootForTest.forceAccessibilityForTesting|forceAccessibilityForTesting(kotlin.Boolean){}[0]
-    open fun measureAndLayoutForTest() // androidx.compose.ui.node/RootForTest.measureAndLayoutForTest|measureAndLayoutForTest(){}[0]
-    open fun setAccessibilityEventBatchIntervalMillis(kotlin/Long) // androidx.compose.ui.node/RootForTest.setAccessibilityEventBatchIntervalMillis|setAccessibilityEventBatchIntervalMillis(kotlin.Long){}[0]
 }
 abstract interface androidx.compose.ui.node/SemanticsModifierNode : androidx.compose.ui.node/DelegatableNode { // androidx.compose.ui.node/SemanticsModifierNode|null[0]
     abstract fun (androidx.compose.ui.semantics/SemanticsPropertyReceiver).applySemantics() // androidx.compose.ui.node/SemanticsModifierNode.applySemantics|applySemantics@androidx.compose.ui.semantics.SemanticsPropertyReceiver(){}[0]
@@ -780,7 +754,6 @@
     abstract val isWindowFocused // androidx.compose.ui.platform/WindowInfo.isWindowFocused|{}isWindowFocused[0]
         abstract fun <get-isWindowFocused>(): kotlin/Boolean // androidx.compose.ui.platform/WindowInfo.isWindowFocused.<get-isWindowFocused>|<get-isWindowFocused>(){}[0]
     open val keyboardModifiers // androidx.compose.ui.platform/WindowInfo.keyboardModifiers|{}keyboardModifiers[0]
-        open fun <get-keyboardModifiers>(): androidx.compose.ui.input.pointer/PointerKeyboardModifiers // androidx.compose.ui.platform/WindowInfo.keyboardModifiers.<get-keyboardModifiers>|<get-keyboardModifiers>(){}[0]
 }
 abstract interface androidx.compose.ui.semantics/SemanticsModifier : androidx.compose.ui/Modifier.Element { // androidx.compose.ui.semantics/SemanticsModifier|null[0]
     abstract val semanticsConfiguration // androidx.compose.ui.semantics/SemanticsModifier.semanticsConfiguration|{}semanticsConfiguration[0]
@@ -797,7 +770,6 @@
 abstract interface androidx.compose.ui/Modifier { // androidx.compose.ui/Modifier|null[0]
     abstract class Node : androidx.compose.ui.node/DelegatableNode { // androidx.compose.ui/Modifier.Node|null[0]
         constructor <init>() // androidx.compose.ui/Modifier.Node.<init>|<init>(){}[0]
-        final fun sideEffect(kotlin/Function0<kotlin/Unit>) // androidx.compose.ui/Modifier.Node.sideEffect|sideEffect(kotlin.Function0<kotlin.Unit>){}[0]
         final val coroutineScope // androidx.compose.ui/Modifier.Node.coroutineScope|{}coroutineScope[0]
             final fun <get-coroutineScope>(): kotlinx.coroutines/CoroutineScope // androidx.compose.ui/Modifier.Node.coroutineScope.<get-coroutineScope>|<get-coroutineScope>(){}[0]
         final var isAttached // androidx.compose.ui/Modifier.Node.isAttached|{}isAttached[0]
@@ -870,27 +842,6 @@
     final val label // androidx.compose.ui.semantics/AccessibilityAction.label|{}label[0]
         final fun <get-label>(): kotlin/String? // androidx.compose.ui.semantics/AccessibilityAction.label.<get-label>|<get-label>(){}[0]
 }
-final class androidx.compose.ui.autofill/AutofillNode { // androidx.compose.ui.autofill/AutofillNode|null[0]
-    constructor <init>(kotlin.collections/List<androidx.compose.ui.autofill/AutofillType> =..., androidx.compose.ui.geometry/Rect? =..., kotlin/Function1<kotlin/String, kotlin/Unit>?) // androidx.compose.ui.autofill/AutofillNode.<init>|<init>(kotlin.collections.List<androidx.compose.ui.autofill.AutofillType>;androidx.compose.ui.geometry.Rect?;kotlin.Function1<kotlin.String,kotlin.Unit>?){}[0]
-    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.ui.autofill/AutofillNode.equals|equals(kotlin.Any?){}[0]
-    final fun hashCode(): kotlin/Int // androidx.compose.ui.autofill/AutofillNode.hashCode|hashCode(){}[0]
-    final val autofillTypes // androidx.compose.ui.autofill/AutofillNode.autofillTypes|{}autofillTypes[0]
-        final fun <get-autofillTypes>(): kotlin.collections/List<androidx.compose.ui.autofill/AutofillType> // androidx.compose.ui.autofill/AutofillNode.autofillTypes.<get-autofillTypes>|<get-autofillTypes>(){}[0]
-    final val id // androidx.compose.ui.autofill/AutofillNode.id|{}id[0]
-        final fun <get-id>(): kotlin/Int // androidx.compose.ui.autofill/AutofillNode.id.<get-id>|<get-id>(){}[0]
-    final val onFill // androidx.compose.ui.autofill/AutofillNode.onFill|{}onFill[0]
-        final fun <get-onFill>(): kotlin/Function1<kotlin/String, kotlin/Unit>? // androidx.compose.ui.autofill/AutofillNode.onFill.<get-onFill>|<get-onFill>(){}[0]
-    final var boundingBox // androidx.compose.ui.autofill/AutofillNode.boundingBox|{}boundingBox[0]
-        final fun <get-boundingBox>(): androidx.compose.ui.geometry/Rect? // androidx.compose.ui.autofill/AutofillNode.boundingBox.<get-boundingBox>|<get-boundingBox>(){}[0]
-        final fun <set-boundingBox>(androidx.compose.ui.geometry/Rect?) // androidx.compose.ui.autofill/AutofillNode.boundingBox.<set-boundingBox>|<set-boundingBox>(androidx.compose.ui.geometry.Rect?){}[0]
-}
-final class androidx.compose.ui.autofill/AutofillTree { // androidx.compose.ui.autofill/AutofillTree|null[0]
-    constructor <init>() // androidx.compose.ui.autofill/AutofillTree.<init>|<init>(){}[0]
-    final fun performAutofill(kotlin/Int, kotlin/String): kotlin/Unit? // androidx.compose.ui.autofill/AutofillTree.performAutofill|performAutofill(kotlin.Int;kotlin.String){}[0]
-    final fun plusAssign(androidx.compose.ui.autofill/AutofillNode) // androidx.compose.ui.autofill/AutofillTree.plusAssign|plusAssign(androidx.compose.ui.autofill.AutofillNode){}[0]
-    final val children // androidx.compose.ui.autofill/AutofillTree.children|{}children[0]
-        final fun <get-children>(): kotlin.collections/MutableMap<kotlin/Int, androidx.compose.ui.autofill/AutofillNode> // androidx.compose.ui.autofill/AutofillTree.children.<get-children>|<get-children>(){}[0]
-}
 final class androidx.compose.ui.draganddrop/DragAndDropEvent { // androidx.compose.ui.draganddrop/DragAndDropEvent|null[0]
     constructor <init>() // androidx.compose.ui.draganddrop/DragAndDropEvent.<init>|<init>(){}[0]
 }
@@ -944,8 +895,6 @@
     final fun captureFocus(): kotlin/Boolean // androidx.compose.ui.focus/FocusRequester.captureFocus|captureFocus(){}[0]
     final fun freeFocus(): kotlin/Boolean // androidx.compose.ui.focus/FocusRequester.freeFocus|freeFocus(){}[0]
     final fun requestFocus() // androidx.compose.ui.focus/FocusRequester.requestFocus|requestFocus(){}[0]
-    final fun restoreFocusedChild(): kotlin/Boolean // androidx.compose.ui.focus/FocusRequester.restoreFocusedChild|restoreFocusedChild(){}[0]
-    final fun saveFocusedChild(): kotlin/Boolean // androidx.compose.ui.focus/FocusRequester.saveFocusedChild|saveFocusedChild(){}[0]
     final object Companion { // androidx.compose.ui.focus/FocusRequester.Companion|null[0]
         final fun createRefs(): androidx.compose.ui.focus/FocusRequester.Companion.FocusRequesterFactory // androidx.compose.ui.focus/FocusRequester.Companion.createRefs|createRefs(){}[0]
         final object FocusRequesterFactory { // androidx.compose.ui.focus/FocusRequester.Companion.FocusRequesterFactory|null[0]
@@ -966,8 +915,6 @@
             final fun component8(): androidx.compose.ui.focus/FocusRequester // androidx.compose.ui.focus/FocusRequester.Companion.FocusRequesterFactory.component8|component8(){}[0]
             final fun component9(): androidx.compose.ui.focus/FocusRequester // androidx.compose.ui.focus/FocusRequester.Companion.FocusRequesterFactory.component9|component9(){}[0]
         }
-        final val Cancel // androidx.compose.ui.focus/FocusRequester.Companion.Cancel|{}Cancel[0]
-            final fun <get-Cancel>(): androidx.compose.ui.focus/FocusRequester // androidx.compose.ui.focus/FocusRequester.Companion.Cancel.<get-Cancel>|<get-Cancel>(){}[0]
         final val Default // androidx.compose.ui.focus/FocusRequester.Companion.Default|{}Default[0]
             final fun <get-Default>(): androidx.compose.ui.focus/FocusRequester // androidx.compose.ui.focus/FocusRequester.Companion.Default.<get-Default>|<get-Default>(){}[0]
     }
@@ -1109,14 +1056,6 @@
         final fun <get-positionChange>(): kotlin/Boolean // androidx.compose.ui.input.pointer/ConsumedData.positionChange.<get-positionChange>|<get-positionChange>(){}[0]
         final fun <set-positionChange>(kotlin/Boolean) // androidx.compose.ui.input.pointer/ConsumedData.positionChange.<set-positionChange>|<set-positionChange>(kotlin.Boolean){}[0]
 }
-final class androidx.compose.ui.input.pointer/HistoricalChange { // androidx.compose.ui.input.pointer/HistoricalChange|null[0]
-    constructor <init>(kotlin/Long, androidx.compose.ui.geometry/Offset) // androidx.compose.ui.input.pointer/HistoricalChange.<init>|<init>(kotlin.Long;androidx.compose.ui.geometry.Offset){}[0]
-    final fun toString(): kotlin/String // androidx.compose.ui.input.pointer/HistoricalChange.toString|toString(){}[0]
-    final val position // androidx.compose.ui.input.pointer/HistoricalChange.position|{}position[0]
-        final fun <get-position>(): androidx.compose.ui.geometry/Offset // androidx.compose.ui.input.pointer/HistoricalChange.position.<get-position>|<get-position>(){}[0]
-    final val uptimeMillis // androidx.compose.ui.input.pointer/HistoricalChange.uptimeMillis|{}uptimeMillis[0]
-        final fun <get-uptimeMillis>(): kotlin/Long // androidx.compose.ui.input.pointer/HistoricalChange.uptimeMillis.<get-uptimeMillis>|<get-uptimeMillis>(){}[0]
-}
 final class androidx.compose.ui.input.pointer/PointerEvent { // androidx.compose.ui.input.pointer/PointerEvent|null[0]
     constructor <init>(kotlin.collections/List<androidx.compose.ui.input.pointer/PointerInputChange>) // androidx.compose.ui.input.pointer/PointerEvent.<init>|<init>(kotlin.collections.List<androidx.compose.ui.input.pointer.PointerInputChange>){}[0]
     final fun component1(): kotlin.collections/List<androidx.compose.ui.input.pointer/PointerInputChange> // androidx.compose.ui.input.pointer/PointerEvent.component1|component1(){}[0]
@@ -1143,14 +1082,10 @@
     constructor <init>(androidx.compose.ui.input.pointer/PointerId, kotlin/Long, androidx.compose.ui.geometry/Offset, kotlin/Boolean, kotlin/Long, androidx.compose.ui.geometry/Offset, kotlin/Boolean, kotlin/Boolean, androidx.compose.ui.input.pointer/PointerType =..., androidx.compose.ui.geometry/Offset =...) // androidx.compose.ui.input.pointer/PointerInputChange.<init>|<init>(androidx.compose.ui.input.pointer.PointerId;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;kotlin.Boolean;androidx.compose.ui.input.pointer.PointerType;androidx.compose.ui.geometry.Offset){}[0]
     final fun consume() // androidx.compose.ui.input.pointer/PointerInputChange.consume|consume(){}[0]
     final fun copy(androidx.compose.ui.input.pointer/PointerId =..., kotlin/Long =..., androidx.compose.ui.geometry/Offset =..., kotlin/Boolean =..., kotlin/Float =..., kotlin/Long =..., androidx.compose.ui.geometry/Offset =..., kotlin/Boolean =..., androidx.compose.ui.input.pointer/PointerType =..., androidx.compose.ui.geometry/Offset =...): androidx.compose.ui.input.pointer/PointerInputChange // androidx.compose.ui.input.pointer/PointerInputChange.copy|copy(androidx.compose.ui.input.pointer.PointerId;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;kotlin.Float;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;androidx.compose.ui.input.pointer.PointerType;androidx.compose.ui.geometry.Offset){}[0]
-    final fun copy(androidx.compose.ui.input.pointer/PointerId =..., kotlin/Long =..., androidx.compose.ui.geometry/Offset =..., kotlin/Boolean =..., kotlin/Float =..., kotlin/Long =..., androidx.compose.ui.geometry/Offset =..., kotlin/Boolean =..., androidx.compose.ui.input.pointer/PointerType =..., kotlin.collections/List<androidx.compose.ui.input.pointer/HistoricalChange> =..., androidx.compose.ui.geometry/Offset =...): androidx.compose.ui.input.pointer/PointerInputChange // androidx.compose.ui.input.pointer/PointerInputChange.copy|copy(androidx.compose.ui.input.pointer.PointerId;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;kotlin.Float;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;androidx.compose.ui.input.pointer.PointerType;kotlin.collections.List<androidx.compose.ui.input.pointer.HistoricalChange>;androidx.compose.ui.geometry.Offset){}[0]
     final fun copy(androidx.compose.ui.input.pointer/PointerId =..., kotlin/Long =..., androidx.compose.ui.geometry/Offset =..., kotlin/Boolean =..., kotlin/Long =..., androidx.compose.ui.geometry/Offset =..., kotlin/Boolean =..., androidx.compose.ui.input.pointer/ConsumedData =..., androidx.compose.ui.input.pointer/PointerType =...): androidx.compose.ui.input.pointer/PointerInputChange // androidx.compose.ui.input.pointer/PointerInputChange.copy|copy(androidx.compose.ui.input.pointer.PointerId;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;androidx.compose.ui.input.pointer.ConsumedData;androidx.compose.ui.input.pointer.PointerType){}[0]
     final fun copy(androidx.compose.ui.input.pointer/PointerId =..., kotlin/Long =..., androidx.compose.ui.geometry/Offset =..., kotlin/Boolean =..., kotlin/Long =..., androidx.compose.ui.geometry/Offset =..., kotlin/Boolean =..., androidx.compose.ui.input.pointer/ConsumedData, androidx.compose.ui.input.pointer/PointerType =..., androidx.compose.ui.geometry/Offset =...): androidx.compose.ui.input.pointer/PointerInputChange // androidx.compose.ui.input.pointer/PointerInputChange.copy|copy(androidx.compose.ui.input.pointer.PointerId;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;androidx.compose.ui.input.pointer.ConsumedData;androidx.compose.ui.input.pointer.PointerType;androidx.compose.ui.geometry.Offset){}[0]
     final fun copy(androidx.compose.ui.input.pointer/PointerId =..., kotlin/Long =..., androidx.compose.ui.geometry/Offset =..., kotlin/Boolean =..., kotlin/Long =..., androidx.compose.ui.geometry/Offset =..., kotlin/Boolean =..., androidx.compose.ui.input.pointer/PointerType =..., androidx.compose.ui.geometry/Offset =...): androidx.compose.ui.input.pointer/PointerInputChange // androidx.compose.ui.input.pointer/PointerInputChange.copy|copy(androidx.compose.ui.input.pointer.PointerId;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;androidx.compose.ui.input.pointer.PointerType;androidx.compose.ui.geometry.Offset){}[0]
-    final fun copy(androidx.compose.ui.input.pointer/PointerId =..., kotlin/Long =..., androidx.compose.ui.geometry/Offset =..., kotlin/Boolean =..., kotlin/Long =..., androidx.compose.ui.geometry/Offset =..., kotlin/Boolean =..., androidx.compose.ui.input.pointer/PointerType =..., kotlin.collections/List<androidx.compose.ui.input.pointer/HistoricalChange>, androidx.compose.ui.geometry/Offset =...): androidx.compose.ui.input.pointer/PointerInputChange // androidx.compose.ui.input.pointer/PointerInputChange.copy|copy(androidx.compose.ui.input.pointer.PointerId;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;kotlin.Long;androidx.compose.ui.geometry.Offset;kotlin.Boolean;androidx.compose.ui.input.pointer.PointerType;kotlin.collections.List<androidx.compose.ui.input.pointer.HistoricalChange>;androidx.compose.ui.geometry.Offset){}[0]
     final fun toString(): kotlin/String // androidx.compose.ui.input.pointer/PointerInputChange.toString|toString(){}[0]
-    final val historical // androidx.compose.ui.input.pointer/PointerInputChange.historical|{}historical[0]
-        final fun <get-historical>(): kotlin.collections/List<androidx.compose.ui.input.pointer/HistoricalChange> // androidx.compose.ui.input.pointer/PointerInputChange.historical.<get-historical>|<get-historical>(){}[0]
     final val id // androidx.compose.ui.input.pointer/PointerInputChange.id|{}id[0]
         final fun <get-id>(): androidx.compose.ui.input.pointer/PointerId // androidx.compose.ui.input.pointer/PointerInputChange.id.<get-id>|<get-id>(){}[0]
     final val isConsumed // androidx.compose.ui.input.pointer/PointerInputChange.isConsumed|{}isConsumed[0]
@@ -1516,46 +1451,6 @@
     final fun <get-RootGroupName>(): kotlin/String // androidx.compose.ui.graphics.vector/RootGroupName.<get-RootGroupName>|<get-RootGroupName>(){}[0]
 final const val androidx.compose.ui.graphics/DefaultCameraDistance // androidx.compose.ui.graphics/DefaultCameraDistance|{}DefaultCameraDistance[0]
     final fun <get-DefaultCameraDistance>(): kotlin/Float // androidx.compose.ui.graphics/DefaultCameraDistance.<get-DefaultCameraDistance>|<get-DefaultCameraDistance>(){}[0]
-final enum class androidx.compose.ui.autofill/AutofillType : kotlin/Enum<androidx.compose.ui.autofill/AutofillType> { // androidx.compose.ui.autofill/AutofillType|null[0]
-    enum entry AddressAuxiliaryDetails // androidx.compose.ui.autofill/AutofillType.AddressAuxiliaryDetails|null[0]
-    enum entry AddressCountry // androidx.compose.ui.autofill/AutofillType.AddressCountry|null[0]
-    enum entry AddressLocality // androidx.compose.ui.autofill/AutofillType.AddressLocality|null[0]
-    enum entry AddressRegion // androidx.compose.ui.autofill/AutofillType.AddressRegion|null[0]
-    enum entry AddressStreet // androidx.compose.ui.autofill/AutofillType.AddressStreet|null[0]
-    enum entry BirthDateDay // androidx.compose.ui.autofill/AutofillType.BirthDateDay|null[0]
-    enum entry BirthDateFull // androidx.compose.ui.autofill/AutofillType.BirthDateFull|null[0]
-    enum entry BirthDateMonth // androidx.compose.ui.autofill/AutofillType.BirthDateMonth|null[0]
-    enum entry BirthDateYear // androidx.compose.ui.autofill/AutofillType.BirthDateYear|null[0]
-    enum entry CreditCardExpirationDate // androidx.compose.ui.autofill/AutofillType.CreditCardExpirationDate|null[0]
-    enum entry CreditCardExpirationDay // androidx.compose.ui.autofill/AutofillType.CreditCardExpirationDay|null[0]
-    enum entry CreditCardExpirationMonth // androidx.compose.ui.autofill/AutofillType.CreditCardExpirationMonth|null[0]
-    enum entry CreditCardExpirationYear // androidx.compose.ui.autofill/AutofillType.CreditCardExpirationYear|null[0]
-    enum entry CreditCardNumber // androidx.compose.ui.autofill/AutofillType.CreditCardNumber|null[0]
-    enum entry CreditCardSecurityCode // androidx.compose.ui.autofill/AutofillType.CreditCardSecurityCode|null[0]
-    enum entry EmailAddress // androidx.compose.ui.autofill/AutofillType.EmailAddress|null[0]
-    enum entry Gender // androidx.compose.ui.autofill/AutofillType.Gender|null[0]
-    enum entry NewPassword // androidx.compose.ui.autofill/AutofillType.NewPassword|null[0]
-    enum entry NewUsername // androidx.compose.ui.autofill/AutofillType.NewUsername|null[0]
-    enum entry Password // androidx.compose.ui.autofill/AutofillType.Password|null[0]
-    enum entry PersonFirstName // androidx.compose.ui.autofill/AutofillType.PersonFirstName|null[0]
-    enum entry PersonFullName // androidx.compose.ui.autofill/AutofillType.PersonFullName|null[0]
-    enum entry PersonLastName // androidx.compose.ui.autofill/AutofillType.PersonLastName|null[0]
-    enum entry PersonMiddleInitial // androidx.compose.ui.autofill/AutofillType.PersonMiddleInitial|null[0]
-    enum entry PersonMiddleName // androidx.compose.ui.autofill/AutofillType.PersonMiddleName|null[0]
-    enum entry PersonNamePrefix // androidx.compose.ui.autofill/AutofillType.PersonNamePrefix|null[0]
-    enum entry PersonNameSuffix // androidx.compose.ui.autofill/AutofillType.PersonNameSuffix|null[0]
-    enum entry PhoneCountryCode // androidx.compose.ui.autofill/AutofillType.PhoneCountryCode|null[0]
-    enum entry PhoneNumber // androidx.compose.ui.autofill/AutofillType.PhoneNumber|null[0]
-    enum entry PhoneNumberDevice // androidx.compose.ui.autofill/AutofillType.PhoneNumberDevice|null[0]
-    enum entry PhoneNumberNational // androidx.compose.ui.autofill/AutofillType.PhoneNumberNational|null[0]
-    enum entry PostalAddress // androidx.compose.ui.autofill/AutofillType.PostalAddress|null[0]
-    enum entry PostalCode // androidx.compose.ui.autofill/AutofillType.PostalCode|null[0]
-    enum entry PostalCodeExtended // androidx.compose.ui.autofill/AutofillType.PostalCodeExtended|null[0]
-    enum entry SmsOtpCode // androidx.compose.ui.autofill/AutofillType.SmsOtpCode|null[0]
-    enum entry Username // androidx.compose.ui.autofill/AutofillType.Username|null[0]
-    final fun valueOf(kotlin/String): androidx.compose.ui.autofill/AutofillType // androidx.compose.ui.autofill/AutofillType.valueOf|valueOf#static(kotlin.String){}[0]
-    final fun values(): kotlin/Array<androidx.compose.ui.autofill/AutofillType> // androidx.compose.ui.autofill/AutofillType.values|values#static(){}[0]
-}
 final enum class androidx.compose.ui.input.pointer/PointerEventPass : kotlin/Enum<androidx.compose.ui.input.pointer/PointerEventPass> { // androidx.compose.ui.input.pointer/PointerEventPass|null[0]
     enum entry Final // androidx.compose.ui.input.pointer/PointerEventPass.Final|null[0]
     enum entry Initial // androidx.compose.ui.input.pointer/PointerEventPass.Initial|null[0]
@@ -1582,8 +1477,6 @@
 final fun (androidx.compose.ui.focus/FocusRequesterModifierNode).androidx.compose.ui.focus/captureFocus(): kotlin/Boolean // androidx.compose.ui.focus/captureFocus|captureFocus@androidx.compose.ui.focus.FocusRequesterModifierNode(){}[0]
 final fun (androidx.compose.ui.focus/FocusRequesterModifierNode).androidx.compose.ui.focus/freeFocus(): kotlin/Boolean // androidx.compose.ui.focus/freeFocus|[email protected](){}[0]
 final fun (androidx.compose.ui.focus/FocusRequesterModifierNode).androidx.compose.ui.focus/requestFocus(): kotlin/Boolean // androidx.compose.ui.focus/requestFocus|requestFocus@androidx.compose.ui.focus.FocusRequesterModifierNode(){}[0]
-final fun (androidx.compose.ui.focus/FocusRequesterModifierNode).androidx.compose.ui.focus/restoreFocusedChild(): kotlin/Boolean // androidx.compose.ui.focus/restoreFocusedChild|restoreFocusedChild@androidx.compose.ui.focus.FocusRequesterModifierNode(){}[0]
-final fun (androidx.compose.ui.focus/FocusRequesterModifierNode).androidx.compose.ui.focus/saveFocusedChild(): kotlin/Boolean // androidx.compose.ui.focus/saveFocusedChild|saveFocusedChild@androidx.compose.ui.focus.FocusRequesterModifierNode(){}[0]
 final fun (androidx.compose.ui.geometry/Size).androidx.compose.ui.layout/div(androidx.compose.ui.layout/ScaleFactor): androidx.compose.ui.geometry/Size // androidx.compose.ui.layout/div|[email protected](androidx.compose.ui.layout.ScaleFactor){}[0]
 final fun (androidx.compose.ui.geometry/Size).androidx.compose.ui.layout/times(androidx.compose.ui.layout/ScaleFactor): androidx.compose.ui.geometry/Size // androidx.compose.ui.layout/times|[email protected](androidx.compose.ui.layout.ScaleFactor){}[0]
 final fun (androidx.compose.ui.input.pointer.util/VelocityTracker).androidx.compose.ui.input.pointer.util/addPointerInputChange(androidx.compose.ui.input.pointer/PointerInputChange) // androidx.compose.ui.input.pointer.util/addPointerInputChange|addPointerInputChange@androidx.compose.ui.input.pointer.util.VelocityTracker(androidx.compose.ui.input.pointer.PointerInputChange){}[0]
@@ -1646,7 +1539,6 @@
 final fun (androidx.compose.ui.semantics/SemanticsPropertyReceiver).androidx.compose.ui.semantics/heading() // androidx.compose.ui.semantics/heading|[email protected](){}[0]
 final fun (androidx.compose.ui.semantics/SemanticsPropertyReceiver).androidx.compose.ui.semantics/indexForKey(kotlin/Function1<kotlin/Any, kotlin/Int>) // androidx.compose.ui.semantics/indexForKey|indexForKey@androidx.compose.ui.semantics.SemanticsPropertyReceiver(kotlin.Function1<kotlin.Any,kotlin.Int>){}[0]
 final fun (androidx.compose.ui.semantics/SemanticsPropertyReceiver).androidx.compose.ui.semantics/insertTextAtCursor(kotlin/String? =..., kotlin/Function1<androidx.compose.ui.text/AnnotatedString, kotlin/Boolean>?) // androidx.compose.ui.semantics/insertTextAtCursor|insertTextAtCursor@androidx.compose.ui.semantics.SemanticsPropertyReceiver(kotlin.String?;kotlin.Function1<androidx.compose.ui.text.AnnotatedString,kotlin.Boolean>?){}[0]
-final fun (androidx.compose.ui.semantics/SemanticsPropertyReceiver).androidx.compose.ui.semantics/invisibleToUser() // androidx.compose.ui.semantics/invisibleToUser|invisibleToUser@androidx.compose.ui.semantics.SemanticsPropertyReceiver(){}[0]
 final fun (androidx.compose.ui.semantics/SemanticsPropertyReceiver).androidx.compose.ui.semantics/onClick(kotlin/String? =..., kotlin/Function0<kotlin/Boolean>?) // androidx.compose.ui.semantics/onClick|[email protected](kotlin.String?;kotlin.Function0<kotlin.Boolean>?){}[0]
 final fun (androidx.compose.ui.semantics/SemanticsPropertyReceiver).androidx.compose.ui.semantics/onImeAction(androidx.compose.ui.text.input/ImeAction, kotlin/String? =..., kotlin/Function0<kotlin/Boolean>?) // androidx.compose.ui.semantics/onImeAction|onImeAction@androidx.compose.ui.semantics.SemanticsPropertyReceiver(androidx.compose.ui.text.input.ImeAction;kotlin.String?;kotlin.Function0<kotlin.Boolean>?){}[0]
 final fun (androidx.compose.ui.semantics/SemanticsPropertyReceiver).androidx.compose.ui.semantics/onLongClick(kotlin/String? =..., kotlin/Function0<kotlin/Boolean>?) // androidx.compose.ui.semantics/onLongClick|onLongClick@androidx.compose.ui.semantics.SemanticsPropertyReceiver(kotlin.String?;kotlin.Function0<kotlin.Boolean>?){}[0]
@@ -1688,7 +1580,6 @@
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.focus/focusOrder(kotlin/Function1<androidx.compose.ui.focus/FocusOrder, kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.ui.focus/focusOrder|[email protected](kotlin.Function1<androidx.compose.ui.focus.FocusOrder,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.focus/focusProperties(kotlin/Function1<androidx.compose.ui.focus/FocusProperties, kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.ui.focus/focusProperties|[email protected](kotlin.Function1<androidx.compose.ui.focus.FocusProperties,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.focus/focusRequester(androidx.compose.ui.focus/FocusRequester): androidx.compose.ui/Modifier // androidx.compose.ui.focus/focusRequester|[email protected](androidx.compose.ui.focus.FocusRequester){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.ui.focus/focusRestorer(kotlin/Function0<androidx.compose.ui.focus/FocusRequester>? =...): androidx.compose.ui/Modifier // androidx.compose.ui.focus/focusRestorer|[email protected](kotlin.Function0<androidx.compose.ui.focus.FocusRequester>?){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.focus/focusTarget(): androidx.compose.ui/Modifier // androidx.compose.ui.focus/focusTarget|[email protected](){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.focus/onFocusChanged(kotlin/Function1<androidx.compose.ui.focus/FocusState, kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.ui.focus/onFocusChanged|[email protected](kotlin.Function1<androidx.compose.ui.focus.FocusState,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.focus/onFocusEvent(kotlin/Function1<androidx.compose.ui.focus/FocusState, kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.ui.focus/onFocusEvent|[email protected](kotlin.Function1<androidx.compose.ui.focus.FocusState,kotlin.Unit>){}[0]
@@ -1698,9 +1589,7 @@
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.graphics/graphicsLayer(kotlin/Float =..., kotlin/Float =..., kotlin/Float =..., kotlin/Float =..., kotlin/Float =..., kotlin/Float =..., kotlin/Float =..., kotlin/Float =..., kotlin/Float =..., kotlin/Float =..., androidx.compose.ui.graphics/TransformOrigin =..., androidx.compose.ui.graphics/Shape =..., kotlin/Boolean =..., androidx.compose.ui.graphics/RenderEffect? =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/Color =..., androidx.compose.ui.graphics/CompositingStrategy =...): androidx.compose.ui/Modifier // androidx.compose.ui.graphics/graphicsLayer|[email protected](kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float;kotlin.Float;androidx.compose.ui.graphics.TransformOrigin;androidx.compose.ui.graphics.Shape;kotlin.Boolean;androidx.compose.ui.graphics.RenderEffect?;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.Color;androidx.compose.ui.graphics.CompositingStrategy){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.graphics/graphicsLayer(kotlin/Function1<androidx.compose.ui.graphics/GraphicsLayerScope, kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.ui.graphics/graphicsLayer|[email protected](kotlin.Function1<androidx.compose.ui.graphics.GraphicsLayerScope,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.graphics/toolingGraphicsLayer(): androidx.compose.ui/Modifier // androidx.compose.ui.graphics/toolingGraphicsLayer|[email protected](){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.ui.input.key/onInterceptKeyBeforeSoftKeyboard(kotlin/Function1<androidx.compose.ui.input.key/KeyEvent, kotlin/Boolean>): androidx.compose.ui/Modifier // androidx.compose.ui.input.key/onInterceptKeyBeforeSoftKeyboard|[email protected](kotlin.Function1<androidx.compose.ui.input.key.KeyEvent,kotlin.Boolean>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.input.key/onKeyEvent(kotlin/Function1<androidx.compose.ui.input.key/KeyEvent, kotlin/Boolean>): androidx.compose.ui/Modifier // androidx.compose.ui.input.key/onKeyEvent|[email protected](kotlin.Function1<androidx.compose.ui.input.key.KeyEvent,kotlin.Boolean>){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.ui.input.key/onPreInterceptKeyBeforeSoftKeyboard(kotlin/Function1<androidx.compose.ui.input.key/KeyEvent, kotlin/Boolean>): androidx.compose.ui/Modifier // androidx.compose.ui.input.key/onPreInterceptKeyBeforeSoftKeyboard|[email protected](kotlin.Function1<androidx.compose.ui.input.key.KeyEvent,kotlin.Boolean>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.input.key/onPreviewKeyEvent(kotlin/Function1<androidx.compose.ui.input.key/KeyEvent, kotlin/Boolean>): androidx.compose.ui/Modifier // androidx.compose.ui.input.key/onPreviewKeyEvent|[email protected](kotlin.Function1<androidx.compose.ui.input.key.KeyEvent,kotlin.Boolean>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.input.nestedscroll/nestedScroll(androidx.compose.ui.input.nestedscroll/NestedScrollConnection, androidx.compose.ui.input.nestedscroll/NestedScrollDispatcher? =...): androidx.compose.ui/Modifier // androidx.compose.ui.input.nestedscroll/nestedScroll|[email protected](androidx.compose.ui.input.nestedscroll.NestedScrollConnection;androidx.compose.ui.input.nestedscroll.NestedScrollDispatcher?){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.input.pointer/pointerHoverIcon(androidx.compose.ui.input.pointer/PointerIcon, kotlin/Boolean =...): androidx.compose.ui/Modifier // androidx.compose.ui.input.pointer/pointerHoverIcon|[email protected](androidx.compose.ui.input.pointer.PointerIcon;kotlin.Boolean){}[0]
@@ -1716,16 +1605,11 @@
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.layout/onGloballyPositioned(kotlin/Function1<androidx.compose.ui.layout/LayoutCoordinates, kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.ui.layout/onGloballyPositioned|[email protected](kotlin.Function1<androidx.compose.ui.layout.LayoutCoordinates,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.layout/onPlaced(kotlin/Function1<androidx.compose.ui.layout/LayoutCoordinates, kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.ui.layout/onPlaced|[email protected](kotlin.Function1<androidx.compose.ui.layout.LayoutCoordinates,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.layout/onSizeChanged(kotlin/Function1<androidx.compose.ui.unit/IntSize, kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.ui.layout/onSizeChanged|[email protected](kotlin.Function1<androidx.compose.ui.unit.IntSize,kotlin.Unit>){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.ui.modifier/modifierLocalConsumer(kotlin/Function1<androidx.compose.ui.modifier/ModifierLocalReadScope, kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.ui.modifier/modifierLocalConsumer|[email protected](kotlin.Function1<androidx.compose.ui.modifier.ModifierLocalReadScope,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.platform/inspectableWrapper(kotlin/Function1<androidx.compose.ui.platform/InspectorInfo, kotlin/Unit>, androidx.compose.ui/Modifier): androidx.compose.ui/Modifier // androidx.compose.ui.platform/inspectableWrapper|[email protected](kotlin.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit>;androidx.compose.ui.Modifier){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.platform/testTag(kotlin/String): androidx.compose.ui/Modifier // androidx.compose.ui.platform/testTag|[email protected](kotlin.String){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.semantics/clearAndSetSemantics(kotlin/Function1<androidx.compose.ui.semantics/SemanticsPropertyReceiver, kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.ui.semantics/clearAndSetSemantics|[email protected](kotlin.Function1<androidx.compose.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui.semantics/semantics(kotlin/Boolean =..., kotlin/Function1<androidx.compose.ui.semantics/SemanticsPropertyReceiver, kotlin/Unit>): androidx.compose.ui/Modifier // androidx.compose.ui.semantics/semantics|[email protected](kotlin.Boolean;kotlin.Function1<androidx.compose.ui.semantics.SemanticsPropertyReceiver,kotlin.Unit>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui/composed(kotlin/Function1<androidx.compose.ui.platform/InspectorInfo, kotlin/Unit> =..., kotlin/Function1<androidx.compose.ui/Modifier, androidx.compose.ui/Modifier>): androidx.compose.ui/Modifier // androidx.compose.ui/composed|[email protected](kotlin.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit>;kotlin.Function1<androidx.compose.ui.Modifier,androidx.compose.ui.Modifier>){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.ui/composed(kotlin/String, kotlin/Any?, kotlin/Any?, kotlin/Any?, kotlin/Function1<androidx.compose.ui.platform/InspectorInfo, kotlin/Unit> =..., kotlin/Function1<androidx.compose.ui/Modifier, androidx.compose.ui/Modifier>): androidx.compose.ui/Modifier // androidx.compose.ui/composed|[email protected](kotlin.String;kotlin.Any?;kotlin.Any?;kotlin.Any?;kotlin.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit>;kotlin.Function1<androidx.compose.ui.Modifier,androidx.compose.ui.Modifier>){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.ui/composed(kotlin/String, kotlin/Any?, kotlin/Any?, kotlin/Function1<androidx.compose.ui.platform/InspectorInfo, kotlin/Unit> =..., kotlin/Function1<androidx.compose.ui/Modifier, androidx.compose.ui/Modifier>): androidx.compose.ui/Modifier // androidx.compose.ui/composed|[email protected](kotlin.String;kotlin.Any?;kotlin.Any?;kotlin.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit>;kotlin.Function1<androidx.compose.ui.Modifier,androidx.compose.ui.Modifier>){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.ui/composed(kotlin/String, kotlin/Any?, kotlin/Function1<androidx.compose.ui.platform/InspectorInfo, kotlin/Unit> =..., kotlin/Function1<androidx.compose.ui/Modifier, androidx.compose.ui/Modifier>): androidx.compose.ui/Modifier // androidx.compose.ui/composed|[email protected](kotlin.String;kotlin.Any?;kotlin.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit>;kotlin.Function1<androidx.compose.ui.Modifier,androidx.compose.ui.Modifier>){}[0]
-final fun (androidx.compose.ui/Modifier).androidx.compose.ui/composed(kotlin/String, kotlin/Array<out kotlin/Any?>..., kotlin/Function1<androidx.compose.ui.platform/InspectorInfo, kotlin/Unit> =..., kotlin/Function1<androidx.compose.ui/Modifier, androidx.compose.ui/Modifier>): androidx.compose.ui/Modifier // androidx.compose.ui/composed|[email protected](kotlin.String;kotlin.Array<out|kotlin.Any?>...;kotlin.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit>;kotlin.Function1<androidx.compose.ui.Modifier,androidx.compose.ui.Modifier>){}[0]
 final fun (androidx.compose.ui/Modifier).androidx.compose.ui/zIndex(kotlin/Float): androidx.compose.ui/Modifier // androidx.compose.ui/zIndex|[email protected](kotlin.Float){}[0]
 final fun <#A: androidx.compose.ui.node/ObserverModifierNode & androidx.compose.ui/Modifier.Node> (#A).androidx.compose.ui.node/observeReads(kotlin/Function0<kotlin/Unit>) // androidx.compose.ui.node/observeReads|observeReads@0:0(kotlin.Function0<kotlin.Unit>){0§<androidx.compose.ui.Modifier.Node&androidx.compose.ui.node.ObserverModifierNode>}[0]
 final fun <#A: androidx.compose.ui.node/TraversableNode> (#A).androidx.compose.ui.node/findNearestAncestor(): #A? // androidx.compose.ui.node/findNearestAncestor|findNearestAncestor@0:0(){0§<androidx.compose.ui.node.TraversableNode>}[0]
@@ -1734,7 +1618,6 @@
 final fun <#A: androidx.compose.ui.node/TraversableNode> (#A).androidx.compose.ui.node/traverseDescendants(kotlin/Function1<#A, androidx.compose.ui.node/TraversableNode.Companion.TraverseDescendantsAction>) // androidx.compose.ui.node/traverseDescendants|traverseDescendants@0:0(kotlin.Function1<0:0,androidx.compose.ui.node.TraversableNode.Companion.TraverseDescendantsAction>){0§<androidx.compose.ui.node.TraversableNode>}[0]
 final fun <#A: kotlin/Any?> (androidx.compose.ui.node/CompositionLocalConsumerModifierNode).androidx.compose.ui.node/currentValueOf(androidx.compose.runtime/CompositionLocal<#A>): #A // androidx.compose.ui.node/currentValueOf|currentValueOf@androidx.compose.ui.node.CompositionLocalConsumerModifierNode(androidx.compose.runtime.CompositionLocal<0:0>){0§<kotlin.Any?>}[0]
 final fun <#A: kotlin/Any?> (androidx.compose.ui.semantics/SemanticsConfiguration).androidx.compose.ui.semantics/getOrNull(androidx.compose.ui.semantics/SemanticsPropertyKey<#A>): #A? // androidx.compose.ui.semantics/getOrNull|[email protected](androidx.compose.ui.semantics.SemanticsPropertyKey<0:0>){0§<kotlin.Any?>}[0]
-final fun <#A: kotlin/Any?> (androidx.compose.ui/Modifier).androidx.compose.ui.modifier/modifierLocalProvider(androidx.compose.ui.modifier/ProvidableModifierLocal<#A>, kotlin/Function0<#A>): androidx.compose.ui/Modifier // androidx.compose.ui.modifier/modifierLocalProvider|[email protected](androidx.compose.ui.modifier.ProvidableModifierLocal<0:0>;kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]
 final fun <#A: kotlin/Any?> androidx.compose.ui.modifier/modifierLocalMapOf(androidx.compose.ui.modifier/ModifierLocal<#A>): androidx.compose.ui.modifier/ModifierLocalMap // androidx.compose.ui.modifier/modifierLocalMapOf|modifierLocalMapOf(androidx.compose.ui.modifier.ModifierLocal<0:0>){0§<kotlin.Any?>}[0]
 final fun <#A: kotlin/Any?> androidx.compose.ui.modifier/modifierLocalMapOf(kotlin/Pair<androidx.compose.ui.modifier/ModifierLocal<#A>, #A>): androidx.compose.ui.modifier/ModifierLocalMap // androidx.compose.ui.modifier/modifierLocalMapOf|modifierLocalMapOf(kotlin.Pair<androidx.compose.ui.modifier.ModifierLocal<0:0>,0:0>){0§<kotlin.Any?>}[0]
 final fun <#A: kotlin/Any?> androidx.compose.ui.modifier/modifierLocalOf(kotlin/Function0<#A>): androidx.compose.ui.modifier/ProvidableModifierLocal<#A> // androidx.compose.ui.modifier/modifierLocalOf|modifierLocalOf(kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]
@@ -1771,7 +1654,6 @@
 final fun androidx.compose.ui.modifier/modifierLocalMapOf(kotlin/Array<out androidx.compose.ui.modifier/ModifierLocal<*>>...): androidx.compose.ui.modifier/ModifierLocalMap // androidx.compose.ui.modifier/modifierLocalMapOf|modifierLocalMapOf(kotlin.Array<out|androidx.compose.ui.modifier.ModifierLocal<*>>...){}[0]
 final fun androidx.compose.ui.modifier/modifierLocalMapOf(kotlin/Array<out kotlin/Pair<androidx.compose.ui.modifier/ModifierLocal<*>, kotlin/Any>>...): androidx.compose.ui.modifier/ModifierLocalMap // androidx.compose.ui.modifier/modifierLocalMapOf|modifierLocalMapOf(kotlin.Array<out|kotlin.Pair<androidx.compose.ui.modifier.ModifierLocal<*>,kotlin.Any>>...){}[0]
 final fun androidx.compose.ui.modifier/modifierLocalMapOf(kotlin/Pair<androidx.compose.ui.modifier/ModifierLocal<*>, kotlin/Any>, kotlin/Pair<androidx.compose.ui.modifier/ModifierLocal<*>, kotlin/Any>, kotlin/Array<out kotlin/Pair<androidx.compose.ui.modifier/ModifierLocal<*>, kotlin/Any>>...): androidx.compose.ui.modifier/ModifierLocalMap // androidx.compose.ui.modifier/modifierLocalMapOf|modifierLocalMapOf(kotlin.Pair<androidx.compose.ui.modifier.ModifierLocal<*>,kotlin.Any>;kotlin.Pair<androidx.compose.ui.modifier.ModifierLocal<*>,kotlin.Any>;kotlin.Array<out|kotlin.Pair<androidx.compose.ui.modifier.ModifierLocal<*>,kotlin.Any>>...){}[0]
-final fun androidx.compose.ui.platform/InterceptPlatformTextInput(androidx.compose.ui.platform/PlatformTextInputInterceptor, kotlin/Function0<kotlin/Unit>) // androidx.compose.ui.platform/InterceptPlatformTextInput|InterceptPlatformTextInput(androidx.compose.ui.platform.PlatformTextInputInterceptor;kotlin.Function0<kotlin.Unit>){}[0]
 final fun androidx.compose.ui.state/ToggleableState(kotlin/Boolean): androidx.compose.ui.state/ToggleableState // androidx.compose.ui.state/ToggleableState|ToggleableState(kotlin.Boolean){}[0]
 final fun androidx.compose.ui.text/rememberTextMeasurer(kotlin/Int =...): androidx.compose.ui.text/TextMeasurer // androidx.compose.ui.text/rememberTextMeasurer|rememberTextMeasurer(kotlin.Int){}[0]
 final fun androidx.compose.ui.window/Dialog(kotlin/Function0<kotlin/Unit>, androidx.compose.ui.window/DialogProperties =..., kotlin/Function0<kotlin/Unit>) // androidx.compose.ui.window/Dialog|Dialog(kotlin.Function0<kotlin.Unit>;androidx.compose.ui.window.DialogProperties;kotlin.Function0<kotlin.Unit>){}[0]
@@ -1867,8 +1749,6 @@
         final fun <get-ImeAction>(): androidx.compose.ui.semantics/SemanticsPropertyKey<androidx.compose.ui.text.input/ImeAction> // androidx.compose.ui.semantics/SemanticsProperties.ImeAction.<get-ImeAction>|<get-ImeAction>(){}[0]
     final val IndexForKey // androidx.compose.ui.semantics/SemanticsProperties.IndexForKey|{}IndexForKey[0]
         final fun <get-IndexForKey>(): androidx.compose.ui.semantics/SemanticsPropertyKey<kotlin/Function1<kotlin/Any, kotlin/Int>> // androidx.compose.ui.semantics/SemanticsProperties.IndexForKey.<get-IndexForKey>|<get-IndexForKey>(){}[0]
-    final val InvisibleToUser // androidx.compose.ui.semantics/SemanticsProperties.InvisibleToUser|{}InvisibleToUser[0]
-        final fun <get-InvisibleToUser>(): androidx.compose.ui.semantics/SemanticsPropertyKey<kotlin/Unit> // androidx.compose.ui.semantics/SemanticsProperties.InvisibleToUser.<get-InvisibleToUser>|<get-InvisibleToUser>(){}[0]
     final val IsContainer // androidx.compose.ui.semantics/SemanticsProperties.IsContainer|{}IsContainer[0]
         final fun <get-IsContainer>(): androidx.compose.ui.semantics/SemanticsPropertyKey<kotlin/Boolean> // androidx.compose.ui.semantics/SemanticsProperties.IsContainer.<get-IsContainer>|<get-IsContainer>(){}[0]
     final val IsDialog // androidx.compose.ui.semantics/SemanticsProperties.IsDialog|{}IsDialog[0]
@@ -2009,10 +1889,6 @@
     final fun (androidx.compose.ui.layout/Measurable).<get-layoutId>(): kotlin/Any? // androidx.compose.ui.layout/layoutId.<get-layoutId>|<get-layoutId>@androidx.compose.ui.layout.Measurable(){}[0]
 final val androidx.compose.ui.platform/LocalAccessibilityManager // androidx.compose.ui.platform/LocalAccessibilityManager|{}LocalAccessibilityManager[0]
     final fun <get-LocalAccessibilityManager>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.ui.platform/AccessibilityManager?> // androidx.compose.ui.platform/LocalAccessibilityManager.<get-LocalAccessibilityManager>|<get-LocalAccessibilityManager>(){}[0]
-final val androidx.compose.ui.platform/LocalAutofill // androidx.compose.ui.platform/LocalAutofill|{}LocalAutofill[0]
-    final fun <get-LocalAutofill>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.ui.autofill/Autofill?> // androidx.compose.ui.platform/LocalAutofill.<get-LocalAutofill>|<get-LocalAutofill>(){}[0]
-final val androidx.compose.ui.platform/LocalAutofillTree // androidx.compose.ui.platform/LocalAutofillTree|{}LocalAutofillTree[0]
-    final fun <get-LocalAutofillTree>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.ui.autofill/AutofillTree> // androidx.compose.ui.platform/LocalAutofillTree.<get-LocalAutofillTree>|<get-LocalAutofillTree>(){}[0]
 final val androidx.compose.ui.platform/LocalClipboardManager // androidx.compose.ui.platform/LocalClipboardManager|{}LocalClipboardManager[0]
     final fun <get-LocalClipboardManager>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.ui.platform/ClipboardManager> // androidx.compose.ui.platform/LocalClipboardManager.<get-LocalClipboardManager>|<get-LocalClipboardManager>(){}[0]
 final val androidx.compose.ui.platform/LocalDensity // androidx.compose.ui.platform/LocalDensity|{}LocalDensity[0]
@@ -2049,15 +1925,6 @@
     final fun <get-LocalWindowInfo>(): androidx.compose.runtime/ProvidableCompositionLocal<androidx.compose.ui.platform/WindowInfo> // androidx.compose.ui.platform/LocalWindowInfo.<get-LocalWindowInfo>|<get-LocalWindowInfo>(){}[0]
 final val androidx.compose.ui.platform/NoInspectorInfo // androidx.compose.ui.platform/NoInspectorInfo|{}NoInspectorInfo[0]
     final fun <get-NoInspectorInfo>(): kotlin/Function1<androidx.compose.ui.platform/InspectorInfo, kotlin/Unit> // androidx.compose.ui.platform/NoInspectorInfo.<get-NoInspectorInfo>|<get-NoInspectorInfo>(){}[0]
-final value class <#A: kotlin/Any?> androidx.compose.ui/SessionMutex { // androidx.compose.ui/SessionMutex|null[0]
-    constructor <init>() // androidx.compose.ui/SessionMutex.<init>|<init>(){}[0]
-    final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.ui/SessionMutex.equals|equals(kotlin.Any?){}[0]
-    final fun hashCode(): kotlin/Int // androidx.compose.ui/SessionMutex.hashCode|hashCode(){}[0]
-    final fun toString(): kotlin/String // androidx.compose.ui/SessionMutex.toString|toString(){}[0]
-    final suspend fun <#A1: kotlin/Any?> withSessionCancellingPrevious(kotlin/Function1<kotlinx.coroutines/CoroutineScope, #A>, kotlin.coroutines/SuspendFunction1<#A, #A1>): #A1 // androidx.compose.ui/SessionMutex.withSessionCancellingPrevious|withSessionCancellingPrevious(kotlin.Function1<kotlinx.coroutines.CoroutineScope,1:0>;kotlin.coroutines.SuspendFunction1<1:0,0:0>){0§<kotlin.Any?>}[0]
-    final val currentSession // androidx.compose.ui/SessionMutex.currentSession|{}currentSession[0]
-        final fun <get-currentSession>(): #A? // androidx.compose.ui/SessionMutex.currentSession.<get-currentSession>|<get-currentSession>(){}[0]
-}
 final value class androidx.compose.ui.draw/BlurredEdgeTreatment { // androidx.compose.ui.draw/BlurredEdgeTreatment|null[0]
     constructor <init>(androidx.compose.ui.graphics/Shape?) // androidx.compose.ui.draw/BlurredEdgeTreatment.<init>|<init>(androidx.compose.ui.graphics.Shape?){}[0]
     final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.ui.draw/BlurredEdgeTreatment.equals|equals(kotlin.Any?){}[0]
@@ -2079,10 +1946,6 @@
     final object Companion { // androidx.compose.ui.focus/FocusDirection.Companion|null[0]
         final val Down // androidx.compose.ui.focus/FocusDirection.Companion.Down|<get-Down>(){}[0]
             final fun <get-Down>(): androidx.compose.ui.focus/FocusDirection // androidx.compose.ui.focus/FocusDirection.Companion.Down.<get-Down>|<get-Down>(){}[0]
-        final val Enter // androidx.compose.ui.focus/FocusDirection.Companion.Enter|<get-Enter>(){}[0]
-            final fun <get-Enter>(): androidx.compose.ui.focus/FocusDirection // androidx.compose.ui.focus/FocusDirection.Companion.Enter.<get-Enter>|<get-Enter>(){}[0]
-        final val Exit // androidx.compose.ui.focus/FocusDirection.Companion.Exit|<get-Exit>(){}[0]
-            final fun <get-Exit>(): androidx.compose.ui.focus/FocusDirection // androidx.compose.ui.focus/FocusDirection.Companion.Exit.<get-Exit>|<get-Exit>(){}[0]
         final val Left // androidx.compose.ui.focus/FocusDirection.Companion.Left|<get-Left>(){}[0]
             final fun <get-Left>(): androidx.compose.ui.focus/FocusDirection // androidx.compose.ui.focus/FocusDirection.Companion.Left.<get-Left>|<get-Left>(){}[0]
         final val Next // androidx.compose.ui.focus/FocusDirection.Companion.Next|<get-Next>(){}[0]
@@ -2753,8 +2616,6 @@
             final fun <get-Drag>(): androidx.compose.ui.input.nestedscroll/NestedScrollSource // androidx.compose.ui.input.nestedscroll/NestedScrollSource.Companion.Drag.<get-Drag>|<get-Drag>(){}[0]
         final val Fling // androidx.compose.ui.input.nestedscroll/NestedScrollSource.Companion.Fling|{}Fling[0]
             final fun <get-Fling>(): androidx.compose.ui.input.nestedscroll/NestedScrollSource // androidx.compose.ui.input.nestedscroll/NestedScrollSource.Companion.Fling.<get-Fling>|<get-Fling>(){}[0]
-        final val Relocate // androidx.compose.ui.input.nestedscroll/NestedScrollSource.Companion.Relocate|<get-Relocate>(){}[0]
-            final fun <get-Relocate>(): androidx.compose.ui.input.nestedscroll/NestedScrollSource // androidx.compose.ui.input.nestedscroll/NestedScrollSource.Companion.Relocate.<get-Relocate>|<get-Relocate>(){}[0]
         final val SideEffect // androidx.compose.ui.input.nestedscroll/NestedScrollSource.Companion.SideEffect|<get-SideEffect>(){}[0]
             final fun <get-SideEffect>(): androidx.compose.ui.input.nestedscroll/NestedScrollSource // androidx.compose.ui.input.nestedscroll/NestedScrollSource.Companion.SideEffect.<get-SideEffect>|<get-SideEffect>(){}[0]
         final val UserInput // androidx.compose.ui.input.nestedscroll/NestedScrollSource.Companion.UserInput|<get-UserInput>(){}[0]
@@ -2884,12 +2745,6 @@
             final fun <get-Tab>(): androidx.compose.ui.semantics/Role // androidx.compose.ui.semantics/Role.Companion.Tab.<get-Tab>|<get-Tab>(){}[0]
     }
 }
-final var androidx.compose.ui.input.pointer.util/VelocityTrackerAddPointsFix // androidx.compose.ui.input.pointer.util/VelocityTrackerAddPointsFix|<get-VelocityTrackerAddPointsFix>(){}[0]
-    final fun <get-VelocityTrackerAddPointsFix>(): kotlin/Boolean // androidx.compose.ui.input.pointer.util/VelocityTrackerAddPointsFix.<get-VelocityTrackerAddPointsFix>|<get-VelocityTrackerAddPointsFix>(){}[0]
-    final fun <set-VelocityTrackerAddPointsFix>(kotlin/Boolean) // androidx.compose.ui.input.pointer.util/VelocityTrackerAddPointsFix.<set-VelocityTrackerAddPointsFix>|<set-VelocityTrackerAddPointsFix>(kotlin.Boolean){}[0]
-final var androidx.compose.ui.input.pointer.util/VelocityTrackerStrategyUseImpulse // androidx.compose.ui.input.pointer.util/VelocityTrackerStrategyUseImpulse|<get-VelocityTrackerStrategyUseImpulse>(){}[0]
-    final fun <get-VelocityTrackerStrategyUseImpulse>(): kotlin/Boolean // androidx.compose.ui.input.pointer.util/VelocityTrackerStrategyUseImpulse.<get-VelocityTrackerStrategyUseImpulse>|<get-VelocityTrackerStrategyUseImpulse>(){}[0]
-    final fun <set-VelocityTrackerStrategyUseImpulse>(kotlin/Boolean) // androidx.compose.ui.input.pointer.util/VelocityTrackerStrategyUseImpulse.<set-VelocityTrackerStrategyUseImpulse>|<set-VelocityTrackerStrategyUseImpulse>(kotlin.Boolean){}[0]
 final var androidx.compose.ui.platform/isDebugInspectorInfoEnabled // androidx.compose.ui.platform/isDebugInspectorInfoEnabled|{}isDebugInspectorInfoEnabled[0]
     final fun <get-isDebugInspectorInfoEnabled>(): kotlin/Boolean // androidx.compose.ui.platform/isDebugInspectorInfoEnabled.<get-isDebugInspectorInfoEnabled>|<get-isDebugInspectorInfoEnabled>(){}[0]
     final fun <set-isDebugInspectorInfoEnabled>(kotlin/Boolean) // androidx.compose.ui.platform/isDebugInspectorInfoEnabled.<set-isDebugInspectorInfoEnabled>|<set-isDebugInspectorInfoEnabled>(kotlin.Boolean){}[0]
@@ -3032,10 +2887,7 @@
 sealed interface androidx.compose.ui.draw/CacheDrawModifierNode : androidx.compose.ui.node/DrawModifierNode { // androidx.compose.ui.draw/CacheDrawModifierNode|null[0]
     abstract fun invalidateDrawCache() // androidx.compose.ui.draw/CacheDrawModifierNode.invalidateDrawCache|invalidateDrawCache(){}[0]
 }
-sealed interface androidx.compose.ui.focus/FocusTargetModifierNode : androidx.compose.ui.node/DelegatableNode { // androidx.compose.ui.focus/FocusTargetModifierNode|null[0]
-    abstract val focusState // androidx.compose.ui.focus/FocusTargetModifierNode.focusState|{}focusState[0]
-        abstract fun <get-focusState>(): androidx.compose.ui.focus/FocusState // androidx.compose.ui.focus/FocusTargetModifierNode.focusState.<get-focusState>|<get-focusState>(){}[0]
-}
+sealed interface androidx.compose.ui.focus/FocusTargetModifierNode : androidx.compose.ui.node/DelegatableNode // androidx.compose.ui.focus/FocusTargetModifierNode|null[0]
 sealed interface androidx.compose.ui.input.pointer/SuspendingPointerInputModifierNode : androidx.compose.ui.node/PointerInputModifierNode { // androidx.compose.ui.input.pointer/SuspendingPointerInputModifierNode|null[0]
     abstract fun resetPointerInputHandler() // androidx.compose.ui.input.pointer/SuspendingPointerInputModifierNode.resetPointerInputHandler|resetPointerInputHandler(){}[0]
     abstract var pointerInputHandler // androidx.compose.ui.input.pointer/SuspendingPointerInputModifierNode.pointerInputHandler|{}pointerInputHandler[0]
@@ -3049,6 +2901,3 @@
         abstract fun <get-lookaheadSize>(): androidx.compose.ui.unit/IntSize // androidx.compose.ui.layout/ApproachIntrinsicMeasureScope.lookaheadSize.<get-lookaheadSize>|<get-lookaheadSize>(){}[0]
 }
 sealed interface androidx.compose.ui.layout/ApproachMeasureScope : androidx.compose.ui.layout/ApproachIntrinsicMeasureScope, androidx.compose.ui.layout/MeasureScope // androidx.compose.ui.layout/ApproachMeasureScope|null[0]
-sealed interface androidx.compose.ui.node/InteroperableComposeUiNode { // androidx.compose.ui.node/InteroperableComposeUiNode|null[0]
-    abstract fun getInteropView(): kotlin/Any? // androidx.compose.ui.node/InteroperableComposeUiNode.getInteropView|getInteropView(){}[0]
-}
diff --git a/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/autofill/SemanticAutofillBenchmark.kt b/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/autofill/SemanticAutofillBenchmark.kt
new file mode 100644
index 0000000..336310f
--- /dev/null
+++ b/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/autofill/SemanticAutofillBenchmark.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.benchmark.autofill
+
+import androidx.benchmark.ExperimentalBenchmarkConfigApi
+import androidx.benchmark.MicrobenchmarkConfig
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.testutils.ComposeTestCase
+import androidx.compose.testutils.ToggleableTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.toggleStateBenchmarkCompose
+import androidx.compose.ui.ComposeUiFlags.isSemanticAutofillEnabled
+import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.test.filters.LargeTest
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@LargeTest
+@RunWith(Parameterized::class)
+class SemanticAutofillBenchmark(private val isAutofillEnabled: Boolean) {
+    @OptIn(ExperimentalComposeUiApi::class)
+    private val previousFlagValue = isSemanticAutofillEnabled
+
+    @OptIn(ExperimentalBenchmarkConfigApi::class)
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule(MicrobenchmarkConfig(traceAppTagEnabled = true))
+
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "Autofill enabled = {0}")
+        fun data(): Collection<Array<Any>> {
+            val testCases = mutableListOf<Array<Any>>()
+            // Add a `false` parameter here and run locally to compare Autofill off vs on
+            for (isAutofillEnabled in listOf(true)) {
+                testCases.add(arrayOf(isAutofillEnabled))
+            }
+            return testCases
+        }
+    }
+
+    @Test
+    fun runChangingAutofillTextBenchmark() {
+        @OptIn(ExperimentalComposeUiApi::class)
+        isSemanticAutofillEnabled = isAutofillEnabled
+
+        benchmarkRule.toggleStateBenchmarkCompose(
+            caseFactory = {
+                object : ComposeTestCase, ToggleableTestCase {
+                    private lateinit var state: MutableState<Boolean>
+
+                    @Composable
+                    override fun Content() {
+                        state = remember { mutableStateOf(false) }
+                        ChangingAutofillText(state = state)
+                    }
+
+                    override fun toggleState() {
+                        state.value = !state.value
+                    }
+                }
+            }
+        )
+
+        @OptIn(ExperimentalComposeUiApi::class)
+        isSemanticAutofillEnabled = previousFlagValue
+    }
+
+    @Test
+    fun runRemovableAutofillTextBenchmark() {
+        @OptIn(ExperimentalComposeUiApi::class)
+        isSemanticAutofillEnabled = isAutofillEnabled
+
+        benchmarkRule.toggleStateBenchmarkCompose(
+            caseFactory = {
+                object : ComposeTestCase, ToggleableTestCase {
+                    private lateinit var state: MutableState<Boolean>
+
+                    @Composable
+                    override fun Content() {
+                        state = remember { mutableStateOf(false) }
+                        RemovableAutofillText(state = state)
+                    }
+
+                    override fun toggleState() {
+                        state.value = !state.value
+                    }
+                }
+            }
+        )
+
+        @OptIn(ExperimentalComposeUiApi::class)
+        isSemanticAutofillEnabled = previousFlagValue
+    }
+
+    @Test
+    fun runChangingAutofillFocusBenchmark() {
+        @OptIn(ExperimentalComposeUiApi::class)
+        isSemanticAutofillEnabled = isAutofillEnabled
+
+        benchmarkRule.toggleStateBenchmarkCompose(
+            caseFactory = {
+                object : ComposeTestCase, ToggleableTestCase {
+                    private lateinit var state: MutableState<Boolean>
+
+                    @Composable
+                    override fun Content() {
+                        state = remember { mutableStateOf(false) }
+                        ChangingAutofillFocus(state = state)
+                    }
+
+                    override fun toggleState() {
+                        state.value = !state.value
+                    }
+                }
+            }
+        )
+
+        @OptIn(ExperimentalComposeUiApi::class)
+        isSemanticAutofillEnabled = previousFlagValue
+    }
+}
diff --git a/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/autofill/SemanticAutofillBenchmarkUtils.kt b/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/autofill/SemanticAutofillBenchmarkUtils.kt
new file mode 100644
index 0000000..898c1b2
--- /dev/null
+++ b/compose/ui/ui/benchmark/src/androidTest/java/androidx/compose/ui/benchmark/autofill/SemanticAutofillBenchmarkUtils.kt
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.benchmark.autofill
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.material.Text
+import androidx.compose.material.TextField
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.autofill.ContentDataType
+import androidx.compose.ui.autofill.ContentType
+import androidx.compose.ui.semantics.contentDataType
+import androidx.compose.ui.semantics.contentType
+import androidx.compose.ui.semantics.focused
+import androidx.compose.ui.semantics.semantics
+
+@Composable
+internal fun RemovableAutofillText(state: MutableState<Boolean>) {
+    Column {
+        Row {
+            if (state.value) {
+                TextField(
+                    value = data.title,
+                    onValueChange = {},
+                    label = { Text("Enter prefix here: ") },
+                    modifier =
+                        Modifier.semantics {
+                            contentType = ContentType.PersonNamePrefix
+                            contentDataType = ContentDataType.Text
+                        }
+                )
+            }
+            TextField(
+                value = data.firstName,
+                onValueChange = {},
+                label = { Text("Enter first name here: ") },
+                modifier =
+                    Modifier.semantics {
+                        contentType = ContentType.PersonFirstName
+                        contentDataType = ContentDataType.Text
+                    }
+            )
+            TextField(
+                value = data.lastName,
+                onValueChange = {},
+                label = { Text("Enter last name here: ") },
+                modifier =
+                    Modifier.semantics {
+                        contentType = ContentType.PersonLastName
+                        contentDataType = ContentDataType.Text
+                    }
+            )
+            if (state.value) {
+                TextField(
+                    value = data.middleName,
+                    onValueChange = {},
+                    label = { Text("Enter middle name here: ") },
+                    modifier =
+                        Modifier.semantics {
+                            contentType = ContentType.PersonMiddleName
+                            contentDataType = ContentDataType.Text
+                        }
+                )
+            }
+        }
+    }
+}
+
+@Composable
+internal fun ChangingAutofillText(state: MutableState<Boolean>) {
+    Column {
+        Row {
+            TextField(
+                value = if (state.value) data.title else dataFlipped.title,
+                onValueChange = {},
+                label = { Text("Enter prefix here: ") },
+                modifier =
+                    Modifier.semantics {
+                        contentType = ContentType.PersonNamePrefix
+                        contentDataType = ContentDataType.Text
+                    }
+            )
+            TextField(
+                value = if (state.value) data.firstName else dataFlipped.firstName,
+                onValueChange = {},
+                label = { Text("Enter first name here: ") },
+                modifier =
+                    Modifier.semantics {
+                        contentType = ContentType.PersonFirstName
+                        contentDataType = ContentDataType.Text
+                    }
+            )
+            TextField(
+                value = if (state.value) data.lastName else dataFlipped.lastName,
+                onValueChange = {},
+                label = { Text("Enter last name here: ") },
+                modifier =
+                    Modifier.semantics {
+                        contentType = ContentType.PersonLastName
+                        contentDataType = ContentDataType.Text
+                    }
+            )
+            TextField(
+                value = if (state.value) data.middleName else dataFlipped.middleName,
+                onValueChange = {},
+                label = { Text("Enter middle name here: ") },
+                modifier =
+                    Modifier.semantics {
+                        contentType = ContentType.PersonMiddleName
+                        contentDataType = ContentDataType.Text
+                    }
+            )
+        }
+    }
+}
+
+@Composable
+internal fun ChangingAutofillFocus(state: MutableState<Boolean>) {
+    Column {
+        Row {
+            TextField(
+                value = if (state.value) data.title else dataFlipped.title,
+                onValueChange = {},
+                label = { Text("Enter prefix here: ") },
+                modifier =
+                    Modifier.semantics {
+                        contentType = ContentType.PersonNamePrefix
+                        contentDataType = ContentDataType.Text
+                        focused = state.value
+                    }
+            )
+            TextField(
+                value = if (state.value) data.firstName else dataFlipped.firstName,
+                onValueChange = {},
+                label = { Text("Enter first name here: ") },
+                modifier =
+                    Modifier.semantics {
+                        contentType = ContentType.PersonFirstName
+                        contentDataType = ContentDataType.Text
+                    }
+            )
+            TextField(
+                value = if (state.value) data.lastName else dataFlipped.lastName,
+                onValueChange = {},
+                label = { Text("Enter last name here: ") },
+                modifier =
+                    Modifier.semantics {
+                        contentType = ContentType.PersonLastName
+                        contentDataType = ContentDataType.Text
+                        focused = state.value
+                    }
+            )
+            TextField(
+                value = if (state.value) data.middleName else dataFlipped.middleName,
+                onValueChange = {},
+                label = { Text("Enter middle name here: ") },
+                modifier =
+                    Modifier.semantics {
+                        contentType = ContentType.PersonMiddleName
+                        contentDataType = ContentDataType.Text
+                    }
+            )
+        }
+    }
+}
+
+internal data class PersonData(
+    var title: String = "",
+    var firstName: String = "",
+    var middleName: String = "",
+    var lastName: String = "",
+    var age: Int = 0,
+)
+
+internal val data =
+    PersonData(title = "Mr ", firstName = "John ", middleName = "Ace ", lastName = "Doe, ", age = 1)
+
+internal val dataFlipped =
+    PersonData(
+        title = "Ms ",
+        firstName = "Jane ",
+        middleName = "Art ",
+        lastName = "Deer, ",
+        age = 2
+    )
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/SimpleChatActivity.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/SimpleChatActivity.kt
index 7e69716..97d73a7 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/SimpleChatActivity.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/SimpleChatActivity.kt
@@ -76,6 +76,9 @@
 @Composable
 private fun SimpleChatPage() {
     val messages = remember { mutableStateListOf<Message>() }
+    for (i in 1..40) {
+        messages.add(Message("test msg $i", isReceived = i % 2 == 0))
+    }
     val listState = rememberLazyListState()
     val coroutineScope = rememberCoroutineScope()
     Scaffold(
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/autofill/AndroidAutofillManagerTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/autofill/AndroidAutofillManagerTest.kt
index 8c06ff3..d6ce34a 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/autofill/AndroidAutofillManagerTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/autofill/AndroidAutofillManagerTest.kt
@@ -29,6 +29,7 @@
 import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.LazyRow
 import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.verticalScroll
@@ -43,6 +44,7 @@
 import androidx.compose.ui.focus.FocusManager
 import androidx.compose.ui.focus.focusProperties
 import androidx.compose.ui.platform.LocalAutofillManager
+import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.semantics.contentDataType
@@ -71,6 +73,7 @@
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
 import org.mockito.kotlin.any
 import org.mockito.kotlin.clearInvocations
 import org.mockito.kotlin.mock
@@ -116,14 +119,16 @@
     @Test
     @SmallTest
     @SdkSuppress(minSdkVersion = 26)
-    fun autofillManager_empty() {
+    fun autofillManager_initialization() {
         val am: PlatformAutofillManager = mock()
         rule.setContent {
             (LocalAutofillManager.current as AndroidAutofillManager).platformAutofillManager = am
             Box(Modifier.semantics { contentType = ContentType.Username }.size(height, width))
         }
 
-        rule.runOnIdle { verifyNoMoreInteractions(am) }
+        // Upon initialization, we send `notifyViewVisibility` for all of the components that appear
+        // onscreen. For other tests, we'll call `clearInvocations(am)` to avoid testing this call.
+        rule.runOnIdle { verify(am, times(1)).notifyViewVisibilityChanged(any(), any(), eq(true)) }
     }
 
     @Test
@@ -491,6 +496,7 @@
                     .focusable()
             )
         }
+        clearInvocations(am)
 
         rule.onNodeWithTag("username").requestFocus()
 
@@ -557,6 +563,7 @@
             focusManager = LocalFocusManager.current
             Box(Modifier.semantics { testTag = "username" }.size(height, width).focusable())
         }
+        clearInvocations(am)
 
         rule.onNodeWithTag("username").requestFocus()
         rule.runOnIdle { focusManager.clearFocus() }
@@ -577,15 +584,20 @@
             Box(
                 modifier =
                     Modifier.then(if (isVisible) Modifier else Modifier.alpha(0f))
-                        .semantics { onAutofillText { true } }
+                        // visibility is related to commit, so we must have a contentType set
+                        .semantics { contentType = ContentType.Username }
                         .size(width, height)
                         .focusable()
             )
         }
 
+        clearInvocations(am)
+
         rule.runOnIdle { isVisible = false }
 
-        rule.runOnIdle { verify(am).notifyViewVisibilityChanged(any(), any(), any()) }
+        // After switching the flag, the autofill manager is then notified that the box has
+        // become transparent.
+        rule.runOnIdle { verify(am).notifyViewVisibilityChanged(any(), any(), eq(false)) }
     }
 
     @Ignore // TODO(b/383198004): Add support for notifyVisibilityChanged.
@@ -601,15 +613,55 @@
             Box(
                 modifier =
                     Modifier.then(if (isVisible) Modifier else Modifier.alpha(0f))
-                        .semantics { onAutofillText { true } }
+                        // visibility is related to commit, so we must have a contentType set
+                        .semantics { contentType = ContentType.Username }
                         .size(width, height)
                         .focusable()
             )
         }
 
+        clearInvocations(am)
+
         rule.runOnIdle { isVisible = true }
 
-        rule.runOnIdle { verify(am).notifyViewVisibilityChanged(any(), any(), any()) }
+        // After switching the flag, the autofill manager is then notified that the box has
+        // become opaque.
+        rule.runOnIdle { verify(am).notifyViewVisibilityChanged(any(), any(), eq(true)) }
+    }
+
+    @Test
+    @SmallTest
+    @SdkSuppress(minSdkVersion = 27)
+    fun autofillManager_notifyVisibilityChanged_lazyScroll() {
+        // Arrange.
+        val am: PlatformAutofillManager = mock()
+        lateinit var lazyListState: LazyListState
+
+        rule.setContent {
+            (LocalAutofillManager.current as AndroidAutofillManager).platformAutofillManager = am
+            lazyListState = rememberLazyListState()
+            with(LocalDensity.current) {
+                LazyRow(state = lazyListState, modifier = Modifier.size(10.toDp())) {
+                    items(2) {
+                        Box(
+                            Modifier.size(10.toDp())
+                                // visibility is related to commit, so we must have a contentType
+                                // set
+                                .semantics { contentType = ContentType.Username }
+                                .focusable()
+                        )
+                    }
+                }
+            }
+        }
+        clearInvocations(am)
+
+        // Act.
+        rule.runOnIdle { lazyListState.requestScrollToItem(1) }
+
+        // After scrolling, one element should be removed and one should be added.
+        rule.runOnIdle { verify(am).notifyViewVisibilityChanged(any(), any(), eq(false)) }
+        rule.runOnIdle { verify(am).notifyViewVisibilityChanged(any(), any(), eq(true)) }
     }
 
     @Test
@@ -710,6 +762,7 @@
                         .size(height, width)
             )
         }
+        clearInvocations(am)
 
         // `requestAutofill` is always called after an element is focused
         rule.onNodeWithTag(contextMenuTag).requestFocus()
@@ -733,9 +786,16 @@
             state = rememberLazyListState()
             (LocalAutofillManager.current as AndroidAutofillManager).platformAutofillManager = am
 
-            LazyColumn(Modifier.fillMaxWidth().height(50.dp), state) {
-                item { Box(Modifier.semantics { contentType = ContentType.Username }.size(10.dp)) }
-                items(count) { Box(Modifier.size(10.dp)) }
+            with(LocalDensity.current) {
+                LazyColumn(Modifier.fillMaxWidth().height(50.dp), state) {
+                    item {
+                        Box(
+                            Modifier.semantics { contentType = ContentType.Username }
+                                .size(10.toDp())
+                        )
+                    }
+                    items(count) { Box(Modifier.size(10.toDp())) }
+                }
             }
         }
 
@@ -756,9 +816,16 @@
             scrollState = rememberScrollState()
             (LocalAutofillManager.current as AndroidAutofillManager).platformAutofillManager = am
 
-            Column(Modifier.fillMaxWidth().height(50.dp).verticalScroll(scrollState)) {
-                Row { Box(Modifier.semantics { contentType = ContentType.Username }.size(10.dp)) }
-                repeat(50) { Box(Modifier.size(10.dp)) }
+            with(LocalDensity.current) {
+                Column(Modifier.fillMaxWidth().height(50.dp).verticalScroll(scrollState)) {
+                    Row {
+                        Box(
+                            Modifier.semantics { contentType = ContentType.Username }
+                                .size(10.toDp())
+                        )
+                    }
+                    repeat(50) { Box(Modifier.size(10.toDp())) }
+                }
             }
         }
 
@@ -779,13 +846,18 @@
             (LocalAutofillManager.current as AndroidAutofillManager).platformAutofillManager = am
             scrollState = rememberScrollState()
 
-            Column(Modifier.fillMaxWidth().height(50.dp).verticalScroll(scrollState)) {
-                if (autofillComponentsVisible) {
-                    Row {
-                        Box(Modifier.semantics { contentType = ContentType.Username }.size(10.dp))
+            with(LocalDensity.current) {
+                Column(Modifier.fillMaxWidth().height(50.dp).verticalScroll(scrollState)) {
+                    if (autofillComponentsVisible) {
+                        Row {
+                            Box(
+                                Modifier.semantics { contentType = ContentType.Username }
+                                    .size(10.toDp())
+                            )
+                        }
                     }
+                    repeat(50) { Box(Modifier.size(10.toDp())) }
                 }
-                repeat(50) { Box(Modifier.size(10.dp)) }
             }
         }
 
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/contentcapture/ContentCaptureTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/contentcapture/ContentCaptureTest.kt
index c484db1..e65a15d 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/contentcapture/ContentCaptureTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/contentcapture/ContentCaptureTest.kt
@@ -17,6 +17,7 @@
 package androidx.compose.ui.contentcapture
 
 import android.os.Build
+import android.os.Bundle
 import android.util.LongSparseArray
 import android.view.ViewStructure
 import android.view.translation.TranslationRequestValue
@@ -27,16 +28,22 @@
 import androidx.annotation.RequiresApi
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListState
+import androidx.compose.foundation.lazy.rememberLazyListState
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.AndroidComposeView
 import androidx.compose.ui.platform.LocalView
 import androidx.compose.ui.platform.coreshims.ContentCaptureSessionCompat
 import androidx.compose.ui.platform.coreshims.ViewStructureCompat
+import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.semantics.clearTextSubstitution
 import androidx.compose.ui.semantics.isShowingTextSubstitution
 import androidx.compose.ui.semantics.semantics
@@ -58,13 +65,18 @@
 import androidx.test.filters.SdkSuppress
 import com.google.common.truth.Truth.assertThat
 import java.util.function.Consumer
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.kotlin.any
 import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.atLeast
 import org.mockito.kotlin.clearInvocations
+import org.mockito.kotlin.doReturnConsecutively
 import org.mockito.kotlin.isNull
 import org.mockito.kotlin.mock
 import org.mockito.kotlin.times
@@ -96,9 +108,10 @@
         // Assert = verify the root node appeared.
         rule.runOnIdle {
             verify(contentCaptureSessionCompat).newVirtualViewStructure(any(), any())
-            verify(contentCaptureSessionCompat).notifyViewsAppeared(any())
+            verify(contentCaptureSessionCompat).notifyViewAppeared(any())
+            verify(contentCaptureSessionCompat).flush()
             verify(viewStructureCompat).setDimens(any(), any(), any(), any(), any(), any())
-            verify(viewStructureCompat).extras
+            verify(viewStructureCompat, times(1)).extras
             verify(viewStructureCompat).toViewStructure()
             verifyNoMoreInteractions(contentCaptureSessionCompat)
             verifyNoMoreInteractions(viewStructureCompat)
@@ -116,7 +129,9 @@
             androidComposeView.doOnDetach {
 
                 // Assert.
-                verify(contentCaptureSessionCompat).notifyViewsDisappeared(any())
+                verify(contentCaptureSessionCompat).newAutofillId(any())
+                verify(contentCaptureSessionCompat).notifyViewDisappeared(any())
+                verify(contentCaptureSessionCompat).flush()
                 verifyNoMoreInteractions(contentCaptureSessionCompat)
                 verifyNoMoreInteractions(viewStructureCompat)
             }
@@ -143,6 +158,10 @@
             }
         }
 
+        val bundle1 = Bundle()
+        val bundle2 = Bundle()
+        whenever(viewStructureCompat.extras).doReturnConsecutively(listOf(bundle1, bundle2))
+
         // Act.
         rule.runOnIdle { appeared = true }
         // TODO(b/272068594): After refactoring this code, ensure that we don't need to wait for two
@@ -159,15 +178,15 @@
                 assertThat(firstValue).isEqualTo("foo")
                 assertThat(secondValue).isEqualTo("bar")
             }
+            verify(viewStructureCompat, times(2)).extras
+            assertAdditionalIndices(bundle1, 0)
+            assertAdditionalIndices(bundle2, 1)
             with(argumentCaptor<String>()) {
                 verify(viewStructureCompat, times(1)).setId(anyInt(), isNull(), isNull(), capture())
                 assertThat(firstValue).isEqualTo("testTagFoo")
             }
             verify(contentCaptureSessionCompat, times(0)).notifyViewsDisappeared(any())
-            with(argumentCaptor<List<ViewStructure>>()) {
-                verify(contentCaptureSessionCompat, times(1)).notifyViewsAppeared(capture())
-                assertThat(firstValue.count()).isEqualTo(2)
-            }
+            verify(contentCaptureSessionCompat, times(2)).notifyViewAppeared(any())
         }
     }
 
@@ -199,10 +218,7 @@
 
         // Assert.
         rule.runOnIdle {
-            with(argumentCaptor<LongArray>()) {
-                verify(contentCaptureSessionCompat, times(1)).notifyViewsDisappeared(capture())
-                assertThat(firstValue.count()).isEqualTo(3)
-            }
+            verify(contentCaptureSessionCompat, times(3)).notifyViewDisappeared(any())
             verify(contentCaptureSessionCompat, times(0)).notifyViewsAppeared(any())
         }
     }
@@ -244,14 +260,8 @@
 
         // Assert.
         rule.runOnIdle {
-            with(argumentCaptor<LongArray>()) {
-                verify(contentCaptureSessionCompat, times(1)).notifyViewsDisappeared(capture())
-                assertThat(firstValue.count()).isEqualTo(3)
-            }
-            with(argumentCaptor<List<ViewStructure>>()) {
-                verify(contentCaptureSessionCompat, times(1)).notifyViewsAppeared(capture())
-                assertThat(firstValue.count()).isEqualTo(3)
-            }
+            verify(contentCaptureSessionCompat, times(3)).notifyViewDisappeared(any())
+            verify(contentCaptureSessionCompat, times(3)).notifyViewAppeared(any())
         }
     }
 
@@ -270,7 +280,6 @@
             }
         }
 
-        // Act.
         rule.runOnIdle { appeared = true }
 
         // TODO(b/272068594): After refactoring this code, ensure that we don't need to wait for two
@@ -280,16 +289,16 @@
             rule.waitForIdle()
         }
 
-        // Assert.
         rule.runOnIdle {
-            verify(contentCaptureSessionCompat, times(0)).notifyViewsDisappeared(any())
-            with(argumentCaptor<List<ViewStructure>>()) {
-                verify(contentCaptureSessionCompat, times(1)).notifyViewsAppeared(capture())
-                assertThat(firstValue.count()).isEqualTo(1)
-            }
+            verify(contentCaptureSessionCompat, times(1)).newAutofillId(any())
+            verify(contentCaptureSessionCompat, times(1)).newVirtualViewStructure(any(), any())
+            verify(contentCaptureSessionCompat, times(1)).notifyViewAppeared(any())
+            verify(contentCaptureSessionCompat, times(1)).flush()
+            verifyNoMoreInteractions(contentCaptureSessionCompat)
             clearInvocations(contentCaptureSessionCompat)
         }
 
+        // Act.
         rule.runOnIdle { appeared = false }
 
         // TODO(b/272068594): After refactoring this code, ensure that we don't need to wait for two
@@ -301,12 +310,193 @@
 
         // Assert.
         rule.runOnIdle {
-            verify(contentCaptureSessionCompat, times(0)).notifyViewsDisappeared(any())
-            verify(contentCaptureSessionCompat, times(0)).notifyViewsAppeared(any())
+            verify(contentCaptureSessionCompat, times(1)).newAutofillId(any())
+            verify(contentCaptureSessionCompat, times(1)).notifyViewDisappeared(any())
+            verify(contentCaptureSessionCompat, times(1)).flush()
+            verifyNoMoreInteractions(contentCaptureSessionCompat)
         }
     }
 
     @Test
+    fun testSendContentCaptureSemanticsStructureChangeEvents_lazyList_onStart() = runBlocking {
+        // Arrange.
+        rule.setContentWithContentCaptureEnabled(retainInteractionsDuringInitialization = true) {
+            ContentCaptureTestLazyList(rememberLazyListState())
+        }
+
+        // Act.
+        rule.waitForIdle()
+        repeat(2) {
+            rule.mainClock.advanceTimeBy(contentCaptureEventLoopIntervalMs)
+            rule.waitForIdle()
+        }
+
+        // Assert
+        rule.runOnIdle {
+            // At least 5 times(List itself + 4 children)
+            verify(contentCaptureSessionCompat, atLeast(5)).notifyViewAppeared(any())
+        }
+    }
+
+    @Test
+    fun testSendContentCaptureSemanticsStructureChangeEvents_lazyList_scrollDown1Item() =
+        runBlocking {
+            // Arrange.
+            var listState: LazyListState? = null
+            var scope: CoroutineScope? = null
+
+            rule.setContentWithContentCaptureEnabled {
+                listState = rememberLazyListState()
+                scope = rememberCoroutineScope()
+                ContentCaptureTestLazyList(listState!!)
+            }
+
+            val bundle1 = Bundle()
+            whenever(viewStructureCompat.extras).thenReturn(bundle1)
+
+            // Act.
+            rule.runOnIdle {
+                // Perform scroll down action: text_4 appeared, text_0 disappeared
+                scope?.launch { listState?.scrollToItem(index = 1) }
+            }
+            repeat(2) {
+                rule.mainClock.advanceTimeBy(contentCaptureEventLoopIntervalMs)
+                rule.waitForIdle()
+            }
+
+            // Assert.
+            rule.runOnIdle {
+                val viewStructures = mutableListOf<ViewStructure>()
+                with(argumentCaptor<ViewStructure>()) {
+                    verify(contentCaptureSessionCompat, times(1)).notifyViewAppeared(capture())
+                    viewStructures.addAll(allValues)
+                }
+                assertThat(viewStructures.size).isEqualTo(1)
+                assertAdditionalIndices(bundle1, 3)
+                verify(contentCaptureSessionCompat, times(1)).notifyViewDisappeared(any())
+            }
+        }
+
+    @Test
+    fun testSendContentCaptureSemanticsStructureChangeEvents_lazyList_scrollDown2Items() =
+        runBlocking {
+            // Arrange
+            var listState: LazyListState? = null
+            var scope: CoroutineScope? = null
+
+            rule.setContentWithContentCaptureEnabled {
+                listState = rememberLazyListState()
+                scope = rememberCoroutineScope()
+                ContentCaptureTestLazyList(listState!!)
+            }
+
+            val bundle1 = Bundle()
+            val bundle2 = Bundle()
+            whenever(viewStructureCompat.extras).doReturnConsecutively(listOf(bundle1, bundle2))
+            rule.runOnIdle {
+                // text_[4,5] appeared, text_[0,1] disappeared
+                scope?.launch { listState?.scrollToItem(index = 2) }
+            }
+
+            repeat(2) {
+                rule.mainClock.advanceTimeBy(contentCaptureEventLoopIntervalMs)
+                rule.waitForIdle()
+            }
+
+            // Assert
+            rule.runOnIdle {
+                val viewStructures = mutableListOf<ViewStructure>()
+                with(argumentCaptor<ViewStructure>()) {
+                    verify(contentCaptureSessionCompat, times(2)).notifyViewAppeared(capture())
+                    viewStructures.addAll(allValues)
+                }
+                assertThat(viewStructures.size).isEqualTo(2)
+                assertAdditionalIndices(bundle1, 2)
+                assertAdditionalIndices(bundle2, 3)
+                verify(contentCaptureSessionCompat, times(2)).notifyViewDisappeared(any())
+            }
+        }
+
+    @Test
+    fun testSendContentCaptureSemanticsStructureChangeEvents_lazyList_scrollUp1Item() =
+        runBlocking {
+            // Arrange.
+            var listState: LazyListState? = null
+            var scope: CoroutineScope? = null
+
+            rule.setContentWithContentCaptureEnabled {
+                listState = rememberLazyListState(initialFirstVisibleItemIndex = 3)
+                scope = rememberCoroutineScope()
+                ContentCaptureTestLazyList(listState!!)
+            }
+
+            val bundle1 = Bundle()
+            whenever(viewStructureCompat.extras).thenReturn(bundle1)
+
+            // Act.
+            rule.runOnIdle {
+                // Perform scroll down action: text_2 appeared, text_6 disappeared
+                scope?.launch { listState?.scrollToItem(index = 2) }
+            }
+            repeat(2) {
+                rule.mainClock.advanceTimeBy(contentCaptureEventLoopIntervalMs)
+                rule.waitForIdle()
+            }
+
+            // Assert.
+            rule.runOnIdle {
+                val viewStructures = mutableListOf<ViewStructure>()
+                with(argumentCaptor<ViewStructure>()) {
+                    verify(contentCaptureSessionCompat, times(1)).notifyViewAppeared(capture())
+                    viewStructures.addAll(allValues)
+                }
+                assertThat(viewStructures.size).isEqualTo(1)
+                assertAdditionalIndices(bundle1, 0)
+                verify(contentCaptureSessionCompat, times(1)).notifyViewDisappeared(any())
+            }
+        }
+
+    @Test
+    fun testSendContentCaptureSemanticsStructureChangeEvents_lazyList_scrollUp2Items() =
+        runBlocking {
+            // Arrange
+            var listState: LazyListState? = null
+            var scope: CoroutineScope? = null
+
+            rule.setContentWithContentCaptureEnabled {
+                listState = rememberLazyListState(initialFirstVisibleItemIndex = 3)
+                scope = rememberCoroutineScope()
+                ContentCaptureTestLazyList(listState!!)
+            }
+
+            val bundle1 = Bundle()
+            val bundle2 = Bundle()
+            whenever(viewStructureCompat.extras).doReturnConsecutively(listOf(bundle1, bundle2))
+            rule.runOnIdle {
+                // text_[1,2] appeared, text_[5,6] disappeared
+                scope?.launch { listState?.scrollToItem(index = 1) }
+            }
+
+            repeat(2) {
+                rule.mainClock.advanceTimeBy(contentCaptureEventLoopIntervalMs)
+                rule.waitForIdle()
+            }
+
+            // Assert
+            rule.runOnIdle {
+                val viewStructures = mutableListOf<ViewStructure>()
+                with(argumentCaptor<ViewStructure>()) {
+                    verify(contentCaptureSessionCompat, times(2)).notifyViewAppeared(capture())
+                    viewStructures.addAll(allValues)
+                }
+                assertThat(viewStructures.size).isEqualTo(2)
+                assertAdditionalIndices(bundle1, 0)
+                assertAdditionalIndices(bundle2, 1)
+                verify(contentCaptureSessionCompat, times(2)).notifyViewDisappeared(any())
+            }
+        }
+
+    @Test
     @SdkSuppress(minSdkVersion = 31)
     fun testUpdateTranslationOnAppeared_showOriginal() {
         // Arrange.
@@ -592,4 +782,27 @@
     // TODO(b/272068594): Add api to fetch the semantics id from SemanticsNodeInteraction directly.
     private val SemanticsNodeInteraction.semanticsId: Int
         get() = fetchSemanticsNode().id
+
+    @Composable
+    private fun ContentCaptureTestLazyList(listState: LazyListState) {
+        val itemCount = 20
+        LazyColumn(state = listState, modifier = Modifier.testTag("LazyColumn").height(36.dp)) {
+            items(itemCount) { index ->
+                Box(
+                    Modifier.size(10.dp).testTag("Item_$index").semantics {
+                        text = AnnotatedString("text_$index")
+                    }
+                )
+            }
+        }
+    }
+
+    private fun assertAdditionalIndices(bundle: Bundle, expected: Int) {
+        assertThat(
+                bundle.getInt(
+                    AndroidContentCaptureManager.VIEW_STRUCTURE_BUNDLE_KEY_ADDITIONAL_INDEX
+                )
+            )
+            .isEqualTo(expected)
+    }
 }
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/draw/DrawModifierTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/draw/DrawModifierTest.kt
index f27e0b9..4547a74 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/draw/DrawModifierTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/draw/DrawModifierTest.kt
@@ -39,14 +39,19 @@
 import androidx.compose.testutils.assertPixels
 import androidx.compose.ui.AtLeastSize
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.background
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.geometry.Size
 import androidx.compose.ui.graphics.BlendMode
+import androidx.compose.ui.graphics.Canvas
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.graphics.ImageBitmap
+import androidx.compose.ui.graphics.ImageBitmapConfig
 import androidx.compose.ui.graphics.Path
 import androidx.compose.ui.graphics.PixelMap
 import androidx.compose.ui.graphics.asAndroidBitmap
+import androidx.compose.ui.graphics.drawscope.CanvasDrawScope
 import androidx.compose.ui.graphics.drawscope.ContentDrawScope
 import androidx.compose.ui.graphics.drawscope.DrawScope
 import androidx.compose.ui.graphics.graphicsLayer
@@ -376,6 +381,83 @@
 
     @Test
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun testRecordWithCache_setsProperties() {
+        var graphicsLayer: GraphicsLayer? = null
+        val testTag = "TestTag"
+        val size = 120.dp
+        val expectedDensity = Density(5f)
+        val expectedDrawSize = 50.dp
+        var expectedDrawSizePx: IntSize? = null
+        val expectedLayoutDirection = LayoutDirection.Rtl
+        var actualDensityFloat: Float? = null
+        var actualDrawSize: IntSize? = null
+        var actualLayoutDirection: LayoutDirection? = null
+        val tintColor = Color.Blue
+        val backgroundColor = Color.Green
+        rule.setContent {
+            expectedDrawSizePx =
+                with(LocalDensity.current) {
+                    val sizePx = expectedDrawSize.roundToPx()
+                    IntSize(sizePx, sizePx)
+                }
+            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
+                Box(Modifier.fillMaxSize().background(backgroundColor)) {
+                    Box(
+                        modifier =
+                            Modifier.size(size)
+                                .testTag(testTag)
+                                .then(
+                                    Modifier.drawWithCache {
+                                        val layer =
+                                            obtainGraphicsLayer().also { graphicsLayer = it }
+                                        // Explicit typing to force resolution to use the extension
+                                        // on
+                                        // CacheDrawScope instead of the GraphicsLayer#record API
+                                        val block: ContentDrawScope.() -> Unit = {
+                                            actualDensityFloat = density
+                                            actualDrawSize = drawContext.size.toIntSize()
+                                            actualLayoutDirection = drawContext.layoutDirection
+                                            drawContent()
+                                        }
+                                        layer.record(
+                                            density = expectedDensity,
+                                            layoutDirection = expectedLayoutDirection,
+                                            size = expectedDrawSizePx!!,
+                                            block = block
+                                        )
+                                        layer.colorFilter = ColorFilter.tint(tintColor)
+                                        onDrawWithContent { drawLayer(layer) }
+                                    }
+                                )
+                    ) {
+                        Canvas(modifier = Modifier.fillMaxSize()) { drawRect(Color.Red) }
+                    }
+                }
+            }
+        }
+        rule.waitForIdle()
+
+        assertEquals(expectedDrawSizePx, graphicsLayer!!.size)
+        assertEquals(expectedDensity.density, actualDensityFloat)
+        assertEquals(expectedLayoutDirection, actualLayoutDirection)
+        assertEquals(expectedDrawSizePx, actualDrawSize)
+
+        rule.onNodeWithTag(testTag).captureToImage().toPixelMap().apply {
+            val width = expectedDrawSizePx!!.width
+            val height = expectedDrawSizePx!!.height
+            assertPixelColor(tintColor, 0, 0)
+            assertPixelColor(tintColor, 0, width - 1)
+            assertPixelColor(tintColor, height - 1, 0)
+            assertPixelColor(tintColor, width - 1, height - 1)
+            assertPixelColor(tintColor, width / 2, height / 2)
+            // We should only draw a box of size expectedDrawSize, so the rest of the pixels
+            // should be the background color
+            assertPixelColor(backgroundColor, width + 1, height + 1)
+        }
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     fun testGraphicsLayerPersistence() {
         val testTag = "TestTag"
         val drawGraphicsLayer = mutableStateOf(0)
@@ -466,6 +548,104 @@
         }
     }
 
+    /** Regression test for b/389046242 */
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun testRecordDrawContent_drawOutsideOfDrawPhase_softwareRendering() {
+        val testTag = "TestTag"
+        val targetColor = Color.Blue
+        var layer: GraphicsLayer? = null
+        var density: Density? = null
+        rule.setContent {
+            Column(modifier = Modifier.testTag(testTag)) {
+                layer = rememberGraphicsLayer()
+                density = LocalDensity.current
+                with(LocalDensity.current) {
+                    Canvas(
+                        Modifier.size(100.toDp()).drawWithContent {
+                            layer!!.record { [email protected]() }
+                            drawLayer(layer!!)
+                        }
+                    ) {
+                        drawRect(targetColor)
+                    }
+                }
+            }
+        }
+        rule.waitForIdle()
+
+        rule.runOnIdle {
+            // Draw into an Argb8888 bitmap to force software rendering
+            val bitmap = ImageBitmap(100, 100, ImageBitmapConfig.Argb8888)
+            val canvas = Canvas(bitmap)
+            CanvasDrawScope()
+                .draw(
+                    density = density!!,
+                    size = Size(100f, 100f),
+                    layoutDirection = LayoutDirection.Ltr,
+                    canvas = canvas,
+                    block = { drawLayer(layer!!) },
+                )
+
+            bitmap.toPixelMap().apply {
+                assertPixelColor(targetColor, 0, 0)
+                assertPixelColor(targetColor, 0, this.width - 1)
+                assertPixelColor(targetColor, this.height - 1, 0)
+                assertPixelColor(targetColor, this.width - 1, this.height - 1)
+                assertPixelColor(targetColor, this.width / 2, this.height / 2)
+            }
+        }
+    }
+
+    /** Regression test for b/389046242 */
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun testRecordWithCacheDrawContent_drawOutsideOfDrawPhase_softwareRendering() {
+        val testTag = "TestTag"
+        val targetColor = Color.Blue
+        var layer: GraphicsLayer? = null
+        var density: Density? = null
+        rule.setContent {
+            Column(modifier = Modifier.testTag(testTag)) {
+                density = LocalDensity.current
+                with(LocalDensity.current) {
+                    Canvas(
+                        Modifier.size(100.toDp()).drawWithCache {
+                            layer = obtainGraphicsLayer()
+                            layer!!.record { drawContent() }
+                            onDrawWithContent { drawLayer(layer!!) }
+                        }
+                    ) {
+                        drawRect(targetColor)
+                    }
+                }
+            }
+        }
+        rule.waitForIdle()
+
+        rule.runOnIdle {
+            // Draw into an Argb8888 bitmap to force software rendering
+            val bitmap = ImageBitmap(100, 100, ImageBitmapConfig.Argb8888)
+            val canvas = Canvas(bitmap)
+            CanvasDrawScope()
+                .draw(
+                    density = density!!,
+                    size = Size(100f, 100f),
+                    layoutDirection = LayoutDirection.Ltr,
+                    canvas = canvas,
+                    block = { drawLayer(layer!!) },
+                )
+
+            bitmap.toPixelMap().apply {
+                assertPixelColor(targetColor, 0, 0)
+                assertPixelColor(targetColor, 0, this.width - 1)
+                assertPixelColor(targetColor, this.height - 1, 0)
+                assertPixelColor(targetColor, this.width - 1, this.height - 1)
+                assertPixelColor(targetColor, this.width / 2, this.height / 2)
+            }
+        }
+    }
+
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     @Test
     fun testCacheHitWithStateChange() {
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/focus/RequestFocusTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/focus/RequestFocusTest.kt
index ccbe363a9..2941447 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/focus/RequestFocusTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/focus/RequestFocusTest.kt
@@ -16,18 +16,30 @@
 
 package androidx.compose.ui.focus
 
+import android.view.View
+import android.widget.LinearLayout
 import androidx.compose.foundation.focusGroup
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.size
+import androidx.compose.material.Button
+import androidx.compose.material.Text
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusStateImpl.Active
 import androidx.compose.ui.focus.FocusStateImpl.ActiveParent
 import androidx.compose.ui.focus.FocusStateImpl.Captured
 import androidx.compose.ui.focus.FocusStateImpl.Inactive
+import androidx.compose.ui.input.InputMode
+import androidx.compose.ui.input.InputModeManager
+import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.platform.LocalInputModeManager
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.assertIsFocused
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth.assertThat
@@ -740,4 +752,55 @@
                 .inOrder()
         }
     }
+
+    @Test
+    fun requestFocus_wrongDirection() {
+        val tag2 = "tag 2"
+        val tag3 = "tag 3"
+        lateinit var button2: View
+        lateinit var button3: View
+        lateinit var inputModeManager: InputModeManager
+
+        rule.setContent {
+            inputModeManager = LocalInputModeManager.current
+            AndroidView(
+                modifier = Modifier.fillMaxSize(),
+                factory = {
+                    LinearLayout(it).apply {
+                        orientation = LinearLayout.VERTICAL
+                        addView(
+                            ComposeView(it).apply {
+                                setContent { Button(onClick = {}) { Text("Button 1") } }
+                            }
+                        )
+                        addView(
+                            ComposeView(it).apply {
+                                button2 = this
+                                setContent {
+                                    Button(onClick = {}, Modifier.testTag(tag2)) {
+                                        Text("Button 2")
+                                    }
+                                }
+                            }
+                        )
+                        addView(
+                            ComposeView(it).apply {
+                                button3 = this
+                                setContent {
+                                    Button(onClick = {}, Modifier.testTag(tag3)) {
+                                        Text("Button 3")
+                                    }
+                                }
+                            }
+                        )
+                    }
+                }
+            )
+        }
+        rule.runOnIdle { inputModeManager.requestInputMode(InputMode.Keyboard) }
+        rule.runOnIdle { button3.requestFocus() }
+        rule.onNodeWithTag(tag3).assertIsFocused()
+        rule.runOnIdle { button2.requestFocus(View.FOCUS_UP, android.graphics.Rect()) }
+        rule.onNodeWithTag(tag2).assertIsFocused()
+    }
 }
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillManager.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillManager.android.kt
index b8cefcb..f6a524e 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillManager.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillManager.android.kt
@@ -219,37 +219,52 @@
         if (semanticsInfo.semanticsConfiguration?.isRelatedToAutoCommit() == true) {
             currentlyDisplayedIDs.add(semanticsInfo.semanticsId)
             pendingChangesToDisplayedIds = true
-            // TODO(MNUZEN): Notify autofill manager that a node has been added.
-            // platformAutofillManager
-            //     .notifyViewVisibilityChanged(view, semanticsInfo.semanticsId, true)
+            // `notifyVisibilityChanged` is called when nodes appear onscreen (and become visible).
+            platformAutofillManager.notifyViewVisibilityChanged(
+                view,
+                semanticsInfo.semanticsId,
+                true
+            )
         }
     }
 
     internal fun onPostLayoutNodeReused(semanticsInfo: SemanticsInfo, previousSemanticsId: Int) {
         if (currentlyDisplayedIDs.remove(previousSemanticsId)) {
             pendingChangesToDisplayedIds = true
+            platformAutofillManager.notifyViewVisibilityChanged(view, previousSemanticsId, false)
         }
         if (semanticsInfo.semanticsConfiguration?.isRelatedToAutoCommit() == true) {
             currentlyDisplayedIDs.add(semanticsInfo.semanticsId)
             pendingChangesToDisplayedIds = true
+            platformAutofillManager.notifyViewVisibilityChanged(
+                view,
+                semanticsInfo.semanticsId,
+                true
+            )
         }
     }
 
     internal fun onLayoutNodeDeactivated(semanticsInfo: SemanticsInfo) {
         if (currentlyDisplayedIDs.remove(semanticsInfo.semanticsId)) {
             pendingChangesToDisplayedIds = true
-            // TODO(MNUZEN): Notify autofill manager that a node has been removed.
-            // platformAutofillManager
-            //     .notifyViewVisibilityChanged(view, semanticsInfo.semanticsId, false)
+            platformAutofillManager.notifyViewVisibilityChanged(
+                view,
+                semanticsInfo.semanticsId,
+                false
+            )
         }
     }
 
     internal fun onDetach(semanticsInfo: SemanticsInfo) {
         if (currentlyDisplayedIDs.remove(semanticsInfo.semanticsId)) {
             pendingChangesToDisplayedIds = true
-            // TODO(MNUZEN): Notify autofill manager that a node has been removed.
-            // platformAutofillManager
-            //     .notifyViewVisibilityChanged(view, semanticsInfo.semanticsId, false)
+            // `notifyVisibilityChanged` is called when nodes go offscreen (and become invisible
+            // to the user).
+            platformAutofillManager.notifyViewVisibilityChanged(
+                view,
+                semanticsInfo.semanticsId,
+                false
+            )
         }
     }
 
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/contentcapture/AndroidContentCaptureManager.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/contentcapture/AndroidContentCaptureManager.android.kt
index 9299d38..f6267e88 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/contentcapture/AndroidContentCaptureManager.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/contentcapture/AndroidContentCaptureManager.android.kt
@@ -26,15 +26,12 @@
 import android.view.translation.ViewTranslationResponse
 import androidx.annotation.RequiresApi
 import androidx.annotation.VisibleForTesting
-import androidx.collection.ArraySet
 import androidx.collection.IntObjectMap
 import androidx.collection.MutableIntObjectMap
-import androidx.collection.MutableIntSet
 import androidx.collection.intObjectMapOf
 import androidx.collection.mutableIntObjectMapOf
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.internal.checkPreconditionNotNull
-import androidx.compose.ui.node.LayoutNode
 import androidx.compose.ui.platform.AndroidComposeView
 import androidx.compose.ui.platform.SemanticsNodeCopy
 import androidx.compose.ui.platform.SemanticsNodeWithAdjustedBounds
@@ -51,7 +48,6 @@
 import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.util.fastForEach
 import androidx.compose.ui.util.fastJoinToString
-import androidx.compose.ui.util.fastMap
 import androidx.lifecycle.DefaultLifecycleObserver
 import androidx.lifecycle.LifecycleOwner
 import java.util.function.Consumer
@@ -70,8 +66,9 @@
 ) : ContentCaptureManager, DefaultLifecycleObserver, View.OnAttachStateChangeListener {
 
     @VisibleForTesting internal var contentCaptureSession: ContentCaptureSessionCompat? = null
-    private val bufferedAppearedNodes = MutableIntObjectMap<ViewStructureCompat>()
-    private val bufferedDisappearedNodes = MutableIntSet()
+
+    /** An ordered list of buffered content capture events. */
+    private val bufferedEvents = mutableListOf<ContentCaptureEvent>()
 
     /**
      * Delay before dispatching a recurring accessibility event in milliseconds. This delay
@@ -95,7 +92,6 @@
     private var translateStatus = TranslateStatus.SHOW_ORIGINAL
 
     private var currentSemanticsNodesInvalidated = true
-    private val subtreeChangedLayoutNodes = ArraySet<LayoutNode>()
     private val boundsUpdateChannel = Channel<Unit>(1)
     internal val handler = Handler(Looper.getMainLooper())
 
@@ -134,12 +130,10 @@
         // once by the CC checker and once by the a11y checker.
         view.measureAndLayout()
 
-        // Structural change
-        sendSemanticsStructureChangeEvents(
-            view.semanticsOwner.unmergedRootSemanticsNode,
-            previousSemanticsRoot
-        )
-        sendContentCaptureStructureChangeEvents(
+        // Semantics structural change
+        // Always send disappear event first.
+        sendContentCaptureDisappearEvents()
+        sendContentCaptureAppearEvents(
             view.semanticsOwner.unmergedRootSemanticsNode,
             previousSemanticsRoot
         )
@@ -164,7 +158,7 @@
 
     override fun onStart(owner: LifecycleOwner) {
         contentCaptureSession = onContentCaptureSession()
-        updateBuffersOnAppeared(view.semanticsOwner.unmergedRootSemanticsNode)
+        updateBuffersOnAppeared(index = -1, view.semanticsOwner.unmergedRootSemanticsNode)
         notifyContentCaptureChanges()
     }
 
@@ -180,21 +174,16 @@
      * batches separated by a 100ms delay.
      */
     internal suspend fun boundsUpdatesEventLoop() {
-        try {
-            for (notification in boundsUpdateChannel) {
-                if (isEnabled) {
-                    notifyContentCaptureChanges()
-                }
-                if (!checkingForSemanticsChanges) {
-                    checkingForSemanticsChanges = true
-                    handler.post(contentCaptureChangeChecker)
-                }
-
-                subtreeChangedLayoutNodes.clear()
-                delay(SendRecurringContentCaptureEventsIntervalMillis)
+        for (notification in boundsUpdateChannel) {
+            if (isEnabled) {
+                notifyContentCaptureChanges()
             }
-        } finally {
-            subtreeChangedLayoutNodes.clear()
+            if (!checkingForSemanticsChanges) {
+                checkingForSemanticsChanges = true
+                handler.post(contentCaptureChangeChecker)
+            }
+
+            delay(SendRecurringContentCaptureEventsIntervalMillis)
         }
     }
 
@@ -211,7 +200,7 @@
         }
     }
 
-    internal fun onLayoutChange(layoutNode: LayoutNode) {
+    internal fun onLayoutChange() {
         // When content capture is turned off, we still want to keep
         // currentSemanticsNodesInvalidated up to date so that when content capture is turned on
         // later, we can refresh currentSemanticsNodes if currentSemanticsNodes is stale.
@@ -219,59 +208,24 @@
 
         // The layout change of a LayoutNode will also affect its children, so even if it doesn't
         // have semantics attached, we should process it.
-        if (isEnabled) notifySubtreeStateChangeIfNeeded(layoutNode)
+        if (isEnabled) notifySubtreeStateChangeIfNeeded()
     }
 
-    // Analogous to sendAccessibilitySemanticsStructureChangeEvents
-    private fun sendSemanticsStructureChangeEvents(
-        newNode: SemanticsNode,
-        oldNode: SemanticsNodeCopy
-    ) {
-        val newChildren = MutableIntSet(newNode.replacedChildren.size)
-        // If any child is added, clear the subtree rooted at this node and return.
-        newNode.replacedChildren.fastForEach { child ->
-            if (currentSemanticsNodes.contains(child.id)) {
-                if (!oldNode.children.contains(child.id)) {
-                    notifySubtreeStateChangeIfNeeded(newNode.layoutNode)
-                    return
-                }
-                newChildren.add(child.id)
-            }
-        }
-
-        // If any child is deleted, clear the subtree rooted at this node and return.
-        oldNode.children.forEach { child ->
-            if (!newChildren.contains(child)) {
-                notifySubtreeStateChangeIfNeeded(newNode.layoutNode)
-                return
-            }
-        }
-
-        newNode.replacedChildren.fastForEach { child ->
-            if (currentSemanticsNodes.contains(child.id)) {
-                val prevNode =
-                    checkPreconditionNotNull(previousSemanticsNodes[child.id]) {
-                        "node not present in pruned tree before this change"
-                    }
-                sendSemanticsStructureChangeEvents(child, prevNode)
-            }
-        }
-    }
-
-    private fun sendContentCaptureStructureChangeEvents(
-        newNode: SemanticsNode,
-        oldNode: SemanticsNodeCopy
-    ) {
-        // Iterate the new tree to notify content capture appear
-        newNode.replacedChildren.fastForEach { child ->
-            if (currentSemanticsNodes.contains(child.id) && !oldNode.children.contains(child.id)) {
-                updateBuffersOnAppeared(child)
-            }
-        }
-        // Notify content capture disappear
+    private fun sendContentCaptureDisappearEvents() {
         previousSemanticsNodes.forEachKey { key ->
             if (!currentSemanticsNodes.contains(key)) {
                 bufferContentCaptureViewDisappeared(key)
+                notifySubtreeStateChangeIfNeeded()
+            }
+        }
+    }
+
+    private fun sendContentCaptureAppearEvents(newNode: SemanticsNode, oldNode: SemanticsNodeCopy) {
+        // Iterate the new tree to notify content capture appear
+        newNode.fastForEachReplacedVisibleChildren { index, child ->
+            if (!oldNode.children.contains(child.id)) {
+                updateBuffersOnAppeared(index, child)
+                notifySubtreeStateChangeIfNeeded()
             }
         }
 
@@ -284,7 +238,7 @@
                     checkPreconditionNotNull(previousSemanticsNodes[child.id]) {
                         "node not present in pruned tree before this change"
                     }
-                sendContentCaptureStructureChangeEvents(child, prevNodeCopy)
+                sendContentCaptureAppearEvents(child, prevNodeCopy)
             }
         }
     }
@@ -356,14 +310,11 @@
             SemanticsNodeCopy(view.semanticsOwner.unmergedRootSemanticsNode, currentSemanticsNodes)
     }
 
-    // Analogous to notifySubtreeAccessibilityStateChangedIfNeeded
-    private fun notifySubtreeStateChangeIfNeeded(layoutNode: LayoutNode) {
-        if (subtreeChangedLayoutNodes.add(layoutNode)) {
-            boundsUpdateChannel.trySend(Unit)
-        }
+    private fun notifySubtreeStateChangeIfNeeded() {
+        boundsUpdateChannel.trySend(Unit)
     }
 
-    private fun SemanticsNode.toViewStructure(): ViewStructureCompat? {
+    private fun SemanticsNode.toViewStructure(index: Int): ViewStructureCompat? {
         val session = contentCaptureSession ?: return null
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
             return null
@@ -385,12 +336,16 @@
             return null
         }
 
-        // Due to the batching strategy, the ContentCaptureEvent.eventTimestamp is inaccurate.
-        // This timestamp in the extra bundle is the equivalent substitution.
-        structure.extras?.putLong(
-            "android.view.contentcapture.EventTimestamp",
-            currentSemanticsNodesSnapshotTimestampMillis
-        )
+        structure.extras?.let {
+            // Due to the batching strategy, the ContentCaptureEvent.eventTimestamp is inaccurate.
+            // This timestamp in the extra bundle is the equivalent substitution.
+            it.putLong(
+                VIEW_STRUCTURE_BUNDLE_KEY_TIMESTAMP,
+                currentSemanticsNodesSnapshotTimestampMillis
+            )
+            // An additional index to help the System Intelligence to rebuild hierarchy with order.
+            it.putInt(VIEW_STRUCTURE_BUNDLE_KEY_ADDITIONAL_INDEX, index)
+        }
 
         configuration.getOrNull(SemanticsProperties.TestTag)?.let {
             // Treat test tag as resourceId
@@ -423,6 +378,27 @@
         return structure
     }
 
+    private fun SemanticsNode.fastForEachReplacedVisibleChildren(
+        action: (Int, SemanticsNode) -> Unit
+    ) =
+        this.replacedChildren.fastForEachIndexedWithFilter(action) {
+            currentSemanticsNodes.contains(it.id)
+        }
+
+    private inline fun <T> List<T>.fastForEachIndexedWithFilter(
+        action: (Int, T) -> Unit,
+        predicate: (T) -> Boolean
+    ) {
+        var i = 0
+        for (index in indices) {
+            val item = get(index)
+            if (predicate(item)) {
+                action(i, item)
+                i++
+            }
+        }
+    }
+
     private fun bufferContentCaptureViewAppeared(
         virtualId: Int,
         viewStructure: ViewStructureCompat?
@@ -431,21 +407,25 @@
             return
         }
 
-        if (bufferedDisappearedNodes.contains(virtualId)) {
-            // disappear then appear
-            bufferedDisappearedNodes.remove(virtualId)
-        } else {
-            bufferedAppearedNodes[virtualId] = viewStructure
-        }
+        bufferedEvents.add(
+            ContentCaptureEvent(
+                virtualId,
+                currentSemanticsNodesSnapshotTimestampMillis,
+                ContentCaptureEventType.VIEW_APPEAR,
+                viewStructure
+            )
+        )
     }
 
     private fun bufferContentCaptureViewDisappeared(virtualId: Int) {
-        if (bufferedAppearedNodes.containsKey(virtualId)) {
-            // appear then disappear
-            bufferedAppearedNodes.remove(virtualId)
-        } else {
-            bufferedDisappearedNodes.add(virtualId)
-        }
+        bufferedEvents.add(
+            ContentCaptureEvent(
+                virtualId,
+                currentSemanticsNodesSnapshotTimestampMillis,
+                ContentCaptureEventType.VIEW_DISAPPEAR,
+                null
+            )
+        )
     }
 
     private fun notifyContentCaptureChanges() {
@@ -454,34 +434,35 @@
             return
         }
 
-        if (bufferedAppearedNodes.isNotEmpty()) {
-            session.notifyViewsAppeared(
-                mutableListOf<ViewStructureCompat>()
-                    .apply { bufferedAppearedNodes.forEachValue { add(it) } }
-                    .fastMap { it.toViewStructure() }
-            )
-            bufferedAppearedNodes.clear()
-        }
-        if (bufferedDisappearedNodes.isNotEmpty()) {
-            session.notifyViewsDisappeared(
-                mutableListOf<Int>()
-                    .apply { bufferedDisappearedNodes.forEach { add(it) } }
-                    .fastMap { it.toLong() }
-                    .toLongArray()
-            )
-            bufferedDisappearedNodes.clear()
+        if (bufferedEvents.isNotEmpty()) {
+            bufferedEvents.fastForEach { event ->
+                when (event.type) {
+                    ContentCaptureEventType.VIEW_APPEAR -> {
+                        event.structureCompat?.let { node ->
+                            session.notifyViewAppeared(node.toViewStructure())
+                        }
+                    }
+                    ContentCaptureEventType.VIEW_DISAPPEAR -> {
+                        session.newAutofillId(event.id.toLong())?.let { autofillId ->
+                            session.notifyViewDisappeared(autofillId)
+                        }
+                    }
+                }
+            }
+            session.flush()
+            bufferedEvents.clear()
         }
     }
 
-    private fun updateBuffersOnAppeared(node: SemanticsNode) {
+    private fun updateBuffersOnAppeared(index: Int, node: SemanticsNode) {
         if (!isEnabled) {
             return
         }
 
         updateTranslationOnAppeared(node)
 
-        bufferContentCaptureViewAppeared(node.id, node.toViewStructure())
-        node.replacedChildren.fastForEach { child -> updateBuffersOnAppeared(child) }
+        bufferContentCaptureViewAppeared(node.id, node.toViewStructure(index))
+        node.fastForEachReplacedVisibleChildren { i, child -> updateBuffersOnAppeared(i, child) }
     }
 
     private fun updateBuffersOnDisappeared(node: SemanticsNode) {
@@ -649,4 +630,22 @@
             response
         )
     }
+
+    companion object {
+        const val VIEW_STRUCTURE_BUNDLE_KEY_TIMESTAMP = "android.view.contentcapture.EventTimestamp"
+        const val VIEW_STRUCTURE_BUNDLE_KEY_ADDITIONAL_INDEX =
+            "android.view.ViewStructure.extra.EXTRA_VIEW_NODE_INDEX"
+    }
 }
+
+private enum class ContentCaptureEventType {
+    VIEW_APPEAR,
+    VIEW_DISAPPEAR,
+}
+
+private data class ContentCaptureEvent(
+    val id: Int,
+    val timestamp: Long,
+    val type: ContentCaptureEventType,
+    val structureCompat: ViewStructureCompat?,
+)
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
index 5197336..1ba5721 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
@@ -1047,7 +1047,7 @@
                 focusedRect = previouslyFocusedRect?.toComposeRect()
             ) {
                 it.requestFocus(focusDirection)
-            } ?: false
+            } == true
         }
         // This view is already focused.
         if (isFocused) return true
@@ -1085,6 +1085,19 @@
             return false // The requestFocus() from within the focusSearch was canceled
         }
 
+        if (previouslyFocusedRect != null && !hasFocus()) {
+            // try searching, ignoring the previously focused rect. We've had a request to focus on
+            // this specific View
+            val altFocus =
+                focusOwner.focusSearch(focusDirection = focusDirection, focusedRect = null) {
+                    it.requestFocus(focusDirection)
+                }
+            if (altFocus == true) {
+                // found alternative focus
+                return true
+            }
+        }
+
         // We advertised ourselves as focusable, but we aren't. Try to just move the focus to the
         // next item.
         val nextFocusedView = findNextNonChildView(direction)
@@ -1794,7 +1807,7 @@
 
     override fun onLayoutChange(layoutNode: LayoutNode) {
         composeAccessibilityDelegate.onLayoutChange(layoutNode)
-        contentCaptureManager.onLayoutChange(layoutNode)
+        contentCaptureManager.onLayoutChange()
     }
 
     override fun onLayoutNodeDeactivated(layoutNode: LayoutNode) {
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/FocusGroupNode.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/FocusGroupNode.android.kt
index 8082b9a..81900a7 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/FocusGroupNode.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/FocusGroupNode.android.kt
@@ -165,8 +165,14 @@
                 focusedChild = newFocus
                 val focusTargetNode = getFocusTargetOfEmbeddedViewWrapper()
                 if (!focusTargetNode.focusState.hasFocus)
-                    focusOwner.focusTransactionManager.withNewTransaction {
+                    if (
+                        @OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled
+                    ) {
                         focusTargetNode.performRequestFocus()
+                    } else {
+                        focusOwner.focusTransactionManager.withNewTransaction {
+                            focusTargetNode.performRequestFocus()
+                        }
                     }
             }
             subViewLostFocus -> {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ComposeUiFlags.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ComposeUiFlags.kt
index d518673..d1c4c32 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ComposeUiFlags.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/ComposeUiFlags.kt
@@ -86,4 +86,12 @@
      * disabling them.
      */
     @Suppress("MutableBareField") @JvmField var isViewFocusFixEnabled: Boolean = true
+
+    /**
+     * With this flag on, the new focus state management implementation is enabled. The new
+     * implementation removes the focus state previously stored in each FocusTargetNode and instead
+     * keeps track of the current active focus node centrally in FocusOwnerImpl. This change reduces
+     * the cost of initializing the focus system.
+     */
+    @Suppress("MutableBareField") @JvmField var isTrackFocusEnabled: Boolean = true
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draw/DrawModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draw/DrawModifier.kt
index 0f1a62f..5cbd602 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draw/DrawModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draw/DrawModifier.kt
@@ -24,8 +24,6 @@
 import androidx.compose.ui.graphics.GraphicsContext
 import androidx.compose.ui.graphics.drawscope.ContentDrawScope
 import androidx.compose.ui.graphics.drawscope.DrawScope
-import androidx.compose.ui.graphics.drawscope.draw
-import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
 import androidx.compose.ui.graphics.layer.GraphicsLayer
 import androidx.compose.ui.internal.JvmDefaultWithCompatibility
 import androidx.compose.ui.internal.checkPrecondition
@@ -334,20 +332,27 @@
         layoutDirection: LayoutDirection = [email protected],
         size: IntSize = [email protected](),
         block: ContentDrawScope.() -> Unit
-    ) =
-        record(density, layoutDirection, size) {
-            val contentDrawScope = [email protected]!!
-            drawIntoCanvas { canvas ->
-                contentDrawScope.draw(
-                    density,
-                    layoutDirection,
-                    canvas,
-                    Size(size.width.toFloat(), size.height.toFloat())
-                ) {
-                    block(contentDrawScope)
+    ) {
+        val scope = contentDrawScope!!
+        with(scope) {
+            val prevDensity = drawContext.density
+            val prevLayoutDirection = drawContext.layoutDirection
+            record(size) {
+                drawContext.apply {
+                    this.density = density
+                    this.layoutDirection = layoutDirection
+                }
+                try {
+                    block(scope)
+                } finally {
+                    drawContext.apply {
+                        this.density = prevDensity
+                        this.layoutDirection = prevLayoutDirection
+                    }
                 }
             }
         }
+    }
 
     /** Issue drawing commands to be executed before the layout content is drawn */
     fun onDrawBehind(block: DrawScope.() -> Unit): DrawResult = onDrawWithContent {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusInvalidationManager.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusInvalidationManager.kt
index b9cb7f3..4860a28 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusInvalidationManager.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusInvalidationManager.kt
@@ -16,9 +16,15 @@
 
 package androidx.compose.ui.focus
 
+import androidx.collection.MutableScatterSet
+import androidx.collection.mutableScatterSetOf
+import androidx.compose.ui.ComposeUiFlags
+import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.ui.focus.FocusStateImpl.ActiveParent
 import androidx.compose.ui.focus.FocusStateImpl.Inactive
 import androidx.compose.ui.internal.checkPrecondition
 import androidx.compose.ui.node.Nodes
+import androidx.compose.ui.node.visitAncestors
 import androidx.compose.ui.node.visitSelfAndChildren
 import androidx.compose.ui.util.fastForEach
 
@@ -30,72 +36,169 @@
 internal class FocusInvalidationManager(
     private val onRequestApplyChangesListener: (() -> Unit) -> Unit,
     private val invalidateOwnerFocusState: () -> Unit,
-    private val rootFocusStateFetcher: () -> FocusState
+    private val rootFocusStateFetcher: () -> FocusState,
+    private val activeFocusTargetNodeFetcher: () -> FocusTargetNode?
 ) {
-    private val focusTargetNodes = mutableListOf<FocusTargetNode>()
-    private val focusEventNodes = mutableListOf<FocusEventModifierNode>()
-    private val focusPropertiesNodes = mutableListOf<FocusPropertiesModifierNode>()
-    private val focusTargetsWithInvalidatedFocusEvents = mutableListOf<FocusTargetNode>()
+    private val focusTargetNodes = mutableScatterSetOf<FocusTargetNode>()
+    private val focusEventNodes = mutableScatterSetOf<FocusEventModifierNode>()
+    private val focusTargetNodesLegacy = mutableListOf<FocusTargetNode>()
+    private val focusEventNodesLegacy = mutableListOf<FocusEventModifierNode>()
+    private val focusPropertiesNodesLegacy = mutableListOf<FocusPropertiesModifierNode>()
+    private val focusTargetsWithInvalidatedFocusEventsLegacy = mutableListOf<FocusTargetNode>()
+
+    private var isInvalidationScheduled = false
 
     fun scheduleInvalidation(node: FocusTargetNode) {
-        focusTargetNodes.scheduleInvalidation(node)
+        if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+            focusTargetNodes.scheduleInvalidation(node)
+        } else {
+            focusTargetNodesLegacy.scheduleInvalidationLegacy(node)
+        }
     }
 
     fun scheduleInvalidation(node: FocusEventModifierNode) {
-        focusEventNodes.scheduleInvalidation(node)
+        if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+            focusEventNodes.scheduleInvalidation(node)
+        } else {
+            focusEventNodesLegacy.scheduleInvalidationLegacy(node)
+        }
     }
 
     fun scheduleInvalidation(node: FocusPropertiesModifierNode) {
-        focusPropertiesNodes.scheduleInvalidation(node)
+        focusPropertiesNodesLegacy.scheduleInvalidationLegacy(node)
+    }
+
+    fun scheduleInvalidationForOwner() {
+        setUpOnRequestApplyChangesListener()
     }
 
     fun hasPendingInvalidation(): Boolean {
-        return focusTargetNodes.isNotEmpty() ||
-            focusPropertiesNodes.isNotEmpty() ||
-            focusEventNodes.isNotEmpty()
+        return if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+            isInvalidationScheduled
+        } else {
+            focusTargetNodesLegacy.isNotEmpty() ||
+                focusPropertiesNodesLegacy.isNotEmpty() ||
+                focusEventNodesLegacy.isNotEmpty()
+        }
     }
 
-    private fun <T> MutableList<T>.scheduleInvalidation(node: T) {
+    private fun <T> MutableScatterSet<T>.scheduleInvalidation(node: T) {
+        if (add(node)) {
+            setUpOnRequestApplyChangesListener()
+        }
+    }
+
+    private fun setUpOnRequestApplyChangesListener() {
+        if (!isInvalidationScheduled) {
+            onRequestApplyChangesListener.invoke(::invalidateNodes)
+            isInvalidationScheduled = true
+        }
+    }
+
+    private fun <T> MutableList<T>.scheduleInvalidationLegacy(node: T) {
         if (add(node)) {
             // If this is the first node scheduled for invalidation,
             // we set up a listener that runs after onApplyChanges.
-            if (focusTargetNodes.size + focusEventNodes.size + focusPropertiesNodes.size == 1) {
+            if (
+                focusTargetNodesLegacy.size +
+                    focusEventNodesLegacy.size +
+                    focusPropertiesNodesLegacy.size == 1
+            ) {
                 onRequestApplyChangesListener.invoke(::invalidateNodes)
             }
         }
     }
 
     private fun invalidateNodes() {
+        if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+            invalidateNodesOptimized()
+        } else {
+            invalidateNodesLegacy()
+        }
+    }
+
+    private fun invalidateNodesOptimized() {
+        val activeFocusTargetNode = activeFocusTargetNodeFetcher()
+        if (activeFocusTargetNode == null) {
+            // If there is no active focus node, dispatch the Inactive state to event nodes.
+            focusEventNodes.forEach { it.onFocusEvent(Inactive) }
+        } else if (activeFocusTargetNode.isAttached) {
+            if (focusTargetNodes.contains(activeFocusTargetNode)) {
+                activeFocusTargetNode.invalidateFocus()
+            }
+
+            var hasVisitedAncestorTarget = false
+            activeFocusTargetNode.visitAncestors(
+                Nodes.FocusTarget or Nodes.FocusEvent,
+                includeSelf = true
+            ) {
+                // Keep track of whether we traversed past the first target node ancestor of the
+                // active focus target node, so that all the subsequent event nodes are sent the
+                // ActiveParent state rather than Active/Captured.
+                if (it is FocusTargetNode && it !== activeFocusTargetNode) {
+                    hasVisitedAncestorTarget = true
+                }
+
+                // Don't send events to event nodes that were not invalidated.
+                if (it !is FocusEventModifierNode || !focusEventNodes.contains(it)) {
+                    return@visitAncestors
+                }
+
+                // Event nodes that are between the active focus target and the first ancestor
+                // target receive the Active/Captured state, while the event nodes further up
+                // receive the ActiveParent state.
+                if (hasVisitedAncestorTarget) {
+                    it.onFocusEvent(ActiveParent)
+                } else {
+                    it.onFocusEvent(activeFocusTargetNode.focusState)
+                }
+
+                // Remove the event node from the list of invalidated nodes, so that we only send a
+                // single event per node.
+                focusEventNodes.remove(it)
+            }
+
+            // Send the Inactive state to the event nodes that are not in the active node ancestors.
+            focusEventNodes.forEach { it.onFocusEvent(Inactive) }
+        }
+
+        invalidateOwnerFocusState()
+        focusTargetNodes.clear()
+        focusEventNodes.clear()
+        isInvalidationScheduled = false
+    }
+
+    private fun invalidateNodesLegacy() {
         if (!rootFocusStateFetcher().hasFocus) {
             // If root doesn't have focus, skip full invalidation and default to the Inactive state.
-            focusEventNodes.fastForEach { it.onFocusEvent(Inactive) }
-            focusTargetNodes.fastForEach { node ->
+            focusEventNodesLegacy.fastForEach { it.onFocusEvent(Inactive) }
+            focusTargetNodesLegacy.fastForEach { node ->
                 if (node.isAttached && !node.isInitialized()) {
                     node.initializeFocusState(Inactive)
                 }
             }
-            focusTargetNodes.clear()
-            focusEventNodes.clear()
-            focusPropertiesNodes.clear()
-            focusTargetsWithInvalidatedFocusEvents.clear()
+            focusTargetNodesLegacy.clear()
+            focusEventNodesLegacy.clear()
+            focusPropertiesNodesLegacy.clear()
+            focusTargetsWithInvalidatedFocusEventsLegacy.clear()
             invalidateOwnerFocusState()
             return
         }
 
         // Process all the invalidated FocusProperties nodes.
-        focusPropertiesNodes.fastForEach {
+        focusPropertiesNodesLegacy.fastForEach {
             // We don't need to invalidate a focus properties node if it was scheduled for
             // invalidation earlier in the composition but was then removed.
             if (!it.node.isAttached) return@fastForEach
 
             it.visitSelfAndChildren(Nodes.FocusTarget) { focusTarget ->
-                focusTargetNodes.add(focusTarget)
+                focusTargetNodesLegacy.add(focusTarget)
             }
         }
-        focusPropertiesNodes.clear()
+        focusPropertiesNodesLegacy.clear()
 
         // Process all the focus events nodes.
-        focusEventNodes.fastForEach { focusEventNode ->
+        focusEventNodesLegacy.fastForEach { focusEventNode ->
             // When focus nodes are removed, the corresponding focus events are scheduled for
             // invalidation. If the focus event was also removed, we don't need to invalidate it.
             // We call onFocusEvent with the default value, just to make it easier for the user,
@@ -123,9 +226,9 @@
                 // send an onFocusEvent if the invalidation causes a focus state change.
                 // However this onFocusEvent was invalidated, so we have to ensure that we call
                 // onFocusEvent even if the focus state didn't change.
-                if (it in focusTargetNodes) {
+                if (it in focusTargetNodesLegacy) {
                     requiresUpdate = false
-                    focusTargetsWithInvalidatedFocusEvents.add(it)
+                    focusTargetsWithInvalidatedFocusEventsLegacy.add(it)
                     return@visitSelfAndChildren
                 }
             }
@@ -140,10 +243,10 @@
                 )
             }
         }
-        focusEventNodes.clear()
+        focusEventNodesLegacy.clear()
 
         // Process all the focus target nodes.
-        focusTargetNodes.fastForEach {
+        focusTargetNodesLegacy.fastForEach {
             // We don't need to invalidate the focus target if it was scheduled for invalidation
             // earlier in the composition but was then removed.
             if (!it.isAttached) return@fastForEach
@@ -152,19 +255,21 @@
             it.invalidateFocus()
             if (
                 preInvalidationState != it.focusState ||
-                    it in focusTargetsWithInvalidatedFocusEvents
+                    it in focusTargetsWithInvalidatedFocusEventsLegacy
             ) {
                 it.dispatchFocusCallbacks()
             }
         }
-        focusTargetNodes.clear()
+        focusTargetNodesLegacy.clear()
         // Clear the set so we can reuse it
-        focusTargetsWithInvalidatedFocusEvents.clear()
+        focusTargetsWithInvalidatedFocusEventsLegacy.clear()
 
         invalidateOwnerFocusState()
 
-        checkPrecondition(focusPropertiesNodes.isEmpty()) { "Unprocessed FocusProperties nodes" }
-        checkPrecondition(focusEventNodes.isEmpty()) { "Unprocessed FocusEvent nodes" }
-        checkPrecondition(focusTargetNodes.isEmpty()) { "Unprocessed FocusTarget nodes" }
+        checkPrecondition(focusPropertiesNodesLegacy.isEmpty()) {
+            "Unprocessed FocusProperties nodes"
+        }
+        checkPrecondition(focusEventNodesLegacy.isEmpty()) { "Unprocessed FocusEvent nodes" }
+        checkPrecondition(focusTargetNodesLegacy.isEmpty()) { "Unprocessed FocusTarget nodes" }
     }
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwner.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwner.kt
index a22a570..ae474794 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwner.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwner.kt
@@ -144,6 +144,15 @@
     /** Schedule a FocusProperties node to be invalidated after onApplyChanges. */
     fun scheduleInvalidation(node: FocusPropertiesModifierNode)
 
+    /** Schedule the owner to be invalidated after onApplyChanges. */
+    fun scheduleInvalidationForOwner()
+
     /** The focus state of the root focus node. */
     val rootState: FocusState
+
+    /** The currently active [FocusTargetNode] or null if no node has focus. */
+    var activeFocusTargetNode: FocusTargetNode?
+
+    /** Whether the active focus target node has requested focus capture. */
+    var isFocusCaptured: Boolean
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwnerImpl.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwnerImpl.kt
index d86a6bc..07a8cdf 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwnerImpl.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOwnerImpl.kt
@@ -30,6 +30,10 @@
 import androidx.compose.ui.focus.FocusRequester.Companion.Cancel
 import androidx.compose.ui.focus.FocusRequester.Companion.Default
 import androidx.compose.ui.focus.FocusRequester.Companion.Redirect
+import androidx.compose.ui.focus.FocusStateImpl.Active
+import androidx.compose.ui.focus.FocusStateImpl.ActiveParent
+import androidx.compose.ui.focus.FocusStateImpl.Captured
+import androidx.compose.ui.focus.FocusStateImpl.Inactive
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.input.key.KeyEvent
 import androidx.compose.ui.input.key.KeyEventType.Companion.KeyDown
@@ -37,6 +41,7 @@
 import androidx.compose.ui.input.key.key
 import androidx.compose.ui.input.key.type
 import androidx.compose.ui.input.rotary.RotaryScrollEvent
+import androidx.compose.ui.internal.requirePrecondition
 import androidx.compose.ui.node.DelegatableNode
 import androidx.compose.ui.node.ModifierNodeElement
 import androidx.compose.ui.node.NodeKind
@@ -75,7 +80,8 @@
         FocusInvalidationManager(
             onRequestApplyChangesListener,
             ::invalidateOwnerFocusState,
-            ::rootState
+            ::rootState,
+            ::activeFocusTargetNode
         )
 
     override val focusTransactionManager: FocusTransactionManager = FocusTransactionManager()
@@ -148,8 +154,12 @@
      * hierarchy.
      */
     override fun releaseFocus() {
-        focusTransactionManager.withExistingTransaction {
+        if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
             rootFocusNode.clearFocus(forced = true, refreshFocusEvents = true)
+        } else {
+            focusTransactionManager.withExistingTransaction {
+                rootFocusNode.clearFocus(forced = true, refreshFocusEvents = true)
+            }
         }
     }
 
@@ -173,23 +183,38 @@
         focusDirection: FocusDirection
     ): Boolean {
         val clearedFocusSuccessfully =
-            focusTransactionManager.withNewTransaction(
-                onCancelled = {
-                    return@withNewTransaction
-                }
-            ) {
+            if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
                 if (!force) {
                     // Don't clear focus if an item on the focused path has a custom exit specified.
                     when (rootFocusNode.performCustomClearFocus(focusDirection)) {
                         Redirected,
                         Cancelled,
-                        RedirectCancelled -> return@withNewTransaction false
-                        None -> {
-                            /* Do nothing. */
+                        RedirectCancelled -> false
+                        None -> clearFocus(force, refreshFocusEvents)
+                    }
+                } else {
+                    clearFocus(force, refreshFocusEvents)
+                }
+            } else {
+                focusTransactionManager.withNewTransaction(
+                    onCancelled = {
+                        return@withNewTransaction
+                    }
+                ) {
+                    if (!force) {
+                        // Don't clear focus if an item on the focused path has a custom exit
+                        // specified.
+                        when (rootFocusNode.performCustomClearFocus(focusDirection)) {
+                            Redirected,
+                            Cancelled,
+                            RedirectCancelled -> return@withNewTransaction false
+                            None -> {
+                                /* Do nothing. */
+                            }
                         }
                     }
+                    return@withNewTransaction rootFocusNode.clearFocus(force, refreshFocusEvents)
                 }
-                return@withNewTransaction rootFocusNode.clearFocus(force, refreshFocusEvents)
             }
 
         if (clearedFocusSuccessfully && clearOwnerFocus) {
@@ -198,6 +223,25 @@
         return clearedFocusSuccessfully
     }
 
+    private fun clearFocus(forced: Boolean = false, refreshFocusEvents: Boolean): Boolean {
+        if (activeFocusTargetNode == null) return true
+        if (isFocusCaptured && !forced) {
+            return false // Cannot clear focus if it's captured unless forced
+        }
+        val previousActiveFocusTargetNode = activeFocusTargetNode
+        activeFocusTargetNode = null
+        if (refreshFocusEvents && previousActiveFocusTargetNode != null) {
+            previousActiveFocusTargetNode.dispatchFocusCallbacks(
+                if (isFocusCaptured) Captured else Active,
+                Inactive
+            )
+            previousActiveFocusTargetNode.visitAncestors(Nodes.FocusTarget) {
+                it.dispatchFocusCallbacks(ActiveParent, Inactive)
+            }
+        }
+        return true
+    }
+
     /**
      * Moves focus in the specified direction.
      *
@@ -211,13 +255,19 @@
         }
         var requestFocusSuccess: Boolean? = false
         val generationBefore = focusTransactionManager.generation
+        val activeNodeBefore = activeFocusTargetNode
         val focusSearchSuccess =
             focusSearch(focusDirection, onFocusRectInterop()) {
                 requestFocusSuccess = it.requestFocus(focusDirection)
                 requestFocusSuccess ?: false
             }
         val generationAfter = focusTransactionManager.generation
-        if (focusSearchSuccess == true && generationBefore != generationAfter) {
+        if (
+            focusSearchSuccess == true &&
+                (generationBefore != generationAfter ||
+                    (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled &&
+                        activeNodeBefore !== activeFocusTargetNode))
+        ) {
             // There was a successful requestFocus() during the focusSearch
             return true
         }
@@ -361,6 +411,10 @@
         focusInvalidationManager.scheduleInvalidation(node)
     }
 
+    override fun scheduleInvalidationForOwner() {
+        focusInvalidationManager.scheduleInvalidationForOwner()
+    }
+
     /**
      * At the end of the invalidations, we need to ensure that the focus system is in a valid state.
      */
@@ -368,7 +422,10 @@
         // If an active item is removed, we currently clear focus from the hierarchy. We don't
         // clear focus from the root because that could cause initial focus logic to be re-run.
         // Now that all the invalidations are complete, we run owner.clearFocus() if needed.
-        if (rootFocusNode.focusState == FocusStateImpl.Inactive) {
+        if (
+            (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled &&
+                activeFocusTargetNode == null) || rootFocusNode.focusState == Inactive
+        ) {
             onClearFocusForOwner()
         }
     }
@@ -408,6 +465,22 @@
     override val rootState: FocusState
         get() = rootFocusNode.focusState
 
+    override var activeFocusTargetNode: FocusTargetNode? = null
+        set(value) {
+            val previousValue = field
+            field = value
+            if (value == null || previousValue !== value) isFocusCaptured = false
+        }
+
+    override var isFocusCaptured: Boolean = false
+        get() = field
+        set(value) {
+            requirePrecondition(!value || activeFocusTargetNode != null) {
+                "Cannot capture focus when the active focus target node is unset"
+            }
+            field = value
+        }
+
     private fun DelegatableNode.lastLocalKeyInputNode(): Modifier.Node? {
         var focusedKeyInputNode: Modifier.Node? = null
         visitLocalDescendants(Nodes.FocusTarget or Nodes.KeyInput) { modifierNode ->
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTargetNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTargetNode.kt
index 5c901a2..b02a220 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTargetNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTargetNode.kt
@@ -16,6 +16,8 @@
 
 package androidx.compose.ui.focus
 
+import androidx.compose.ui.ComposeUiFlags
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.CustomDestinationResult.Cancelled
 import androidx.compose.ui.focus.CustomDestinationResult.None
@@ -65,12 +67,31 @@
     override val shouldAutoInvalidate = false
 
     override var focusState: FocusStateImpl
-        get() =
-            focusTransactionManager?.run { uncommittedFocusState }
-                ?: committedFocusState
-                ?: Inactive
+        get() {
+            if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+                if (!isAttached) return Inactive
+                val focusOwner = requireOwner().focusOwner
+                val activeNode = focusOwner.activeFocusTargetNode ?: return Inactive
+                return if (this === activeNode) {
+                    if (focusOwner.isFocusCaptured) Captured else Active
+                } else {
+                    if (activeNode.isAttached) {
+                        activeNode.visitAncestors(Nodes.FocusTarget) {
+                            if (this === it) return ActiveParent
+                        }
+                    }
+                    Inactive
+                }
+            } else {
+                return focusTransactionManager?.run { uncommittedFocusState }
+                    ?: committedFocusState
+                    ?: Inactive
+            }
+        }
         set(value) {
-            with(requireTransactionManager()) { uncommittedFocusState = value }
+            if (!@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+                with(requireTransactionManager()) { uncommittedFocusState = value }
+            }
         }
 
     @Deprecated(
@@ -85,15 +106,24 @@
     override fun requestFocus(focusDirection: FocusDirection): Boolean {
         trace("FocusTransactions:requestFocus") {
             if (!fetchFocusProperties().canFocus) return false
-            return requireTransactionManager().withNewTransaction(
-                onCancelled = { if (node.isAttached) dispatchFocusCallbacks() }
-            ) {
+            return if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
                 when (performCustomRequestFocus(focusDirection)) {
                     None -> performRequestFocus()
                     Redirected -> true
                     Cancelled,
                     RedirectCancelled -> false
                 }
+            } else {
+                requireTransactionManager().withNewTransaction(
+                    onCancelled = { if (node.isAttached) dispatchFocusCallbacks() }
+                ) {
+                    when (performCustomRequestFocus(focusDirection)) {
+                        None -> performRequestFocus()
+                        Redirected -> true
+                        Cancelled,
+                        RedirectCancelled -> false
+                    }
+                }
             }
         }
     }
@@ -102,11 +132,21 @@
         set(value) {
             if (field != value) {
                 field = value
-                // Avoid invalidating if we have not been initialized yet: there is no need to
-                // invalidate since these property changes cannot affect anything.
-                if (isAttached && isInitialized()) {
-                    // Invalidate focus if needed
-                    onObservedReadsChanged()
+                if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+                    if (
+                        isAttached &&
+                            this === requireOwner().focusOwner.activeFocusTargetNode &&
+                            !field.canFocus(this)
+                    ) {
+                        clearFocus(forced = true, refreshFocusEvents = true)
+                    }
+                } else {
+                    // Avoid invalidating if we have not been initialized yet: there is no need to
+                    // invalidate since these property changes cannot affect anything.
+                    if (isAttached && isInitialized()) {
+                        // Invalidate focus if needed
+                        onObservedReadsChanged()
+                    }
                 }
             }
         }
@@ -117,12 +157,17 @@
         get() = ModifierLocalBeyondBoundsLayout.current
 
     override fun onObservedReadsChanged() {
-        val previousFocusState = focusState
-        invalidateFocus()
-        if (previousFocusState != focusState) dispatchFocusCallbacks()
+        if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+            invalidateFocus()
+        } else {
+            val previousFocusState = focusState
+            invalidateFocus()
+            if (previousFocusState != focusState) dispatchFocusCallbacks()
+        }
     }
 
     override fun onAttach() {
+        if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) return
         invalidateFocusTarget()
     }
 
@@ -136,23 +181,29 @@
             // implementation so that focus is sent to the immediate focus parent.
             Active,
             Captured -> {
-                requireOwner()
-                    .focusOwner
-                    .clearFocus(
-                        force = true,
-                        refreshFocusEvents = true,
-                        clearOwnerFocus = false,
-                        focusDirection = Exit
-                    )
+                val focusOwner = requireOwner().focusOwner
+                focusOwner.clearFocus(
+                    force = true,
+                    refreshFocusEvents = true,
+                    clearOwnerFocus = false,
+                    focusDirection = Exit
+                )
                 // We don't clear the owner's focus yet, because this could trigger an initial
                 // focus scenario after the focus is cleared. Instead, we schedule invalidation
                 // after onApplyChanges. The FocusInvalidationManager contains the invalidation
                 // logic and calls clearFocus() on the owner after all the nodes in the hierarchy
                 // are invalidated.
-                invalidateFocusTarget()
+                if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+                    focusOwner.scheduleInvalidationForOwner()
+                } else {
+                    invalidateFocusTarget()
+                }
             }
             // This node might be reused, so reset the state to Inactive.
-            ActiveParent -> requireTransactionManager().withNewTransaction { focusState = Inactive }
+            ActiveParent ->
+                if (!@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+                    requireTransactionManager().withNewTransaction { focusState = Inactive }
+                }
             Inactive -> {}
         }
         // This node might be reused, so we reset its state.
@@ -182,11 +233,18 @@
         val scope = CancelIndicatingFocusBoundaryScope(focusDirection)
         val focusTransactionManager = focusTransactionManager
         val generationBefore = focusTransactionManager?.generation ?: 0
+        val focusOwner = requireOwner().focusOwner
+        val activeNodeBefore = focusOwner.activeFocusTargetNode
         focusProperties.enterOrExit(scope)
         val generationAfter = focusTransactionManager?.generation ?: 0
+        val activeNodeAfter = focusOwner.activeFocusTargetNode
         if (scope.isCanceled) {
             block(Cancel)
-        } else if (generationBefore != generationAfter) {
+        } else if (
+            generationBefore != generationAfter ||
+                (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled &&
+                    (activeNodeBefore !== activeNodeAfter && activeNodeAfter != null))
+        ) {
             block(Redirect)
         }
     }
@@ -287,6 +345,20 @@
         onDispatchEventsCompleted?.invoke(this)
     }
 
+    internal fun dispatchFocusCallbacks(previousState: FocusState, newState: FocusState) {
+        val focusOwner = requireOwner().focusOwner
+        val activeNode = focusOwner.activeFocusTargetNode
+        if (previousState != newState) onFocusChange?.invoke(previousState, newState)
+        visitSelfAndAncestors(Nodes.FocusEvent, untilType = Nodes.FocusTarget) {
+            if (activeNode !== focusOwner.activeFocusTargetNode) {
+                // Stop sending events, as focus changed in a callback
+                return@visitSelfAndAncestors
+            }
+            it.onFocusEvent(newState)
+        }
+        onDispatchEventsCompleted?.invoke(this)
+    }
+
     internal object FocusTargetElement : ModifierNodeElement<FocusTargetNode>() {
         override fun create() = FocusTargetNode()
 
@@ -301,7 +373,9 @@
         override fun equals(other: Any?) = other === this
     }
 
-    internal fun isInitialized(): Boolean = committedFocusState != null
+    internal fun isInitialized(): Boolean =
+        if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) true
+        else committedFocusState != null
 
     internal fun initializeFocusState(initialFocusState: FocusStateImpl? = null) {
         fun isInActiveSubTree(): Boolean {
@@ -334,12 +408,14 @@
 
         check(!isInitialized()) { "Re-initializing focus target node." }
 
-        requireTransactionManager().withNewTransaction {
-            // Note: hasActiveChild() is expensive since it searches the entire subtree. So we only
-            // do this if we are part of the active subtree.
-            this.focusState =
-                initialFocusState
-                    ?: if (isInActiveSubTree() && hasActiveChild()) ActiveParent else Inactive
+        if (!@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+            requireTransactionManager().withNewTransaction {
+                // Note: hasActiveChild() is expensive since it searches the entire subtree. So we
+                // only do this if we are part of the active subtree.
+                this.focusState =
+                    initialFocusState
+                        ?: if (isInActiveSubTree() && hasActiveChild()) ActiveParent else Inactive
+            }
         }
     }
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactionManager.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactionManager.kt
index c629e08..92af6b2 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactionManager.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactionManager.kt
@@ -18,6 +18,8 @@
 
 import androidx.collection.mutableScatterMapOf
 import androidx.compose.runtime.collection.mutableVectorOf
+import androidx.compose.ui.ComposeUiFlags
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.internal.checkPreconditionNotNull
 
 /**
@@ -83,13 +85,20 @@
      * current transaction.
      */
     var FocusTargetNode.uncommittedFocusState: FocusStateImpl?
-        get() = states[this]
-        set(value) {
-            val currentFocusState = states[this] ?: FocusStateImpl.Inactive
-            if (currentFocusState != value) {
-                generation++
+        get() =
+            if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+                error("uncommittedFocusState must not be accessed when isTrackFocusEnabled is on")
+            } else {
+                states[this]
             }
-            states[this] = checkPreconditionNotNull(value) { "requires a non-null focus state" }
+        set(value) {
+            if (!@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+                val currentFocusState = states[this] ?: FocusStateImpl.Inactive
+                if (currentFocusState != value) {
+                    generation++
+                }
+                states[this] = checkPreconditionNotNull(value) { "requires a non-null focus state" }
+            }
         }
 
     private fun beginTransaction() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactions.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactions.kt
index fe97805..2b49356 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactions.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTransactions.kt
@@ -16,6 +16,8 @@
 
 package androidx.compose.ui.focus
 
+import androidx.compose.runtime.collection.MutableVector
+import androidx.compose.runtime.collection.mutableVectorOf
 import androidx.compose.ui.ComposeUiFlags
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.InternalComposeUiApi
@@ -29,11 +31,12 @@
 import androidx.compose.ui.focus.FocusStateImpl.ActiveParent
 import androidx.compose.ui.focus.FocusStateImpl.Captured
 import androidx.compose.ui.focus.FocusStateImpl.Inactive
-import androidx.compose.ui.node.Nodes.FocusTarget
+import androidx.compose.ui.node.Nodes
 import androidx.compose.ui.node.nearestAncestor
 import androidx.compose.ui.node.observeReads
 import androidx.compose.ui.node.requireLayoutNode
 import androidx.compose.ui.node.requireOwner
+import androidx.compose.ui.node.visitAncestors
 
 /**
  * This function performs the request focus action.
@@ -43,13 +46,103 @@
  * [properties][FocusProperties] have been specified.
  */
 internal fun FocusTargetNode.performRequestFocus(): Boolean {
+    return if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+        performRequestFocusOptimized()
+    } else {
+        performRequestFocusLegacy()
+    }
+}
+
+private fun FocusTargetNode.performRequestFocusOptimized(): Boolean {
+    val focusOwner = requireOwner().focusOwner
+    val previousActiveNode = focusOwner.activeFocusTargetNode
+    val previousFocusState = focusState
+    if (previousActiveNode === this) {
+        // Focus events should be sent again if focus is requested for an already focused node
+        dispatchFocusCallbacks(previousFocusState, previousFocusState)
+        return true
+    }
+
+    if (previousActiveNode?.clearFocus(refreshFocusEvents = true) == false) {
+        return false // Don't grant focus if clearing focus from the previous node was rejected
+    }
+
+    // Request owner focus if it doesn't already have focus
+    if (previousActiveNode == null && !requestFocusForOwner()) {
+        return false // Don't grant focus if requesting owner focus failed
+    }
+    grantFocus()
+
+    // Find ancestor target and event nodes of the previous active target node
+    var previousAncestorTargetNodes: MutableVector<FocusTargetNode>? = null
+    if (previousActiveNode != null) {
+        previousAncestorTargetNodes = mutableVectorOf()
+        previousActiveNode.visitAncestors(Nodes.FocusTarget) { previousAncestorTargetNodes.add(it) }
+    }
+
+    // Diff the previous ancestor nodes with the ancestors of the new active target node
+    val ancestorTargetNodes = mutableVectorOf<FocusTargetNode>()
+    visitAncestors(Nodes.FocusTarget) {
+        val removed = previousAncestorTargetNodes?.remove(it)
+        if (removed == null || !removed) {
+            ancestorTargetNodes.add(it)
+        }
+    }
+
+    // Notify ancestor target nodes of the previous active node that are no longer ActiveParent
+    // The ancestors are traversed in the reversed order to dispatch events top->down
+    previousAncestorTargetNodes?.forEachReversed {
+        // Check if focus was cleared or redirected in a previous focus change callback
+        if (focusOwner.activeFocusTargetNode !== this) {
+            // The focus request was redirected or cancelled in a previous focus change callback
+            return false
+        }
+        it.dispatchFocusCallbacks(ActiveParent, Inactive)
+    }
+
+    // Notify ancestor target nodes of the new active node that become ActiveParent
+    // The ancestors are traversed in the reversed order to dispatch events top->down
+    ancestorTargetNodes.forEachReversed {
+        // Check if focus was cleared or redirected in a previous focus change callback
+        if (focusOwner.activeFocusTargetNode !== this) {
+            // The focus request was redirected or cancelled in a previous focus change callback
+            return false
+        }
+        it.dispatchFocusCallbacks(Inactive, ActiveParent)
+    }
+
+    // Check if focus was cleared or redirected in a previous focus change callback
+    if (focusOwner.activeFocusTargetNode !== this) {
+        // The focus request was redirected or cancelled in a previous focus change callback
+        return false
+    }
+
+    // Send events to the new active node
+    dispatchFocusCallbacks(previousFocusState, Active)
+
+    // Check if focus was cleared or redirected in a previous focus change callback
+    if (focusOwner.activeFocusTargetNode !== this) {
+        // The focus request was redirected or cancelled in a previous focus change callback
+        return false
+    }
+
+    @OptIn(ExperimentalComposeUiApi::class, InternalComposeUiApi::class)
+    if (ComposeUiFlags.isViewFocusFixEnabled && requireLayoutNode().getInteropView() == null) {
+        // This isn't an AndroidView, so we should be focused on this ComposeView
+        requireOwner().focusOwner.requestFocusForOwner(FocusDirection.Next, null)
+    }
+
+    return true
+}
+
+private fun FocusTargetNode.performRequestFocusLegacy(): Boolean {
     val success =
         when (focusState) {
             Active,
             Captured -> true
             ActiveParent -> clearChildFocus() && grantFocus()
             Inactive -> {
-                val parent = nearestAncestor(FocusTarget)
+                val parent = nearestAncestor(Nodes.FocusTarget)
                 if (parent != null) {
                     val prevState = parent.focusState
                     val success = parent.requestFocusForChild(this)
@@ -82,17 +175,30 @@
  * @return true if the focus was successfully captured. False otherwise.
  */
 internal fun FocusTargetNode.captureFocus() =
-    requireTransactionManager().withNewTransaction {
+    if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
         when (focusState) {
             Active -> {
-                focusState = Captured
-                dispatchFocusCallbacks()
+                requireOwner().focusOwner.isFocusCaptured = true
+                dispatchFocusCallbacks(Active, Captured)
                 true
             }
             Captured -> true
             ActiveParent,
             Inactive -> false
         }
+    } else {
+        requireTransactionManager().withNewTransaction {
+            when (focusState) {
+                Active -> {
+                    focusState = Captured
+                    dispatchFocusCallbacks()
+                    true
+                }
+                Captured -> true
+                ActiveParent,
+                Inactive -> false
+            }
+        }
     }
 
 /**
@@ -103,17 +209,30 @@
  * @return true if the captured focus was released. False Otherwise.
  */
 internal fun FocusTargetNode.freeFocus() =
-    requireTransactionManager().withNewTransaction {
+    if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
         when (focusState) {
             Captured -> {
-                focusState = Active
-                dispatchFocusCallbacks()
+                requireOwner().focusOwner.isFocusCaptured = false
+                dispatchFocusCallbacks(previousState = Captured, newState = Active)
                 true
             }
             Active -> true
             ActiveParent,
             Inactive -> false
         }
+    } else {
+        requireTransactionManager().withNewTransaction {
+            when (focusState) {
+                Captured -> {
+                    focusState = Active
+                    dispatchFocusCallbacks()
+                    true
+                }
+                Active -> true
+                ActiveParent,
+                Inactive -> false
+            }
+        }
     }
 
 /**
@@ -129,8 +248,14 @@
 ): Boolean =
     when (focusState) {
         Active -> {
-            focusState = Inactive
-            if (refreshFocusEvents) dispatchFocusCallbacks()
+            if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+                requireOwner().focusOwner.activeFocusTargetNode = null
+                if (refreshFocusEvents)
+                    dispatchFocusCallbacks(previousState = Active, newState = Inactive)
+            } else {
+                focusState = Inactive
+                if (refreshFocusEvents) dispatchFocusCallbacks()
+            }
             true
         }
         /**
@@ -139,8 +264,13 @@
          */
         ActiveParent ->
             if (clearChildFocus(forced, refreshFocusEvents)) {
-                focusState = Inactive
-                if (refreshFocusEvents) dispatchFocusCallbacks()
+                if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+                    if (refreshFocusEvents)
+                        dispatchFocusCallbacks(previousState = ActiveParent, newState = Inactive)
+                } else {
+                    focusState = Inactive
+                    if (refreshFocusEvents) dispatchFocusCallbacks()
+                }
                 true
             } else {
                 false
@@ -149,8 +279,14 @@
         /** If the node is [Captured], deny requests to clear focus, except for a forced clear. */
         Captured -> {
             if (forced) {
-                focusState = Inactive
-                if (refreshFocusEvents) dispatchFocusCallbacks()
+                if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+                    requireOwner().focusOwner.activeFocusTargetNode = null
+                    if (refreshFocusEvents)
+                        dispatchFocusCallbacks(previousState = Captured, newState = Inactive)
+                } else {
+                    focusState = Inactive
+                    if (refreshFocusEvents) dispatchFocusCallbacks()
+                }
             }
             forced
         }
@@ -169,7 +305,11 @@
     // No Focused Children, or we don't want to propagate focus to children.
     when (focusState) {
         Inactive,
-        ActiveParent -> focusState = Active
+        ActiveParent -> {
+            if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled)
+                requireOwner().focusOwner.activeFocusTargetNode = this
+            else focusState = Active
+        }
         Active,
         Captured -> {
             /* Already focused. */
@@ -193,7 +333,7 @@
 private fun FocusTargetNode.requestFocusForChild(childNode: FocusTargetNode): Boolean {
 
     // Only this node's children can ask for focus.
-    if (childNode.nearestAncestor(FocusTarget) != this) {
+    if (childNode.nearestAncestor(Nodes.FocusTarget) != this) {
         error("Non child node cannot request focus.")
     }
 
@@ -209,7 +349,7 @@
         // If this node is not [Active], we must gain focus first before granting it
         // to the requesting child.
         Inactive -> {
-            val focusParent = nearestAncestor(FocusTarget)
+            val focusParent = nearestAncestor(Nodes.FocusTarget)
             when {
                 // If this node is the root, request focus from the compose owner.
                 focusParent == null && requestFocusForOwner() -> {
@@ -262,7 +402,7 @@
         Captured -> return None
         ActiveParent -> return requireActiveChild().performCustomClearFocus(focusDirection)
         Inactive -> {
-            val focusParent = nearestAncestor(FocusTarget) ?: return None
+            val focusParent = nearestAncestor(Nodes.FocusTarget) ?: return None
             return when (focusParent.focusState) {
                 Captured -> Cancelled
                 ActiveParent -> focusParent.performCustomRequestFocus(focusDirection)
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTraversal.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTraversal.kt
index fe2b645..5313d30 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTraversal.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTraversal.kt
@@ -16,6 +16,8 @@
 
 package androidx.compose.ui.focus
 
+import androidx.compose.ui.ComposeUiFlags
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.focus.FocusDirection.Companion.Down
 import androidx.compose.ui.focus.FocusDirection.Companion.Enter
 import androidx.compose.ui.focus.FocusDirection.Companion.Exit
@@ -34,6 +36,7 @@
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.layout.findRootCoordinates
 import androidx.compose.ui.node.Nodes
+import androidx.compose.ui.node.requireOwner
 import androidx.compose.ui.node.visitAncestors
 import androidx.compose.ui.node.visitChildren
 import androidx.compose.ui.unit.LayoutDirection
@@ -80,6 +83,8 @@
             with(focusProperties) {
                 val focusTransactionManager = focusTransactionManager
                 val generationBefore = focusTransactionManager?.generation ?: 0
+                val focusOwner = requireOwner().focusOwner
+                val activeNodeBefore = focusOwner.activeFocusTargetNode
                 if (focusDirection == Enter) {
                     scope.onEnter()
                 } else {
@@ -88,7 +93,12 @@
                 val generationAfter = focusTransactionManager?.generation ?: 0
                 if (scope.isCanceled) {
                     Cancel
-                } else if (generationBefore != generationAfter) {
+                } else if (
+                    generationBefore != generationAfter ||
+                        (@OptIn(ExperimentalComposeUiApi::class)
+                        ComposeUiFlags.isTrackFocusEnabled &&
+                            activeNodeBefore !== focusOwner.activeFocusTargetNode)
+                ) {
                     Redirect
                 } else {
                     Default
@@ -168,18 +178,23 @@
     }
 
 internal fun FocusTargetNode.findActiveFocusNode(): FocusTargetNode? {
-    when (focusState) {
-        Active,
-        Captured -> return this
-        ActiveParent -> {
-            visitChildren(Nodes.FocusTarget) { node ->
-                node.findActiveFocusNode()?.let {
-                    return it
+    if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled) {
+        val activeNode = requireOwner().focusOwner.activeFocusTargetNode
+        return if (activeNode != null && activeNode.isAttached) activeNode else null
+    } else {
+        when (focusState) {
+            Active,
+            Captured -> return this
+            ActiveParent -> {
+                visitChildren(Nodes.FocusTarget) { node ->
+                    node.findActiveFocusNode()?.let {
+                        return it
+                    }
                 }
+                return null
             }
-            return null
+            Inactive -> return null
         }
-        Inactive -> return null
     }
 }
 
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/OneDimensionalFocusSearch.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/OneDimensionalFocusSearch.kt
index 5c45ba7..8b159c4 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/OneDimensionalFocusSearch.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/OneDimensionalFocusSearch.kt
@@ -18,6 +18,8 @@
 
 import androidx.compose.runtime.collection.MutableVector
 import androidx.compose.runtime.collection.mutableVectorOf
+import androidx.compose.ui.ComposeUiFlags
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.focus.FocusDirection.Companion.Next
 import androidx.compose.ui.focus.FocusDirection.Companion.Previous
 import androidx.compose.ui.focus.FocusStateImpl.Active
@@ -28,6 +30,7 @@
 import androidx.compose.ui.node.Nodes
 import androidx.compose.ui.node.nearestAncestor
 import androidx.compose.ui.node.requireLayoutNode
+import androidx.compose.ui.node.requireOwner
 import androidx.compose.ui.node.visitChildren
 import kotlin.contracts.ExperimentalContracts
 import kotlin.contracts.contract
@@ -113,9 +116,14 @@
 
     val focusTransactionManager = requireTransactionManager()
     val generationBeforeSearch = focusTransactionManager.generation
+    val activeNodeBeforeSearch = requireOwner().focusOwner.activeFocusTargetNode
     // Generate more items until searchChildren() finds a result.
     return searchBeyondBounds(direction) {
-        if (generationBeforeSearch != focusTransactionManager.generation) {
+        if (
+            generationBeforeSearch != focusTransactionManager.generation ||
+                (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled &&
+                    activeNodeBeforeSearch !== requireOwner().focusOwner.activeFocusTargetNode)
+        ) {
             // A new focus change was triggered during searchBeyondBounds.
             true
         } else {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusSearch.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusSearch.kt
index 6d8b8e05..71979f1 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusSearch.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/TwoDimensionalFocusSearch.kt
@@ -17,6 +17,8 @@
 package androidx.compose.ui.focus
 
 import androidx.compose.runtime.collection.MutableVector
+import androidx.compose.ui.ComposeUiFlags
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.focus.FocusDirection.Companion.Down
 import androidx.compose.ui.focus.FocusDirection.Companion.Enter
 import androidx.compose.ui.focus.FocusDirection.Companion.Left
@@ -30,6 +32,7 @@
 import androidx.compose.ui.node.DelegatableNode
 import androidx.compose.ui.node.Nodes
 import androidx.compose.ui.node.requireLayoutNode
+import androidx.compose.ui.node.requireOwner
 import androidx.compose.ui.node.visitChildren
 import androidx.compose.ui.util.fastCoerceAtLeast
 
@@ -168,9 +171,14 @@
 
     val focusTransactionManager = requireTransactionManager()
     val generationBeforeSearch = focusTransactionManager.generation
+    val activeNodeBeforeSearch = requireOwner().focusOwner.activeFocusTargetNode
     // Generate more items until searchChildren() finds a result.
     return searchBeyondBounds(direction) {
-        if (generationBeforeSearch != focusTransactionManager.generation) {
+        if (
+            generationBeforeSearch != focusTransactionManager.generation ||
+                (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled &&
+                    activeNodeBeforeSearch !== requireOwner().focusOwner.activeFocusTargetNode)
+        ) {
             // A new focus change was triggered during searchBeyondBounds.
             true
         } else {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/HitPathTracker.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/HitPathTracker.kt
index 3dbaa83..708518f 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/HitPathTracker.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/HitPathTracker.kt
@@ -441,6 +441,12 @@
 
         modifierNode.dispatchForKind(Nodes.PointerInput) { coordinates = it.layoutCoordinates }
 
+        // In some cases, undelegate() may be called and the modifierNode is still attached, but
+        // the [SuspendingPointerInputModifierNode] is no longer associated with it (since there
+        // are no [Nodes.PointerInput] kinds). In those cases, we skip triggering the event
+        // for this Node.
+        if (coordinates == null) return true
+
         @OptIn(ExperimentalComposeUiApi::class)
         for (j in 0 until changes.size()) {
             val keyValue = changes.keyAt(j)
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeDrawScope.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeDrawScope.kt
index 71607f9..2301631 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeDrawScope.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeDrawScope.kt
@@ -25,6 +25,8 @@
 import androidx.compose.ui.graphics.drawscope.draw
 import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
 import androidx.compose.ui.graphics.layer.GraphicsLayer
+import androidx.compose.ui.internal.checkPreconditionNotNull
+import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.toSize
 
 /**
@@ -43,7 +45,16 @@
 
     override fun drawContent() {
         drawIntoCanvas { canvas ->
-            val drawNode = drawNode!!
+            val drawNode =
+                checkPreconditionNotNull(drawNode) {
+                    "Attempting to drawContent for a `null` node. This usually means that a call" +
+                        " to ContentDrawScope#drawContent() has been captured inside a lambda," +
+                        " and is being invoked outside of the draw pass. Capturing the scope" +
+                        " this way is unsupported - if you are trying to record drawContent" +
+                        " with graphicsLayer.record(), make sure you are using the" +
+                        " GraphicsLayer#record function within DrawScope, instead of the" +
+                        " member function on GraphicsLayer."
+                }
             val nextDrawNode = drawNode.nextDrawNode()
             // NOTE(lmr): we only run performDraw directly on the node if the node's coordinator
             // is our own. This seems to work, but we should think about a cleaner way to dispatch
@@ -65,6 +76,31 @@
         }
     }
 
+    override fun GraphicsLayer.record(size: IntSize, block: DrawScope.() -> Unit) {
+        // When we record drawContent, we need to make sure to restore the drawModifierNode that is
+        // being drawn when we draw the recorded layer later, since the block passed to record
+        // sometimes needs to be invoked outside of this current draw pass
+        val currentDrawNode = drawNode
+        record(this@LayoutNodeDrawScope, [email protected], size) {
+            val previousDrawNode = [email protected]
+            [email protected] = currentDrawNode
+            try {
+                [email protected](
+                    // we can use [email protected] directly as the values in this@DrawScope
+                    // and this@record are the same
+                    drawContext.density,
+                    drawContext.layoutDirection,
+                    drawContext.canvas,
+                    drawContext.size,
+                    drawContext.graphicsLayer,
+                    block
+                )
+            } finally {
+                [email protected] = previousDrawNode
+            }
+        }
+    }
+
     // This is not thread safe
     fun DrawModifierNode.performDraw(canvas: Canvas, layer: GraphicsLayer?) {
         val coordinator = requireCoordinator(Nodes.Draw)
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt
index d204355..a4f5fe6 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt
@@ -17,6 +17,8 @@
 package androidx.compose.ui.node
 
 import androidx.collection.mutableObjectIntMapOf
+import androidx.compose.ui.ComposeUiFlags
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.classKeyForObject
 import androidx.compose.ui.draw.DrawModifier
@@ -339,9 +341,13 @@
             node is FocusPropertiesModifierNode &&
             node.specifiesCanFocusProperty()
     ) {
-        when (phase) {
-            Removed -> node.scheduleInvalidationOfAssociatedFocusTargets()
-            else -> node.invalidateFocusProperties()
+        if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isTrackFocusEnabled)
+            node.scheduleInvalidationOfAssociatedFocusTargets()
+        else {
+            when (phase) {
+                Removed -> node.scheduleInvalidationOfAssociatedFocusTargets()
+                else -> node.invalidateFocusProperties()
+            }
         }
     }
     if (Nodes.FocusEvent in selfKindSet && node is FocusEventModifierNode) {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.kt
index c1dc069..6802f8d 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.kt
@@ -871,7 +871,7 @@
 /**
  * Whether this semantics node is a traversal group.
  *
- * See https://developer.android.com/jetpack/compose/accessibility#modify-traversal-order
+ * See https://developer.android.com/develop/ui/compose/accessibility/traversal
  *
  * @see SemanticsProperties.IsTraversalGroup
  */
diff --git a/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/ContentCaptureSessionCompat.java b/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/ContentCaptureSessionCompat.java
index 476a580..6c19545 100644
--- a/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/ContentCaptureSessionCompat.java
+++ b/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/ContentCaptureSessionCompat.java
@@ -91,7 +91,7 @@
     /**
      * Creates a new {@link AutofillId} for a virtual child, so it can be used to uniquely identify
      * the children in the session.
-     *
+     * <p>
      * Compatibility behavior:
      * <ul>
      * <li>SDK 29 and above, this method matches platform behavior.
@@ -115,7 +115,7 @@
     /**
      * Creates a {@link ViewStructure} for a "virtual" view, so it can be passed to
      * {@link #notifyViewsAppeared} by the view managing the virtual view hierarchy.
-     *
+     * <p>
      * Compatibility behavior:
      * <ul>
      * <li>SDK 29 and above, this method matches platform behavior.
@@ -139,16 +139,104 @@
     }
 
     /**
+     * Notifies the Content Capture Service that a node has been added to the view structure.
+     *
+     * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
+     * automatically by the Android System for views that return {@code true} on
+     * {@link View#onProvideContentCaptureStructure(ViewStructure, int)}.
+     *
+     * <p>Consider use {@link #notifyViewsAppeared} which has a better performance when notifying
+     * a list of nodes has appeared.
+     * <p>
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 29 and above, this method matches platform behavior.
+     * <li>SDK 28 and below, this method does nothing.
+     * </ul>
+     *
+     * @param node node that has been added.
+     */
+    public void notifyViewAppeared(@NonNull ViewStructure node) {
+        if (SDK_INT >= 29) {
+            Api29Impl.notifyViewAppeared((ContentCaptureSession) mWrappedObj, node);
+        }
+    }
+
+    /**
+     * Notifies the Content Capture Service that a node has been removed from the view structure.
+     *
+     * <p>Typically called "manually" by views that handle their own virtual view hierarchy, or
+     * automatically by the Android System for standard views.
+     *
+     * <p>Consider use {@link #notifyViewsDisappeared} which has a better performance when notifying
+     * a list of nodes has disappeared.
+     * <p>
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 29 and above, this method matches platform behavior.
+     * <li>SDK 28 and below, this method does nothing.
+     * </ul>
+     *
+     * @param id id of the node that has been removed.
+     */
+    public void notifyViewDisappeared(@NonNull AutofillId id) {
+        if (SDK_INT >= 29) {
+            Api29Impl.notifyViewDisappeared((ContentCaptureSession) mWrappedObj, id);
+        }
+    }
+
+    /**
+     * Flushes an internal buffer of UI events and signals System Intelligence (SI) that a
+     * semantically meaningful state has been reached. SI uses this signal to potentially
+     * rebuild the view hierarchy and understand the current state of the UI.
+     *
+     * <p>UI events are often batched together for performance reasons. A semantic batch
+     * represents a series of events that, when applied sequentially, result in a
+     * meaningful and complete UI state.
+     *
+     * <p>It is crucial to call {@code flush()} after completing a semantic batch to ensure
+     * SI can accurately reconstruct the view hierarchy.
+     *
+     * <p><b>Premature Flushing:</b> Calling {@code flush()} within a semantic batch may
+     * lead to SI failing to rebuild the view hierarchy correctly. This could manifest as
+     * incorrect ordering of sibling nodes.
+     *
+     * <p><b>Delayed Flushing:</b> While not immediately flushing after a semantic batch is
+     * generally safe, it's recommended to do so as soon as possible. In the worst-case
+     * scenario where a {@code flush()} is never called, SI will attempt to process the
+     * events after a short delay based on view appearance and disappearance events.
+     * <p>
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 36 and above, this method matches platform behavior.
+     * <li>SDK 29 through 35, this method is a best-effort to match platform behavior, by
+     * sending a special {@link #notifyViewsDisappeared} event.
+     * <li>SDK 28 and below, this method does nothing.
+     * </ul>
+     */
+    public void flush() {
+        // TODO(b/380381249): implement after the new API is finalized.
+        // TODO(b/388128425): upstream changes back to the `core` lib.
+        if (SDK_INT >= 29) {
+            Api29Impl.notifyViewsDisappeared(
+                    (ContentCaptureSession) mWrappedObj,
+                    Objects.requireNonNull(ViewCompatShims.getAutofillId(mView)).toAutofillId(),
+                    new long[] { Long.MIN_VALUE });
+        }
+    }
+
+    /**
      * Notifies the Content Capture Service that a list of nodes has appeared in the view structure.
      *
      * <p>Typically called manually by views that handle their own virtual view hierarchy.
-     *
+     * <p>
      * Compatibility behavior:
      * <ul>
      * <li>SDK 34 and above, this method matches platform behavior.
      * <li>SDK 29 through 33, this method is a best-effort to match platform behavior, by
      * wrapping the virtual children with a pair of special view appeared events.
      * <li>SDK 28 and below, this method does nothing.
+     * </ul>
      *
      * @param appearedNodes nodes that have appeared. Each element represents a view node that has
      * been added to the view structure. The order of the elements is important, which should be
@@ -180,7 +268,7 @@
      * structure.
      *
      * <p>Should only be called by views that handle their own virtual view hierarchy.
-     *
+     * <p>
      * Compatibility behavior:
      * <ul>
      * <li>SDK 34 and above, this method matches platform behavior.
@@ -217,7 +305,7 @@
 
     /**
      * Notifies the Intelligence Service that the value of a text node has been changed.
-     *
+     * <p>
      * Compatibility behavior:
      * <ul>
      * <li>SDK 29 and above, this method matches platform behavior.
@@ -256,6 +344,11 @@
             contentCaptureSession.notifyViewsDisappeared(hostId, virtualIds);
         }
 
+        static void notifyViewDisappeared(
+                ContentCaptureSession contentCaptureSession, AutofillId id) {
+            contentCaptureSession.notifyViewDisappeared(id);
+        }
+
         static void notifyViewAppeared(
                 ContentCaptureSession contentCaptureSession, ViewStructure node) {
             contentCaptureSession.notifyViewAppeared(node);
diff --git a/constraintlayout/constraintlayout-compose/api/current.ignore b/constraintlayout/constraintlayout-compose/api/current.ignore
deleted file mode 100644
index dfb0518a..0000000
--- a/constraintlayout/constraintlayout-compose/api/current.ignore
+++ /dev/null
@@ -1,9 +0,0 @@
-// Baseline format: 1.0
-RemovedMethod: androidx.constraintlayout.compose.DebugFlags#getShowBounds():
-    Removed method androidx.constraintlayout.compose.DebugFlags.getShowBounds()
-RemovedMethod: androidx.constraintlayout.compose.DebugFlags#getShowKeyPositions():
-    Removed method androidx.constraintlayout.compose.DebugFlags.getShowKeyPositions()
-RemovedMethod: androidx.constraintlayout.compose.DebugFlags#getShowPaths():
-    Removed method androidx.constraintlayout.compose.DebugFlags.getShowPaths()
-RemovedMethod: androidx.constraintlayout.compose.GridFlag#isPlaceLayoutsOnSpansFirst():
-    Removed method androidx.constraintlayout.compose.GridFlag.isPlaceLayoutsOnSpansFirst()
diff --git a/constraintlayout/constraintlayout-compose/api/restricted_current.ignore b/constraintlayout/constraintlayout-compose/api/restricted_current.ignore
deleted file mode 100644
index dfb0518a..0000000
--- a/constraintlayout/constraintlayout-compose/api/restricted_current.ignore
+++ /dev/null
@@ -1,9 +0,0 @@
-// Baseline format: 1.0
-RemovedMethod: androidx.constraintlayout.compose.DebugFlags#getShowBounds():
-    Removed method androidx.constraintlayout.compose.DebugFlags.getShowBounds()
-RemovedMethod: androidx.constraintlayout.compose.DebugFlags#getShowKeyPositions():
-    Removed method androidx.constraintlayout.compose.DebugFlags.getShowKeyPositions()
-RemovedMethod: androidx.constraintlayout.compose.DebugFlags#getShowPaths():
-    Removed method androidx.constraintlayout.compose.DebugFlags.getShowPaths()
-RemovedMethod: androidx.constraintlayout.compose.GridFlag#isPlaceLayoutsOnSpansFirst():
-    Removed method androidx.constraintlayout.compose.GridFlag.isPlaceLayoutsOnSpansFirst()
diff --git a/constraintlayout/constraintlayout-compose/api/restricted_current.txt b/constraintlayout/constraintlayout-compose/api/restricted_current.txt
index 339b479..467bc76 100644
--- a/constraintlayout/constraintlayout-compose/api/restricted_current.txt
+++ b/constraintlayout/constraintlayout-compose/api/restricted_current.txt
@@ -679,7 +679,8 @@
     method public final void drawDebugBounds(androidx.compose.ui.graphics.drawscope.DrawScope, float forcedScaleFactor);
     method public String getDesignInfo(int startX, int startY, String args);
     method public final float getForcedScaleFactor();
-    method protected final java.util.Map<androidx.compose.ui.layout.Measurable,androidx.constraintlayout.core.state.WidgetFrame> getFrameCache();
+    method @Deprecated protected final java.util.Map<androidx.compose.ui.layout.Measurable,androidx.constraintlayout.core.state.WidgetFrame> getFrameCache();
+    method protected final java.util.Map<java.lang.String,androidx.constraintlayout.core.state.WidgetFrame> getFrameCache2();
     method public final int getLayoutCurrentHeight();
     method public final int getLayoutCurrentWidth();
     method protected final androidx.constraintlayout.compose.LayoutInformationReceiver? getLayoutInformationReceiver();
@@ -688,12 +689,16 @@
     method protected final androidx.constraintlayout.compose.State getState();
     method public void measure(androidx.constraintlayout.core.widgets.ConstraintWidget constraintWidget, androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.Measure measure);
     method public final void parseDesignElements(androidx.constraintlayout.compose.ConstraintSet constraintSet);
-    method public final void performLayout(androidx.compose.ui.layout.Placeable.PlacementScope, java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables);
-    method public final long performMeasure(long constraints, androidx.compose.ui.unit.LayoutDirection layoutDirection, androidx.constraintlayout.compose.ConstraintSet constraintSet, java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables, int optimizationLevel);
+    method @Deprecated public final void performLayout(androidx.compose.ui.layout.Placeable.PlacementScope, java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables);
+    method public final void performLayout(androidx.compose.ui.layout.Placeable.PlacementScope, java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables, java.util.Map<androidx.compose.ui.layout.Measurable,androidx.compose.ui.layout.Placeable> placeableMap);
+    method @Deprecated public final long performMeasure(long constraints, androidx.compose.ui.unit.LayoutDirection layoutDirection, androidx.constraintlayout.compose.ConstraintSet constraintSet, java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables, int optimizationLevel);
+    method public final long performMeasure(long constraints, androidx.compose.ui.unit.LayoutDirection layoutDirection, androidx.constraintlayout.compose.ConstraintSet constraintSet, java.util.List<? extends androidx.compose.ui.layout.Measurable> measurables, java.util.Map<androidx.compose.ui.layout.Measurable,androidx.compose.ui.layout.Placeable> placeableMap, int optimizationLevel);
     method public final void setForcedScaleFactor(float);
     method protected final void setLayoutInformationReceiver(androidx.constraintlayout.compose.LayoutInformationReceiver?);
+    method protected final void setPlaceables(java.util.Map<androidx.compose.ui.layout.Measurable,androidx.compose.ui.layout.Placeable>);
     property public final float forcedScaleFactor;
-    property protected final java.util.Map<androidx.compose.ui.layout.Measurable,androidx.constraintlayout.core.state.WidgetFrame> frameCache;
+    property @Deprecated protected final java.util.Map<androidx.compose.ui.layout.Measurable,androidx.constraintlayout.core.state.WidgetFrame> frameCache;
+    property protected final java.util.Map<java.lang.String,androidx.constraintlayout.core.state.WidgetFrame> frameCache2;
     property public final int layoutCurrentHeight;
     property public final int layoutCurrentWidth;
     property protected final androidx.constraintlayout.compose.LayoutInformationReceiver? layoutInformationReceiver;
diff --git a/constraintlayout/constraintlayout-compose/build.gradle b/constraintlayout/constraintlayout-compose/build.gradle
index 333e65d..970db03 100644
--- a/constraintlayout/constraintlayout-compose/build.gradle
+++ b/constraintlayout/constraintlayout-compose/build.gradle
@@ -83,7 +83,6 @@
                 implementation(project(":compose:material:material"))
                 implementation("androidx.compose.material:material-icons-core:1.6.7")
                 implementation(project(":compose:ui:ui-test-junit4"))
-                implementation(project(":compose:ui:ui-test-manifest"))
                 implementation(project(":compose:test-utils"))
             }
         }
diff --git a/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/ConstraintLayoutTest.kt b/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/ConstraintLayoutTest.kt
index e7f7289..c6ccca1 100644
--- a/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/ConstraintLayoutTest.kt
+++ b/constraintlayout/constraintlayout-compose/src/androidInstrumentedTest/kotlin/androidx/constraintlayout/compose/ConstraintLayoutTest.kt
@@ -44,6 +44,7 @@
 import androidx.compose.ui.graphics.asAndroidBitmap
 import androidx.compose.ui.graphics.toArgb
 import androidx.compose.ui.layout.FirstBaseline
+import androidx.compose.ui.layout.LookaheadScope
 import androidx.compose.ui.layout.boundsInParent
 import androidx.compose.ui.layout.layout
 import androidx.compose.ui.layout.layoutId
@@ -2454,6 +2455,138 @@
             assertEquals(IntSize(rootSizePx.fastRoundToInt(), 0), layoutSize)
         }
 
+    @Test
+    fun testToggleVisibilityWithFillConstraintsWidth() =
+        with(rule.density) {
+            val rootSizePx = 100f
+
+            var toggleVisibility by mutableStateOf(false)
+
+            rule.setContent {
+                // Regression test, modify only dimensions if necessary
+                ConstraintLayout(modifier = Modifier.size(rootSizePx.toDp())) {
+                    val (titleRef, detailRef) = createRefs()
+                    Box(
+                        modifier =
+                            Modifier.background(Color.Cyan).testTag("box1").constrainAs(detailRef) {
+                                centerHorizontallyTo(parent)
+
+                                width = Dimension.fillToConstraints
+                                height = rootSizePx.toDp().asDimension()
+
+                                visibility =
+                                    if (!toggleVisibility) Visibility.Gone else Visibility.Visible
+                            }
+                    )
+                    Box(
+                        modifier =
+                            Modifier.background(Color.Red).testTag("box2").constrainAs(titleRef) {
+                                centerHorizontallyTo(parent)
+
+                                width = Dimension.fillToConstraints
+                                height = rootSizePx.toDp().asDimension()
+
+                                visibility =
+                                    if (toggleVisibility) Visibility.Gone else Visibility.Visible
+                            }
+                    )
+                }
+            }
+            rule.waitForIdle()
+
+            rule.onNodeWithTag("box1").apply {
+                assertWidthIsEqualTo(Dp.Unspecified)
+                assertHeightIsEqualTo(Dp.Unspecified)
+            }
+            rule.onNodeWithTag("box2").apply {
+                assertWidthIsEqualTo(rootSizePx.toDp())
+                assertHeightIsEqualTo(rootSizePx.toDp())
+            }
+
+            toggleVisibility = !toggleVisibility
+            rule.waitForIdle()
+
+            rule.onNodeWithTag("box1").apply {
+                assertWidthIsEqualTo(rootSizePx.toDp())
+                assertHeightIsEqualTo(rootSizePx.toDp())
+            }
+            rule.onNodeWithTag("box2").apply {
+                assertWidthIsEqualTo(Dp.Unspecified)
+                assertHeightIsEqualTo(Dp.Unspecified)
+            }
+            Unit // Test expects to return Unit
+        }
+
+    @Test
+    fun testToggleVisibilityWithFillConstraintsWidth_underLookahead() =
+        with(rule.density) {
+            val rootSizePx = 100f
+
+            var toggleVisibility by mutableStateOf(false)
+
+            rule.setContent {
+                LookaheadScope {
+                    // Regression test, modify only dimensions if necessary
+                    ConstraintLayout(modifier = Modifier.size(rootSizePx.toDp())) {
+                        val (titleRef, detailRef) = createRefs()
+                        Box(
+                            modifier =
+                                Modifier.background(Color.Cyan).testTag("box1").constrainAs(
+                                    detailRef
+                                ) {
+                                    centerHorizontallyTo(parent)
+
+                                    width = Dimension.fillToConstraints
+                                    height = rootSizePx.toDp().asDimension()
+
+                                    visibility =
+                                        if (!toggleVisibility) Visibility.Gone
+                                        else Visibility.Visible
+                                }
+                        )
+                        Box(
+                            modifier =
+                                Modifier.background(Color.Red).testTag("box2").constrainAs(
+                                    titleRef
+                                ) {
+                                    centerHorizontallyTo(parent)
+
+                                    width = Dimension.fillToConstraints
+                                    height = rootSizePx.toDp().asDimension()
+
+                                    visibility =
+                                        if (toggleVisibility) Visibility.Gone
+                                        else Visibility.Visible
+                                }
+                        )
+                    }
+                }
+            }
+            rule.waitForIdle()
+
+            rule.onNodeWithTag("box1").apply {
+                assertWidthIsEqualTo(Dp.Unspecified)
+                assertHeightIsEqualTo(Dp.Unspecified)
+            }
+            rule.onNodeWithTag("box2").apply {
+                assertWidthIsEqualTo(rootSizePx.toDp())
+                assertHeightIsEqualTo(rootSizePx.toDp())
+            }
+
+            toggleVisibility = !toggleVisibility
+            rule.waitForIdle()
+
+            rule.onNodeWithTag("box1").apply {
+                assertWidthIsEqualTo(rootSizePx.toDp())
+                assertHeightIsEqualTo(rootSizePx.toDp())
+            }
+            rule.onNodeWithTag("box2").apply {
+                assertWidthIsEqualTo(Dp.Unspecified)
+                assertHeightIsEqualTo(Dp.Unspecified)
+            }
+            Unit // Test expects to return Unit
+        }
+
     /**
      * Provides a list constraints combination for horizontal anchors: `start`, `end`,
      * `absoluteLeft`, `absoluteRight`.
diff --git a/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayout.kt b/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayout.kt
index 04acd28..da91f65 100644
--- a/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayout.kt
+++ b/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayout.kt
@@ -420,21 +420,27 @@
     val contentTracker = remember { mutableStateOf(Unit, neverEqualPolicy()) }
 
     val measurePolicy = MeasurePolicy { measurables, constraints ->
+        // Map to properly capture Placeables across Measure and Layout passes
+        val placeableMap = mutableMapOf<Measurable, Placeable>()
+
+        // Call to invalidate measure on content recomposition
         contentTracker.value
+
         val layoutSize =
             measurer.performMeasure(
-                constraints,
-                layoutDirection,
-                constraintSet,
-                measurables,
-                optimizationLevel
+                constraints = constraints,
+                layoutDirection = layoutDirection,
+                constraintSet = constraintSet,
+                measurables = measurables,
+                placeableMap = placeableMap,
+                optimizationLevel = optimizationLevel
             )
         // We read the remeasurement requester state, to request remeasure when the value
         // changes. This will happen when the scope helpers are changing at recomposition.
         remeasureRequesterState.value
 
         layout(layoutSize.width, layoutSize.height) {
-            with(measurer) { performLayout(measurables) }
+            with(measurer) { performLayout(measurables = measurables, placeableMap = placeableMap) }
         }
     }
 
@@ -805,17 +811,25 @@
             true
         }
         val measurePolicy = MeasurePolicy { measurables, constraints ->
+            // Map to properly capture Placeables across Measure and Layout passes
+            val placeableMap = mutableMapOf<Measurable, Placeable>()
+
+            // Call to invalidate measure on content recomposition
             contentTracker.value
+
             val layoutSize =
                 measurer.performMeasure(
-                    constraints,
-                    layoutDirection,
-                    constraintSet,
-                    measurables,
-                    optimizationLevel
+                    constraints = constraints,
+                    layoutDirection = layoutDirection,
+                    constraintSet = constraintSet,
+                    measurables = measurables,
+                    placeableMap = placeableMap,
+                    optimizationLevel = optimizationLevel
                 )
             layout(layoutSize.width, layoutSize.height) {
-                with(measurer) { performLayout(measurables) }
+                with(measurer) {
+                    performLayout(measurables = measurables, placeableMap = placeableMap)
+                }
             }
         }
         if (constraintSet is EditableJSONLayout) {
@@ -1611,9 +1625,22 @@
     private var computedLayoutResult: String = ""
     protected var layoutInformationReceiver: LayoutInformationReceiver? = null
     protected val root = ConstraintWidgetContainer(0, 0).also { it.measurer = this }
-    protected val placeables = mutableMapOf<Measurable, Placeable>()
+
+    /**
+     * Due to Lookahead measure pass, the object used to measure and place should not be
+     * instantiated internally, instead, should be instantiated within the MeasurePolicy call, and
+     * then passed to update this variable, at each the measure and layout passes.
+     */
+    protected var placeables = mutableMapOf<Measurable, Placeable>()
     private val lastMeasures = mutableMapOf<String, Array<Int>>()
-    protected val frameCache = mutableMapOf<Measurable, WidgetFrame>()
+
+    @Suppress("unused") // Exists for compatibility.
+    @Deprecated(
+        message = "Should not reference a Measurable.",
+        replaceWith = ReplaceWith("frameCache2")
+    )
+    protected val frameCache = emptyMap<Measurable, WidgetFrame>()
+    protected val frameCache2 = mutableMapOf<String, WidgetFrame>()
 
     protected val state = State(density)
 
@@ -1790,7 +1817,7 @@
                 val id = measurable.layoutId ?: measurable.constraintLayoutId
                 child.stringId = id?.toString()
             }
-            val frame = frameCache[measurable]?.widget?.frame
+            val frame = frameCache2[measurable.anyOrNullId]?.widget?.frame
             if (frame == null) {
                 continue
             }
@@ -1867,13 +1894,33 @@
         this[2] = measure.measuredBaseline
     }
 
+    @Suppress("DeprecatedCallableAddReplaceWith") // Requires manual replacement
+    @Deprecated("Should receive placeable Map from caller.")
     fun performMeasure(
         constraints: Constraints,
         layoutDirection: LayoutDirection,
         constraintSet: ConstraintSet,
         measurables: List<Measurable>,
         optimizationLevel: Int
+    ): IntSize =
+        performMeasure(
+            constraints = constraints,
+            layoutDirection = layoutDirection,
+            constraintSet = constraintSet,
+            measurables = measurables,
+            placeableMap = placeables,
+            optimizationLevel = optimizationLevel
+        )
+
+    fun performMeasure(
+        constraints: Constraints,
+        layoutDirection: LayoutDirection,
+        constraintSet: ConstraintSet,
+        measurables: List<Measurable>,
+        placeableMap: MutableMap<Measurable, Placeable>,
+        optimizationLevel: Int
     ): IntSize {
+        this.placeables = placeableMap
         if (measurables.isEmpty()) {
             // TODO(b/335524398): Behavior with zero children is unexpected. It's also inconsistent
             //      with ViewGroup, so this is a workaround to handle those cases the way it seems
@@ -1938,7 +1985,7 @@
     internal fun resetMeasureState() {
         placeables.clear()
         lastMeasures.clear()
-        frameCache.clear()
+        frameCache2.clear()
     }
 
     protected fun applyRootSize(constraints: Constraints) {
@@ -1977,37 +2024,30 @@
         }
     }
 
+    @Suppress("DeprecatedCallableAddReplaceWith") // Requires manual replacement
+    @Deprecated("Should receive placeable Map from caller.")
     fun Placeable.PlacementScope.performLayout(measurables: List<Measurable>) {
-        if (frameCache.isEmpty()) {
+        performLayout(measurables, placeables)
+    }
+
+    fun Placeable.PlacementScope.performLayout(
+        measurables: List<Measurable>,
+        placeableMap: MutableMap<Measurable, Placeable>,
+    ) {
+        if (frameCache2.isEmpty()) {
             root.children.fastForEach { child ->
                 val measurable = child.companionWidget
                 if (measurable !is Measurable) return@fastForEach
                 val frame = WidgetFrame(child.frame.update())
-                frameCache[measurable] = frame
+                frameCache2[measurable.anyOrNullId] = frame
             }
         }
         measurables.fastForEach { measurable ->
-            val matchedMeasurable: Measurable =
-                if (!frameCache.containsKey(measurable)) {
-                    // TODO: Workaround for lookaheadLayout, the measurable is a different instance
-                    frameCache.keys.firstOrNull {
-                        it.layoutId != null && it.layoutId == measurable.layoutId
-                    } ?: return@fastForEach
-                } else {
-                    measurable
-                }
-            val frame = frameCache[matchedMeasurable] ?: return
-            val placeable = placeables[matchedMeasurable] ?: return
-            if (!frameCache.containsKey(measurable)) {
-                // TODO: Workaround for lookaheadLayout, the measurable is a different instance and
-                //   the placeable should be a result of the given measurable
-                placeWithFrameTransform(
-                    measurable.measure(Constraints.fixed(placeable.width, placeable.height)),
-                    frame
-                )
-            } else {
-                placeWithFrameTransform(placeable, frame)
-            }
+            val frame = frameCache2[measurable.anyOrNullId] ?: return@fastForEach
+            // Don't use `placeables` map from Measurer, is not guaranteed to correspond to this
+            // Layout pass
+            val placeable = placeableMap[measurable] ?: return@fastForEach
+            placeWithFrameTransform(placeable, frame)
         }
         if (layoutInformationReceiver?.getLayoutInformationMode() == LayoutInfoFlags.BOUNDS) {
             computeLayoutResult()
@@ -2056,7 +2096,8 @@
                 IntIntPair(constraintWidget.measuredWidth, constraintWidget.measuredHeight)
             }
             measurable is Measurable -> {
-                val result = measurable.measure(constraints).also { placeables[measurable] = it }
+                val result = measurable.measure(constraints)
+                placeables[measurable] = result
                 IntIntPair(result.width, result.height)
             }
             else -> {
@@ -2275,6 +2316,10 @@
     }
 }
 
+/** Returns either [LayoutIdParentData] or [ConstraintLayoutParentData] id. Otherwise "null". */
+internal val Measurable.anyOrNullId: String
+    get() = (this.layoutId ?: this.constraintLayoutId)?.toString() ?: "null"
+
 internal typealias SolverDimension = androidx.constraintlayout.core.state.Dimension
 
 internal typealias SolverState = androidx.constraintlayout.core.state.State
diff --git a/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/LateMotionLayout.kt b/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/LateMotionLayout.kt
index 8287e20..46b7f27 100644
--- a/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/LateMotionLayout.kt
+++ b/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/LateMotionLayout.kt
@@ -25,8 +25,10 @@
 import androidx.compose.runtime.mutableIntStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.Measurable
 import androidx.compose.ui.layout.MeasurePolicy
 import androidx.compose.ui.layout.MultiMeasureLayout
+import androidx.compose.ui.layout.Placeable
 import androidx.compose.ui.node.Ref
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.semantics.semantics
@@ -117,6 +119,9 @@
     measurer: MotionMeasurer,
     optimizationLevel: Int,
 ): MeasurePolicy = MeasurePolicy { measurables, constraints ->
+    // Map to properly capture Placeables across Measure and Layout passes
+    val placeableMap = mutableMapOf<Measurable, Placeable>()
+
     // Do a state read, to guarantee that we control measure when the content recomposes without
     // notifying our Composable caller
     contentTracker.value
@@ -129,6 +134,7 @@
             constraintSetEnd = endProvider(),
             transition = TransitionImpl.EMPTY,
             measurables = measurables,
+            placeableMap = placeableMap,
             optimizationLevel = optimizationLevel,
             progress = motionProgress.value,
             compositionSource = compositionSource.value ?: CompositionSource.Unknown,
@@ -136,5 +142,7 @@
         )
     compositionSource.value = CompositionSource.Unknown // Reset after measuring
 
-    layout(layoutSize.width, layoutSize.height) { with(measurer) { performLayout(measurables) } }
+    layout(layoutSize.width, layoutSize.height) {
+        with(measurer) { performLayout(measurables = measurables, placeableMap = placeableMap) }
+    }
 }
diff --git a/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/MotionLayout.kt b/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/MotionLayout.kt
index 280dca8..8b0e892 100644
--- a/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/MotionLayout.kt
+++ b/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/MotionLayout.kt
@@ -42,8 +42,10 @@
 import androidx.compose.ui.draw.scale
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.layout.Measurable
 import androidx.compose.ui.layout.MeasurePolicy
 import androidx.compose.ui.layout.MultiMeasureLayout
+import androidx.compose.ui.layout.Placeable
 import androidx.compose.ui.layout.onGloballyPositioned
 import androidx.compose.ui.layout.onPlaced
 import androidx.compose.ui.node.Ref
@@ -978,6 +980,9 @@
     optimizationLevel: Int,
     invalidationStrategy: InvalidationStrategy
 ): MeasurePolicy = MeasurePolicy { measurables, constraints ->
+    // Map to properly capture Placeables across Measure and Layout passes
+    val placeableMap = mutableMapOf<Measurable, Placeable>()
+
     // Do a state read, to guarantee that we control measure when the content recomposes without
     // notifying our Composable caller
     contentTracker.value
@@ -990,6 +995,7 @@
             constraintSetEnd = constraintSetEnd,
             transition = transition,
             measurables = measurables,
+            placeableMap = placeableMap,
             optimizationLevel = optimizationLevel,
             progress = motionProgress.floatValue,
             compositionSource = compositionSource.value ?: CompositionSource.Unknown,
@@ -997,7 +1003,9 @@
         )
     compositionSource.value = CompositionSource.Unknown // Reset after measuring
 
-    layout(layoutSize.width, layoutSize.height) { with(measurer) { performLayout(measurables) } }
+    layout(layoutSize.width, layoutSize.height) {
+        with(measurer) { performLayout(measurables = measurables, placeableMap = placeableMap) }
+    }
 }
 
 /**
diff --git a/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/MotionMeasurer.kt b/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/MotionMeasurer.kt
index ecd807c..b077a37 100644
--- a/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/MotionMeasurer.kt
+++ b/constraintlayout/constraintlayout-compose/src/androidMain/kotlin/androidx/constraintlayout/compose/MotionMeasurer.kt
@@ -27,6 +27,7 @@
 import androidx.compose.ui.graphics.drawscope.translate
 import androidx.compose.ui.graphics.nativeCanvas
 import androidx.compose.ui.layout.Measurable
+import androidx.compose.ui.layout.Placeable
 import androidx.compose.ui.layout.layoutId
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.Density
@@ -84,11 +85,13 @@
         constraintSetEnd: ConstraintSet,
         @SuppressWarnings("HiddenTypeParameter") transition: TransitionImpl,
         measurables: List<Measurable>,
+        placeableMap: MutableMap<Measurable, Placeable>,
         optimizationLevel: Int,
         progress: Float,
         compositionSource: CompositionSource,
         invalidateOnConstraintsCallback: ShouldInvalidateCallback?
     ): IntSize {
+        placeables = placeableMap
         val needsRemeasure =
             needsRemeasure(
                 constraints = constraints,
@@ -139,7 +142,7 @@
         source: CompositionSource,
         invalidateOnConstraintsCallback: ShouldInvalidateCallback?
     ): Boolean {
-        if (this.transition.isEmpty || frameCache.isEmpty()) {
+        if (this.transition.isEmpty || frameCache2.isEmpty()) {
             // Nothing measured (by MotionMeasurer)
             return true
         }
@@ -226,7 +229,7 @@
                 measurable.measure(
                     Constraints.fixed(interpolatedFrame.width(), interpolatedFrame.height())
                 )
-            frameCache[measurable] = interpolatedFrame
+            frameCache2[measurable.anyOrNullId] = interpolatedFrame
         }
 
         if (layoutInformationReceiver?.getLayoutInformationMode() == LayoutInfoFlags.BOUNDS) {
@@ -539,7 +542,7 @@
 
     fun clearConstraintSets() {
         transition.clear()
-        frameCache.clear()
+        frameCache2.clear()
     }
 
     @Suppress("UnavailableSymbol")
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/CallsManager.kt b/core/core-telecom/src/main/java/androidx/core/telecom/CallsManager.kt
index f84b88d..93260ab 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/CallsManager.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/CallsManager.kt
@@ -51,6 +51,7 @@
 import androidx.core.telecom.internal.JetpackConnectionService
 import androidx.core.telecom.internal.PreCallEndpointsUpdater
 import androidx.core.telecom.internal.utils.Utils
+import androidx.core.telecom.internal.utils.Utils.Companion.hasBluetoothPermissions
 import androidx.core.telecom.internal.utils.Utils.Companion.remapJetpackCapsToPlatformCaps
 import androidx.core.telecom.util.ExperimentalAppActions
 import java.util.UUID
@@ -356,10 +357,17 @@
      * Continuously streams available call audio endpoints that can be used for a new call session.
      * This API leverages [callbackFlow] to emit updates as the available audio endpoints change.
      *
-     * **Bluetooth Permissions:** The [android.Manifest.permission.BLUETOOTH_CONNECT] runtime
-     * permission is essential when multiple bluetooth devices are connected. Granting this
-     * permission allows the API to display the names of multiple connected Bluetooth devices.
-     * Without this permission, only the active Bluetooth device will be surfaced.
+     * **Bluetooth Permissions**:
+     * * For API level 31 and above: The [android.Manifest.permission.BLUETOOTH_CONNECT] runtime
+     *   permission is highly recommended.
+     * * For API levels 28-30: The following runtime permissions are highly recommended:
+     *     * [android.Manifest.permission.BLUETOOTH] - Allows apps to view Bluetooth information.
+     *     * [android.Manifest.permission.BLUETOOTH_ADMIN] - Allows apps to connect to paired
+     *       devices.
+     *
+     * For all API levels: Granting these permissions allows the API to display the names of
+     * multiple connected Bluetooth devices. Without these permissions, only the active Bluetooth
+     * device will be surfaced.
      *
      * **Coroutine Usage and Cleanup:** The returned [Flow] from this [callbackFlow] should be
      * collected within a [kotlinx.coroutines.CoroutineScope]. To properly manage resources and
@@ -380,10 +388,15 @@
         val audioDeviceListener = AudioDeviceListener(mContext, callEndpointsUpdater, id)
         // register a bluetooth listener to surface connected bluetooth devices instead of just
         // the active bluetooth device
-        val bluetoothProfileListener = BluetoothProfileListener(mContext, callEndpointsUpdater, id)
+        var bluetoothProfileListener =
+            if (hasBluetoothPermissions(mContext)) {
+                BluetoothProfileListener(mContext, callEndpointsUpdater, id)
+            } else {
+                null
+            }
         awaitClose {
             Log.i(TAG, "getAvailableStartingCallEndpoints: awaitClose")
-            bluetoothProfileListener.close()
+            bluetoothProfileListener?.close()
             audioDeviceListener.close()
             CallEndpointUuidTracker.endSession(id)
         }
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/internal/utils/Utils.kt b/core/core-telecom/src/main/java/androidx/core/telecom/internal/utils/Utils.kt
index 4f370f87..f5e8613 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/internal/utils/Utils.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/internal/utils/Utils.kt
@@ -16,6 +16,8 @@
 
 package androidx.core.telecom.internal.utils
 
+import android.content.Context
+import android.content.pm.PackageManager
 import android.os.Build.VERSION
 import android.os.Build.VERSION_CODES
 import android.os.Bundle
@@ -24,6 +26,7 @@
 import android.telecom.TelecomManager
 import android.util.Log
 import androidx.annotation.RequiresApi
+import androidx.core.content.ContextCompat
 import androidx.core.telecom.CallAttributesCompat
 import androidx.core.telecom.CallsManager
 
@@ -81,6 +84,33 @@
             return VERSION.SDK_INT >= VERSION_CODES.P
         }
 
+        /**
+         * Checks if the application has the necessary Bluetooth permissions.
+         *
+         * For API level 31 and above, this checks for BLUETOOTH_CONNECT permission. For API levels
+         * 28-30, it checks for BLUETOOTH and BLUETOOTH_ADMIN permissions.
+         *
+         * @param context The application context.
+         * @return `true` if the required permissions are granted, `false` otherwise.
+         */
+        fun hasBluetoothPermissions(context: Context): Boolean {
+            return if (VERSION.SDK_INT >= VERSION_CODES.S) {
+                // API level 31+
+                ContextCompat.checkSelfPermission(
+                    context,
+                    android.Manifest.permission.BLUETOOTH_CONNECT
+                ) == PackageManager.PERMISSION_GRANTED
+            } else {
+                // API levels 28-30
+                ContextCompat.checkSelfPermission(context, android.Manifest.permission.BLUETOOTH) ==
+                    PackageManager.PERMISSION_GRANTED ||
+                    ContextCompat.checkSelfPermission(
+                        context,
+                        android.Manifest.permission.BLUETOOTH_ADMIN
+                    ) == PackageManager.PERMISSION_GRANTED
+            }
+        }
+
         @RequiresApi(VERSION_CODES.O)
         fun remapJetpackCapsToPlatformCaps(
             @CallsManager.Companion.Capability clientBitmapSelection: Int
diff --git a/core/core/api/current.txt b/core/core/api/current.txt
index 21ac7e4..45edc44 100644
--- a/core/core/api/current.txt
+++ b/core/core/api/current.txt
@@ -1653,9 +1653,13 @@
     method public android.view.Display![] getDisplays();
     method public android.view.Display![] getDisplays(String?);
     method public static androidx.core.hardware.display.DisplayManagerCompat getInstance(android.content.Context);
+    field @SuppressCompatibility @androidx.core.hardware.display.ExperimentalDisplayApi public static final String DISPLAY_CATEGORY_BUILT_IN_DISPLAYS = "android.hardware.display.category.BUILT_IN_DISPLAYS";
     field public static final String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
   }
 
+  @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.WARNING) @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalDisplayApi {
+  }
+
 }
 
 package androidx.core.location {
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index 4b7cff1..46e97fe 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -1967,9 +1967,13 @@
     method public android.view.Display![] getDisplays();
     method public android.view.Display![] getDisplays(String?);
     method public static androidx.core.hardware.display.DisplayManagerCompat getInstance(android.content.Context);
+    field @SuppressCompatibility @androidx.core.hardware.display.ExperimentalDisplayApi public static final String DISPLAY_CATEGORY_BUILT_IN_DISPLAYS = "android.hardware.display.category.BUILT_IN_DISPLAYS";
     field public static final String DISPLAY_CATEGORY_PRESENTATION = "android.hardware.display.category.PRESENTATION";
   }
 
+  @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.WARNING) @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalDisplayApi {
+  }
+
 }
 
 package androidx.core.hardware.fingerprint {
diff --git a/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java b/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
index 5f1ca3a..8f4ae79 100644
--- a/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
@@ -73,6 +73,8 @@
 import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.SmallTest;
 
+import com.google.common.collect.Lists;
+
 import org.jetbrains.annotations.NotNull;
 import org.junit.Before;
 import org.junit.Test;
@@ -2456,7 +2458,7 @@
     }
 
     @Test
-    @SdkSuppress(minSdkVersion = 20, maxSdkVersion = 32) // Failing on API 33 emulator, b/355507696
+    @SdkSuppress(minSdkVersion = 20)
     public void testCallStyle_preservesCustomActions() {
         PendingIntent hangupIntent = createIntent("hangup");
         Person person = new Person.Builder().setName("test name").build();
@@ -2473,17 +2475,31 @@
                 .setStyle(callStyle)
                 .build();
 
-        Notification.Action[] resultActions = notification.actions;
-        assertThat(resultActions).hasLength(2); // Hang up + custom (fits on all Android versions).
-        // But ordering is different per version.
-        if (Build.VERSION.SDK_INT <= 30 || Build.VERSION.SDK_INT >= 34) {
-            assertThat(resultActions[0].title.toString()).isEqualTo(
-                    mContext.getString(R.string.call_notification_hang_up_action));
-            assertThat(resultActions[1].title.toString()).isEqualTo(customAction.title.toString());
+        // Actions as Hang up + Custom (fits on all Android versions).
+        assertThat(notification.actions).hasLength(2);
+
+        // But order is different per Android version. CallStyle was introduced in SDK 31 and
+        // placed custom actions first. A QPR of SDK 33 switched to system actions first. Pre-31
+        // there is no native CallStyle, so the Compat version uses the newer ordering there too.
+        List<String> actionTitles = Lists.transform(Arrays.asList(notification.actions),
+                a -> a.title.toString());
+        if (Build.VERSION.SDK_INT < 31 || Build.VERSION.SDK_INT >= 34) {
+            assertThat(actionTitles).containsExactly(
+                            mContext.getString(R.string.call_notification_hang_up_action),
+                            customAction.title.toString())
+                    .inOrder();
+        } else if (Build.VERSION.SDK_INT >= 31 && Build.VERSION.SDK_INT <= 32) {
+            assertThat(actionTitles).containsExactly(
+                            customAction.title.toString(),
+                            mContext.getString(R.string.call_notification_hang_up_action))
+                    .inOrder();
+        } else if (Build.VERSION.SDK_INT == 33) {
+            // Could be either, so check presence but not ordering.
+            assertThat(actionTitles).containsExactly(
+                            mContext.getString(R.string.call_notification_hang_up_action),
+                            customAction.title.toString());
         } else {
-            assertThat(resultActions[0].title.toString()).isEqualTo(customAction.title.toString());
-            assertThat(resultActions[1].title.toString()).isEqualTo(
-                    mContext.getString(R.string.call_notification_hang_up_action));
+            throw new AssertionError("All SDK_INT values are covered!");
         }
     }
 
diff --git a/core/core/src/androidTest/java/androidx/core/hardware/display/DisplayManagerCompatTest.kt b/core/core/src/androidTest/java/androidx/core/hardware/display/DisplayManagerCompatTest.kt
index 90e8665..e271a8d 100644
--- a/core/core/src/androidTest/java/androidx/core/hardware/display/DisplayManagerCompatTest.kt
+++ b/core/core/src/androidTest/java/androidx/core/hardware/display/DisplayManagerCompatTest.kt
@@ -17,10 +17,17 @@
 package androidx.core.hardware.display
 
 import android.content.Context
+import android.os.Build
+import android.view.Display
+import androidx.core.hardware.display.DisplayManagerCompat.DISPLAY_CATEGORY_ALL
+import androidx.core.hardware.display.DisplayManagerCompat.DISPLAY_CATEGORY_BUILT_IN_DISPLAYS
+import androidx.core.hardware.display.DisplayManagerCompat.DISPLAY_TYPE_INTERNAL
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import androidx.test.platform.app.InstrumentationRegistry
 import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Assume.assumeTrue
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -30,10 +37,12 @@
 class DisplayManagerCompatTest {
 
     private lateinit var context: Context
+    private lateinit var displayManager: DisplayManagerCompat
 
     @Before
     fun setup() {
         context = InstrumentationRegistry.getInstrumentation().context
+        displayManager = DisplayManagerCompat.getInstance(context)
     }
 
     @Test
@@ -44,7 +53,6 @@
 
     @Test
     fun testGetDisplay() {
-        val displayManager = DisplayManagerCompat.getInstance(context)
         assertNotNull(displayManager)
 
         val displays = displayManager.displays
@@ -57,4 +65,41 @@
             assertNotNull(actualDisplay)
         }
     }
+
+    @OptIn(ExperimentalDisplayApi::class)
+    @Test
+    fun testReportedBuiltInDisplaysShowInBuiltInCategory() {
+        val activeBuiltInDisplays = displayManager.displays.filter(this::isDisplayInternal)
+        val builtInDisplays = displayManager.getDisplays(DISPLAY_CATEGORY_BUILT_IN_DISPLAYS)
+
+        activeBuiltInDisplays.forEach { display ->
+            assertTrue(
+                "Expected display to be in built in displays Display: $display " +
+                    "builtInDisplays $builtInDisplays",
+                builtInDisplays.contains(display)
+            )
+        }
+    }
+
+    @OptIn(ExperimentalDisplayApi::class)
+    @Test
+    fun testAllBuiltInDisplaysAreReported() {
+        assumeTrue(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S_V2)
+
+        val activeBuiltInDisplays =
+            displayManager.getDisplays(DISPLAY_CATEGORY_ALL).filter(this::isDisplayInternal)
+        val builtInDisplays = displayManager.getDisplays(DISPLAY_CATEGORY_BUILT_IN_DISPLAYS)
+
+        activeBuiltInDisplays.forEach { display ->
+            assertTrue(
+                "Expected display to be in built in displays Display: $display " +
+                    "builtInDisplays $builtInDisplays",
+                builtInDisplays.contains(display)
+            )
+        }
+    }
+
+    private fun isDisplayInternal(display: Display): Boolean {
+        return DisplayManagerCompat.getTypeCompat(display) == DISPLAY_TYPE_INTERNAL
+    }
 }
diff --git a/core/core/src/main/java/androidx/core/app/ActivityOptionsCompat.java b/core/core/src/main/java/androidx/core/app/ActivityOptionsCompat.java
index 3bed9b4..ba819f6 100644
--- a/core/core/src/main/java/androidx/core/app/ActivityOptionsCompat.java
+++ b/core/core/src/main/java/androidx/core/app/ActivityOptionsCompat.java
@@ -321,7 +321,7 @@
             if (Build.VERSION.SDK_INT >= 26) {
                 return mActivityOptions.getLaunchDisplayId();
             } else {
-                return 0;
+                return Display.INVALID_DISPLAY;
             }
         }
 
diff --git a/core/core/src/main/java/androidx/core/hardware/display/DisplayManagerCompat.java b/core/core/src/main/java/androidx/core/hardware/display/DisplayManagerCompat.java
index 49a4630..a3fc28b 100644
--- a/core/core/src/main/java/androidx/core/hardware/display/DisplayManagerCompat.java
+++ b/core/core/src/main/java/androidx/core/hardware/display/DisplayManagerCompat.java
@@ -16,20 +16,43 @@
 
 package androidx.core.hardware.display;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.hardware.display.DisplayManager;
+import android.os.Build;
 import android.view.Display;
 
+import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
+
 import org.jspecify.annotations.NonNull;
 import org.jspecify.annotations.Nullable;
 
+import java.util.Objects;
+
 /**
  * Helper for accessing features in {@link android.hardware.display.DisplayManager}.
  */
-@SuppressWarnings("unused")
 public final class DisplayManagerCompat {
 
     /**
+     * An internal category to get all the displays. This was added in SC_V2 and should only be
+     * used internally. This is not a stable API so it should not be make public.
+     */
+    @VisibleForTesting
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    static final String DISPLAY_CATEGORY_ALL =
+            "android.hardware.display.category.ALL_INCLUDING_DISABLED";
+
+    /**
+     * An internal copy of the type from the platform. This was added in SDK 17 and should only be
+     * used internally. This is not a stable API so it should not be made public.
+     */
+    @VisibleForTesting
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    static final int DISPLAY_TYPE_INTERNAL = 1;
+
+    /**
      * Display category: Presentation displays.
      * <p>
      * This category can be used to identify secondary displays that are suitable for
@@ -43,6 +66,17 @@
     public static final String DISPLAY_CATEGORY_PRESENTATION =
             "android.hardware.display.category.PRESENTATION";
 
+    /**
+     * Display category: Built in displays.
+     * <p>
+     *     This category can be used to identify displays that are built in to the device.
+     * </p>
+     * @see #getDisplays(String)
+     */
+    @ExperimentalDisplayApi
+    public static final String DISPLAY_CATEGORY_BUILT_IN_DISPLAYS =
+            "android.hardware.display.category.BUILT_IN_DISPLAYS";
+
     private final Context mContext;
 
     private DisplayManagerCompat(Context context) {
@@ -65,7 +99,6 @@
      * @param displayId The logical display id.
      * @return The display object, or null if there is no valid display with the given id.
      */
-    @SuppressWarnings("deprecation")
     public @Nullable Display getDisplay(int displayId) {
         DisplayManager displayManager =
                 (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
@@ -77,7 +110,6 @@
      *
      * @return An array containing all displays.
      */
-    @SuppressWarnings("deprecation")
     public Display @NonNull [] getDisplays() {
         return ((DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE)).getDisplays();
     }
@@ -98,8 +130,76 @@
      *
      * @see #DISPLAY_CATEGORY_PRESENTATION
      */
-    @SuppressWarnings("deprecation")
     public Display @NonNull [] getDisplays(@Nullable String category) {
-        return ((DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE)).getDisplays();
+        DisplayManager displayManager = (DisplayManager) mContext
+                .getSystemService(Context.DISPLAY_SERVICE);
+        if (DISPLAY_CATEGORY_BUILT_IN_DISPLAYS.equals(category)) {
+            return computeBuiltInDisplays(displayManager);
+        } else {
+            return ((DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE))
+                    .getDisplays(category);
+        }
+    }
+
+    /**
+     * Returns an array of built in displays, a built in display is one that is physically part
+     * of the device.
+     */
+    private static Display[] computeBuiltInDisplays(DisplayManager displayManager) {
+        final Display[] allDisplays;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S_V2) {
+            allDisplays = displayManager
+                    .getDisplays(DISPLAY_CATEGORY_ALL);
+
+        } else {
+            allDisplays = displayManager.getDisplays();
+        }
+        final int numberOfBuiltInDisplays =
+                numberOfDisplaysByType(DISPLAY_TYPE_INTERNAL, allDisplays);
+        final Display[] builtInDisplays = new Display[numberOfBuiltInDisplays];
+
+        int builtInDisplayIndex = 0;
+        for (int i = 0; i < allDisplays.length; i++) {
+            Display display = allDisplays[i];
+            if (DISPLAY_TYPE_INTERNAL == getTypeCompat(display)) {
+                builtInDisplays[builtInDisplayIndex] = display;
+                builtInDisplayIndex = builtInDisplayIndex + 1;
+            }
+        }
+        return builtInDisplays;
+    }
+
+    /**
+     * Returns the number of displays that have the matching type.
+     */
+    private static int numberOfDisplaysByType(int type, Display[] displays) {
+        int count = 0;
+        for (int i = 0; i < displays.length; i++) {
+            Display display = displays[i];
+            if (type == getTypeCompat(display)) {
+                count = count + 1;
+            }
+        }
+        return count;
+    }
+
+    /**
+     * An internal method to get the type of the display using reflection. This is used to support
+     * backporting of getting a display of a specific type. The preferred way to expose displays is
+     * to have a category and have developers get them using the category.
+     */
+    @SuppressLint("BanUncheckedReflection")
+    @VisibleForTesting
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    static int getTypeCompat(@NonNull Display display) {
+        try {
+            return (Integer) Objects.requireNonNull(
+                    Display.class.getMethod("getType").invoke(display)
+            );
+        } catch (NoSuchMethodException noSuchMethodException) {
+            return 0;
+        } catch (Exception exception) {
+            throw new RuntimeException(exception);
+        }
     }
 }
diff --git a/core/core/src/main/java/androidx/core/hardware/display/ExperimentalDisplayApi.kt b/core/core/src/main/java/androidx/core/hardware/display/ExperimentalDisplayApi.kt
new file mode 100644
index 0000000..7e833a7
--- /dev/null
+++ b/core/core/src/main/java/androidx/core/hardware/display/ExperimentalDisplayApi.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.core.hardware.display
+
+@MustBeDocumented
+@Retention(value = AnnotationRetention.BINARY)
+@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
+public annotation class ExperimentalDisplayApi
diff --git a/core/core/src/test/java/androidx/core/app/ActivityOptionsCompatTest.kt b/core/core/src/test/java/androidx/core/app/ActivityOptionsCompatTest.kt
index ba6a594..c57f0a1 100644
--- a/core/core/src/test/java/androidx/core/app/ActivityOptionsCompatTest.kt
+++ b/core/core/src/test/java/androidx/core/app/ActivityOptionsCompatTest.kt
@@ -49,4 +49,14 @@
         activityOptionsCompat.setLaunchDisplayId(0)
         assertEquals(activityOptionsCompat.launchDisplayId, 0)
     }
+
+    @Config(maxSdk = 25)
+    @Test
+    fun testGetLaunchDisplayId_pre26() {
+        val activityOptionsCompat = ActivityOptionsCompat.makeBasic()
+        assertEquals(activityOptionsCompat.launchDisplayId, Display.INVALID_DISPLAY)
+
+        activityOptionsCompat.launchDisplayId = 0
+        assertEquals(activityOptionsCompat.launchDisplayId, Display.INVALID_DISPLAY)
+    }
 }
diff --git a/development/importMaven/src/main/kotlin/androidx/build/importMaven/ArtifactResolver.kt b/development/importMaven/src/main/kotlin/androidx/build/importMaven/ArtifactResolver.kt
index d4c4c46..9354334 100644
--- a/development/importMaven/src/main/kotlin/androidx/build/importMaven/ArtifactResolver.kt
+++ b/development/importMaven/src/main/kotlin/androidx/build/importMaven/ArtifactResolver.kt
@@ -208,7 +208,7 @@
                 }
             }
             val resolutionList = configurations.map { configuration ->
-                resolveArtifacts(configuration, disableVerificationOnFailure = true)
+                resolveArtifacts(configuration)
             }
             val artifacts = resolutionList.flatMap { resolution ->
                 resolution.artifacts
@@ -222,41 +222,16 @@
         /**
          * Resolves the given configuration.
          * @param configuration The configuration to resolve
-         * @param disableVerificationOnFailure If set, this method will try to re-resolve the
-         *        configuration without dependency verification. This might be necessary if an
-         *        artifact is signed but the key is not registered in any of the public key servers.
          */
         private fun resolveArtifacts(
             configuration: Configuration,
-            disableVerificationOnFailure: Boolean
         ): ArtifactsResolutionResult {
-            return try {
-                val artifacts = configuration.incoming.artifactView {
-                    // We need to be lenient because we are requesting files that might not exist.
-                    // For example source.jar or .asc.
-                    it.lenient(true)
-                }.artifacts.artifacts.toList()
-                ArtifactsResolutionResult(artifacts.toList(), dependenciesPassedVerification = true)
-            } catch (verificationException: DependencyVerificationException) {
-                if (disableVerificationOnFailure) {
-                    val copy = configuration.copyRecursive().also {
-                        it.resolutionStrategy.disableDependencyVerification()
-                    }
-                    logger.warn {
-                        """
-Failed key verification for public servers, will retry without verification.
-${verificationException.message?.prependIndent("    ")}
-                        """
-                    }
-                    val artifacts = resolveArtifacts(copy, disableVerificationOnFailure = false)
-                    return ArtifactsResolutionResult(
-                        artifacts.artifacts,
-                        dependenciesPassedVerification = false
-                    )
-                } else {
-                    throw verificationException
-                }
-            }
+            val artifacts = configuration.incoming.artifactView {
+                // We need to be lenient because we are requesting files that might not exist.
+                // For example source.jar or .asc.
+                it.lenient(true)
+            }.artifacts.artifacts.toList()
+            return ArtifactsResolutionResult(artifacts.toList(), dependenciesPassedVerification = false)
         }
 
         /**
diff --git a/development/importMaven/src/main/kotlin/androidx/build/importMaven/Main.kt b/development/importMaven/src/main/kotlin/androidx/build/importMaven/Main.kt
index 363e0a4..7403a72 100644
--- a/development/importMaven/src/main/kotlin/androidx/build/importMaven/Main.kt
+++ b/development/importMaven/src/main/kotlin/androidx/build/importMaven/Main.kt
@@ -269,7 +269,9 @@
             if (!result.dependenciesPassedVerification) {
                 logger.warn(
                     """
-                   Our Gradle build won't trust any artifacts that are unsigned or are signed with new keys. To trust these artifacts, run `development/update-verification-metadata.sh
+                   Our Gradle build won't trust any artifacts that are unsigned or are signed with new keys.
+                   To trust these artifacts, you might need run `development/update-verification-metadata.sh`
+                   later if Gradle's dependency verification fails when you run a Gradle command. 
                    """.trimIndent()
                 )
             }
@@ -426,6 +428,11 @@
     )
 
 fun main(args: Array<String>) {
-    createCliCommands().main(args)
-    exitProcess(0)
+    try {
+        createCliCommands().main(args)
+        exitProcess(0)
+    } catch (e: Throwable) {
+        e.printStackTrace()
+        exitProcess(1)
+    }
 }
diff --git a/development/importMaven/src/main/kotlin/androidx/build/importMaven/ProjectService.kt b/development/importMaven/src/main/kotlin/androidx/build/importMaven/ProjectService.kt
index dd85164..27991f9 100644
--- a/development/importMaven/src/main/kotlin/androidx/build/importMaven/ProjectService.kt
+++ b/development/importMaven/src/main/kotlin/androidx/build/importMaven/ProjectService.kt
@@ -18,6 +18,7 @@
 
 import org.apache.logging.log4j.kotlin.logger
 import org.gradle.api.Project
+import org.gradle.api.artifacts.verification.DependencyVerificationMode
 import org.gradle.testfixtures.ProjectBuilder
 import java.io.File
 import java.util.UUID
@@ -44,6 +45,13 @@
             }
         ).withName("importMaven")
             .build()
+            .also {
+                // Enables us to download .asc files if they exist whilst not failing for
+                // dependencies that do not have the .asc file. Do not set the mode to OFF as that
+                // stops downloading .asc files even if they do exist
+                it.gradle.startParameter.dependencyVerificationMode =
+                    DependencyVerificationMode.LENIENT
+            }
     }
 
     private fun randomProjectFolder(): File {
diff --git a/development/update_studio.sh b/development/update_studio.sh
index d0ff902..d4b0ff3 100755
--- a/development/update_studio.sh
+++ b/development/update_studio.sh
@@ -15,8 +15,8 @@
 
 # Versions that the user should update when running this script
 echo Getting Studio version and link
-AGP_VERSION=${1:-8.9.0-alpha06}
-STUDIO_VERSION_STRING=${2:-"Android Studio Meerkat | 2024.3.1 Canary 6"}
+AGP_VERSION=${1:-8.9.0-alpha01}
+STUDIO_VERSION_STRING=${2:-"Android Studio Meerkat | 2024.3.1 Canary 1"}
 
 # Get studio version number from version name
 STUDIO_IFRAME_LINK=`curl "https://developer.android.com/studio/archive.html" | grep "<iframe " | sed "s/.* src=\"\([^\"]*\)\".*/\1/g"`
diff --git a/docs-tip-of-tree/build.gradle b/docs-tip-of-tree/build.gradle
index 6b26ac0..61b9230 100644
--- a/docs-tip-of-tree/build.gradle
+++ b/docs-tip-of-tree/build.gradle
@@ -21,9 +21,10 @@
     docs(project(":annotation:annotation-experimental"))
     docs(project(":appcompat:appcompat"))
     docs(project(":appcompat:appcompat-resources"))
-    docs(project(":appfunctions:appfunctions-agent-runtime"))
     docs(project(":appfunctions:appfunctions-app-runtime"))
     docs(project(":appfunctions:appfunctions-common"))
+    docs(project(":appfunctions:appfunctions-runtime"))
+    docs(project(":appfunctions:appfunctions-stubs"))
     docs(project(":appsearch:appsearch"))
     docs(project(":appsearch:appsearch-builtin-types"))
     docs(project(":appsearch:appsearch-ktx"))
@@ -269,6 +270,8 @@
     docs(project(":pdf:pdf-viewer"))
     docs(project(":pdf:pdf-viewer-fragment"))
     docs(project(":percentlayout:percentlayout"))
+    kmpDocs(project(":performance:performance-annotation"))
+    docs(project(":performance:performance-unsafe"))
     docs(project(":preference:preference"))
     docs(project(":preference:preference-ktx"))
     docs(project(":print:print"))
diff --git a/docs/onboarding.md b/docs/onboarding.md
index 56f2578..88ae7f5 100644
--- a/docs/onboarding.md
+++ b/docs/onboarding.md
@@ -384,8 +384,15 @@
 ./gradlew core:core:assemble --strict
 ```
 
-To build every module and generate the local Maven repository artifact, use the
-`createArchive` Gradle task:
+To generate a local Maven artifact for the specific module and place it in
+`out/repository`, use the `publish` Gradle task:
+
+```shell
+./gradlew core:core:publish
+```
+
+To build every module and generate the local Maven repository artifacts and
+place them in `out/repository`, use the `createArchive` Gradle task:
 
 ```shell
 ./gradlew createArchive
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentContainerView.kt b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentContainerView.kt
index 04e1400..205b6b0 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentContainerView.kt
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentContainerView.kt
@@ -179,7 +179,7 @@
         )
     }
 
-    public override fun setOnApplyWindowInsetsListener(listener: OnApplyWindowInsetsListener) {
+    public override fun setOnApplyWindowInsetsListener(listener: OnApplyWindowInsetsListener?) {
         applyWindowInsetsListener = listener
     }
 
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 7012d9e..510a96e 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -2,13 +2,13 @@
 # -----------------------------------------------------------------------------
 # All of the following should be updated in sync.
 # -----------------------------------------------------------------------------
-androidGradlePlugin = "8.9.0-alpha06"
+androidGradlePlugin = "8.9.0-alpha01"
 # NOTE: When updating the lint version we also need to update the `api` version
 # supported by `IssueRegistry`'s.' For e.g. r.android.com/1331903
-androidLint = "31.9.0-alpha06"
+androidLint = "31.9.0-alpha01"
 # Once you have a chosen version of AGP to upgrade to, go to
 # https://developer.android.com/studio/archive and find the matching version of Studio.
-androidStudio = "2024.3.1.6"
+androidStudio = "2024.3.1.1"
 # -----------------------------------------------------------------------------
 
 androidLintMin = "31.1.0"
diff --git a/gradle/verification-keyring.keys b/gradle/verification-keyring.keys
index b9e6596..322947c 100644
--- a/gradle/verification-keyring.keys
+++ b/gradle/verification-keyring.keys
@@ -4081,40 +4081,6 @@
 =Q+9k
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    EB095DA7D2F6AC0E
-sub    603D72C90616CD6B
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v@RELEASE_NAME@
-
-mQGNBGBm/LQBDADMr/VPcTvE6k3wEYxq5kZusnDCDTsI6RK51d4oMwaRc3Z0jtZ0
-CfyWocZBok4rMbZAVnE3Q8pMyikGGUnc8ZsWoPEmJyCpw/2Orj0QqZhIgYMQ31Uq
-tiGZF/G4w9phLIkFgU9BLGYjRNM69R0oE/Tj8mjguvnKzYM3GjkY6nDsgWCM5TJX
-01k4sdLs0dVg86m4keq+SeS9uEwnINZTh6kQUKsW6aHvvPXze/UPoaZqxgXDjF+F
-JrPwW8yDllkbzpbo53ulz1TL5RsIH3daUwxXG3ciovUXG/b2ZRuWjtH7Gn/AvCNL
-0RXdHK3A2I23zCooOE+we2D45QUHm/vcmvsnbxOU7Tslm2DsnYxBjf5dAl2yZn+J
-FSrV91Bbd5ZXi1UkkGjBzAgbHDwdMvL9K6fTO9NwjXyBpiHy6ukIOObn9uIgDSSa
-xPnqgeykSv+RZEea8ML4BSif5RJYlmILEzJhH4rtX9X+t8BZv+ZoaN6p/qYg4/2+
-XfSUPmCJjlUaIUUAEQEAAbkBjQRgZvy0AQwAtuysL4l1wLjDIgva/+mD76cekxRu
-54s7zYOkh/87NIZ6tPkPlw/w+m7CEohurx2sQSPrClJoaMqxlPgRCmmj5JQVEC79
-9pkvJZb+QwslD57P84LYntiqpr+nmmR6vgDlZxaiRa6OVUllUTYwDpHcQ8MocXan
-e4iAea99acxL60zOimPeaPVK9tXZQ1nKPVIWs6RSYna54FFZn0uXfG4Qx8xEAXYd
-cUj5oEh4JFtEcP+55YVWopfi+zIQwwJ7JaO6ZZhHco4OpCwTauB/hX2SVdSijV32
-O9IhHXO3xPIi+5RC/iwHrhF3kexNLlfVWMnb/RWC7ROQXdUEK4YQGLy7+dFd7lKQ
-5gbUoAhuqWOnHyaSAyNlFGum3FR5oroad0eKS5jzk2n4UMPNDAoo7yEi1cdCrykD
-Jeb1GQD6ucQx+oqLkc1OGwqVjJU3FDQj/yvSCPKmst9lSGS3JH9l6ac033Db2qAP
-kUxnhw2xN4LHk2Ioovn5SZu1IUzH8/i+HhpfABEBAAGJAbYEGAEKACAWIQR0QPH3
-0nusEV+VPVXrCV2n0vasDgUCYGb8tAIbDAAKCRDrCV2n0vasDkSBC/91fDW0V6U8
-pRwW6HFruAnq/0uQ2gISrmDlpJzsgSO6HQQfho1T/7uuYhnBGyU4dxIF4G9A+Ehh
-2iwhB90JzCNLstTW6ueSWMK+4hvBpfx3kCbs2oxu0z8ZHroxE9I7e5XqDQOazANn
-eLRZJ5SArg1dFGYveBRlyjE55CmDQyj58aJkMbLAAJrdrMkFZHwbeBKOs3ph0zn5
-NvSBDUP8A3wlUXuSySeXYCUIj2k4Q6zJodnhP76ivfpu0eZn4UnD0sI8YdoJOsNK
-gDRO6fR9kEEh/XGY082B1Ad6tO2nea1MIVF0GIgfh3ezd3YcG4Rip0uqIPr7yxpT
-mVEA8wVvpWg8+wY2/xvLuHtZD59bK4KlQ9m+4W5WhursrdUfSI2EuXNp7xYwNRVf
-elApmsOOWqONqWg4leirxkWUMz7XDArDPuei4Qk8VF4/0yfGOVSh8VHQrIauzqrN
-p4LbYC9sii1fqxQTFVGPPhv6Wujd/eUuUeURZbKgpHIfniDXLiaTUyc=
-=aMmv
------END PGP PUBLIC KEY BLOCK-----
-
 pub    EB380DC13C39F675
 uid    Mark Vedder <[email protected]>
 
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index c5a4c74..5f5b0c8 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -316,7 +316,6 @@
          <trusted-key id="719F7C29985A8E95F58F47194D8159D6A1159B69" group="dev.zacsweers.moshix"/>
          <trusted-key id="720746177725A89207A7075BFD5DEA07FCB690A8" group="org.codehaus.mojo"/>
          <trusted-key id="73976C9C39C1479B84E2641A5A68A2249128E2C6" group="com.google.crypto.tink" name="tink-android"/>
-         <trusted-key id="7440F1F7D27BAC115F953D55EB095DA7D2F6AC0E" group="org.tensorflow"/>
          <trusted-key id="748F15B2CF9BA8F024155E6ED7C92B70FA1C814D" group="org.apache.logging.log4j"/>
          <trusted-key id="7615AD56144DF2376F49D98B1669C4BB543E0445" group="com.google.errorprone"/>
          <trusted-key id="7616EB882DAF57A11477AAF559A252FB1199D873" group="com.google.code.findbugs"/>
diff --git a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensionsTest.kt b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensionsTest.kt
index 6d5ea0a..ac6a966 100644
--- a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensionsTest.kt
+++ b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensionsTest.kt
@@ -19,13 +19,14 @@
 import android.annotation.TargetApi
 import android.content.Context
 import android.os.Build
-import android.os.ext.SdkExtensions
 import androidx.health.connect.client.HealthConnectClient
 import androidx.health.connect.client.impl.HealthConnectClientUpsideDownImpl
+import androidx.health.connect.client.impl.platform.toLocalTimeWithDefaultZoneFallback
 import androidx.health.connect.client.permission.HealthPermission
 import androidx.health.connect.client.records.BloodPressureRecord
 import androidx.health.connect.client.records.NutritionRecord
 import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.request.AggregateGroupByPeriodRequest
 import androidx.health.connect.client.request.AggregateRequest
 import androidx.health.connect.client.time.TimeRangeFilter
 import androidx.health.connect.client.units.millimetersOfMercury
@@ -38,12 +39,12 @@
 import java.time.Duration
 import java.time.LocalDate
 import java.time.LocalDateTime
+import java.time.Period
 import java.time.ZoneOffset
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.test.runTest
 import org.junit.After
 import org.junit.Assert.assertThrows
-import org.junit.Assume.assumeTrue
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -407,7 +408,6 @@
 
     @Test
     fun aggregateBloodPressure_localTimeRangeFilter() = runTest {
-        assumeTrue(SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 10)
         healthConnectClient.insertRecords(
             listOf(
                 BloodPressureRecord(
@@ -548,10 +548,99 @@
         assertThat(aggregationResult.dataOrigins).isEmpty()
     }
 
+    @Test
+    fun aggregateBloodPressure_groupByPeriod() = runTest {
+        healthConnectClient.insertRecords(
+            listOf(
+                BloodPressureRecord(
+                    time = START_TIME + 4.minutes,
+                    zoneOffset = ZoneOffset.UTC,
+                    systolic = 120.millimetersOfMercury,
+                    diastolic = 80.millimetersOfMercury
+                ),
+                BloodPressureRecord(
+                    time = START_TIME + 8.minutes,
+                    zoneOffset = ZoneOffset.UTC,
+                    systolic = 100.millimetersOfMercury,
+                    diastolic = 60.millimetersOfMercury
+                ),
+                BloodPressureRecord(
+                    time = START_TIME + 1.days + 10.minutes,
+                    zoneOffset = ZoneOffset.UTC,
+                    systolic = 100.millimetersOfMercury,
+                    diastolic = 70.millimetersOfMercury
+                )
+            )
+        )
+
+        val aggregationResult =
+            healthConnectClient.aggregateFallback(
+                AggregateGroupByPeriodRequest(
+                    setOf(
+                        BloodPressureRecord.DIASTOLIC_AVG,
+                        BloodPressureRecord.DIASTOLIC_MAX,
+                        BloodPressureRecord.DIASTOLIC_MIN,
+                        BloodPressureRecord.SYSTOLIC_AVG,
+                        BloodPressureRecord.SYSTOLIC_MAX,
+                        BloodPressureRecord.SYSTOLIC_MIN,
+                    ),
+                    TimeRangeFilter.after(
+                        START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                    ),
+                    timeRangeSlicer = Period.ofDays(1)
+                )
+            )
+
+        assertThat(aggregationResult).hasSize(2)
+
+        with(aggregationResult[0]) {
+            assertThat(startTime)
+                .isEqualTo(START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC))
+            assertThat(endTime)
+                .isEqualTo(
+                    START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC).plusDays(1)
+                )
+            assertThat(result.dataOrigins).containsExactly(DataOrigin(context.packageName))
+
+            assertEquals(
+                result[BloodPressureRecord.DIASTOLIC_AVG] to 70.millimetersOfMercury,
+                result[BloodPressureRecord.DIASTOLIC_MAX] to 80.millimetersOfMercury,
+                result[BloodPressureRecord.DIASTOLIC_MIN] to 60.millimetersOfMercury,
+                result[BloodPressureRecord.SYSTOLIC_AVG] to 110.millimetersOfMercury,
+                result[BloodPressureRecord.SYSTOLIC_MAX] to 120.millimetersOfMercury,
+                result[BloodPressureRecord.SYSTOLIC_MIN] to 100.millimetersOfMercury,
+            )
+        }
+
+        with(aggregationResult[1]) {
+            assertThat(startTime)
+                .isEqualTo(
+                    START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC).plusDays(1)
+                )
+            assertThat(endTime)
+                .isEqualTo(
+                    START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC).plusDays(2)
+                )
+            assertThat(result.dataOrigins).containsExactly(DataOrigin(context.packageName))
+
+            assertEquals(
+                result[BloodPressureRecord.DIASTOLIC_AVG] to 70.millimetersOfMercury,
+                result[BloodPressureRecord.DIASTOLIC_MAX] to 70.millimetersOfMercury,
+                result[BloodPressureRecord.DIASTOLIC_MIN] to 70.millimetersOfMercury,
+                result[BloodPressureRecord.SYSTOLIC_AVG] to 100.millimetersOfMercury,
+                result[BloodPressureRecord.SYSTOLIC_MAX] to 100.millimetersOfMercury,
+                result[BloodPressureRecord.SYSTOLIC_MIN] to 100.millimetersOfMercury,
+            )
+        }
+    }
+
     private fun <A, E> assertEquals(vararg assertions: Pair<A, E>) {
         assertions.forEach { (actual, expected) -> assertThat(actual).isEqualTo(expected) }
     }
 
+    private val Int.days: Duration
+        get() = Duration.ofDays(1)
+
     private val Int.seconds: Duration
         get() = Duration.ofSeconds(this.toLong())
 
diff --git a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensionsTest.kt b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensionsTest.kt
index 5fccd27..9d4d0e2 100644
--- a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensionsTest.kt
+++ b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensionsTest.kt
@@ -109,90 +109,6 @@
     }
 
     @Test
-    fun aggregateFallback_sdkExt10AndAbove() = runTest {
-        assumeTrue(SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 10)
-
-        healthConnectClient.insertRecords(
-            listOf(
-                BloodPressureRecord(
-                    time = START_TIME,
-                    zoneOffset = ZoneOffset.UTC,
-                    diastolic = 70.millimetersOfMercury,
-                    systolic = 110.millimetersOfMercury
-                ),
-                CyclingPedalingCadenceRecord(
-                    startTime = START_TIME,
-                    endTime = START_TIME + 30.minutes,
-                    startZoneOffset = ZoneOffset.UTC,
-                    endZoneOffset = ZoneOffset.UTC,
-                    samples =
-                        listOf(
-                            CyclingPedalingCadenceRecord.Sample(
-                                time = START_TIME + 5.minutes,
-                                revolutionsPerMinute = 80.0
-                            ),
-                            CyclingPedalingCadenceRecord.Sample(
-                                time = START_TIME + 15.minutes,
-                                revolutionsPerMinute = 90.0
-                            )
-                        )
-                ),
-                NutritionRecord(
-                    startTime = START_TIME,
-                    endTime = START_TIME + 1.minutes,
-                    transFat = 0.3.grams,
-                    calcium = 0.1.grams,
-                    startZoneOffset = ZoneOffset.UTC,
-                    endZoneOffset = ZoneOffset.UTC
-                ),
-                SpeedRecord(
-                    startTime = START_TIME,
-                    endTime = START_TIME + 15.minutes,
-                    startZoneOffset = ZoneOffset.UTC,
-                    endZoneOffset = ZoneOffset.UTC,
-                    samples =
-                        listOf(
-                            SpeedRecord.Sample(
-                                time = START_TIME + 5.minutes,
-                                speed = Velocity.metersPerSecond(2.8)
-                            ),
-                            SpeedRecord.Sample(
-                                time = START_TIME + 10.minutes,
-                                speed = Velocity.metersPerSecond(2.7)
-                            )
-                        )
-                ),
-                StepsCadenceRecord(
-                    startTime = START_TIME,
-                    endTime = START_TIME + 10.minutes,
-                    startZoneOffset = ZoneOffset.UTC,
-                    endZoneOffset = ZoneOffset.UTC,
-                    samples =
-                        listOf(
-                            StepsCadenceRecord.Sample(time = START_TIME + 3.minutes, rate = 170.0)
-                        )
-                )
-            )
-        )
-
-        // Adding calcium total (which has always been supported) to make sure it's filtered out of
-        // the calculation.
-        val aggregationResult =
-            healthConnectClient.aggregateFallback(
-                AggregateRequest(
-                    metrics = AGGREGATE_METRICS_ADDED_IN_SDK_EXT_10 + NutritionRecord.CALCIUM_TOTAL,
-                    timeRangeFilter = TimeRangeFilter.none()
-                )
-            )
-
-        for (metric in AGGREGATE_METRICS_ADDED_IN_SDK_EXT_10) {
-            assertThat(metric in aggregationResult).isFalse()
-        }
-        assertThat(NutritionRecord.CALCIUM_TOTAL in aggregationResult).isFalse()
-        assertThat(aggregationResult.dataOrigins).isEmpty()
-    }
-
-    @Test
     fun aggregateFallback_belowSdkExt10() = runTest {
         assumeFalse(SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 10)
 
diff --git a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensionsTest.kt b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensionsTest.kt
index 0e6d629..5a1a21c 100644
--- a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensionsTest.kt
+++ b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensionsTest.kt
@@ -21,12 +21,15 @@
 import android.os.Build
 import androidx.health.connect.client.HealthConnectClient
 import androidx.health.connect.client.impl.HealthConnectClientUpsideDownImpl
+import androidx.health.connect.client.impl.platform.toLocalTimeWithDefaultZoneFallback
 import androidx.health.connect.client.permission.HealthPermission
 import androidx.health.connect.client.records.NutritionRecord
 import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.request.AggregateGroupByPeriodRequest
 import androidx.health.connect.client.request.AggregateRequest
 import androidx.health.connect.client.time.TimeRangeFilter
 import androidx.health.connect.client.units.Mass
+import androidx.health.connect.client.units.grams
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
@@ -36,6 +39,7 @@
 import java.time.Duration
 import java.time.LocalDate
 import java.time.LocalDateTime
+import java.time.Period
 import java.time.ZoneOffset
 import kotlinx.coroutines.test.runTest
 import org.junit.After
@@ -133,6 +137,80 @@
     }
 
     @Test
+    fun aggregateNutritionTransFatTotal_groupByPeriod() = runTest {
+        healthConnectClient.insertRecords(
+            listOf(
+                NutritionRecord(
+                    startTime = START_TIME,
+                    endTime = START_TIME + 1.minutes,
+                    transFat = .3.grams,
+                    startZoneOffset = ZoneOffset.UTC,
+                    endZoneOffset = ZoneOffset.UTC
+                ),
+                NutritionRecord(
+                    startTime = START_TIME + 1.days + 2.minutes,
+                    endTime = START_TIME + 1.days + 3.minutes,
+                    transFat = null,
+                    startZoneOffset = ZoneOffset.UTC,
+                    endZoneOffset = ZoneOffset.UTC
+                ),
+                NutritionRecord(
+                    startTime = START_TIME + 3.days + 4.minutes,
+                    endTime = START_TIME + 3.days + 5.minutes,
+                    transFat = .4.grams,
+                    startZoneOffset = ZoneOffset.UTC,
+                    endZoneOffset = ZoneOffset.UTC
+                ),
+                NutritionRecord(
+                    startTime = START_TIME + 3.days + 6.minutes,
+                    endTime = START_TIME + 3.days + 7.minutes,
+                    transFat = .5.grams,
+                    startZoneOffset = ZoneOffset.UTC,
+                    endZoneOffset = ZoneOffset.UTC
+                )
+            )
+        )
+
+        val aggregationResult =
+            healthConnectClient.aggregateFallback(
+                AggregateGroupByPeriodRequest(
+                    metrics = setOf(NutritionRecord.TRANS_FAT_TOTAL),
+                    timeRangeFilter =
+                        TimeRangeFilter.after(
+                            START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                        ),
+                    timeRangeSlicer = Period.ofDays(1)
+                )
+            )
+
+        assertThat(aggregationResult).hasSize(2)
+
+        with(aggregationResult[0]) {
+            assertThat(startTime)
+                .isEqualTo(START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC))
+            assertThat(endTime)
+                .isEqualTo(
+                    START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC).plusDays(1)
+                )
+            assertThat(result[NutritionRecord.TRANS_FAT_TOTAL]).isEqualTo(.3.grams)
+            assertThat(result.dataOrigins).containsExactly(DataOrigin(context.packageName))
+        }
+
+        with(aggregationResult[1]) {
+            assertThat(startTime)
+                .isEqualTo(
+                    START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC).plusDays(3)
+                )
+            assertThat(endTime)
+                .isEqualTo(
+                    START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC).plusDays(4)
+                )
+            assertThat(result[NutritionRecord.TRANS_FAT_TOTAL]).isEqualTo(.9.grams)
+            assertThat(result.dataOrigins).containsExactly(DataOrigin(context.packageName))
+        }
+    }
+
+    @Test
     fun aggregateNutritionTransFatTotal_instantTimeRangeFilter() = runTest {
         healthConnectClient.insertRecords(
             listOf(
@@ -503,6 +581,9 @@
         assertThat(aggregationResult.dataOrigins).isEmpty()
     }
 
+    private val Int.days: Duration
+        get() = Duration.ofDays(this.toLong())
+
     private val Int.seconds: Duration
         get() = Duration.ofSeconds(this.toLong())
 
diff --git a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensionsTest.kt b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensionsTest.kt
index 3d67fb7..a1516dd 100644
--- a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensionsTest.kt
+++ b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensionsTest.kt
@@ -19,15 +19,16 @@
 import android.annotation.TargetApi
 import android.content.Context
 import android.os.Build
-import android.os.ext.SdkExtensions
 import androidx.health.connect.client.HealthConnectClient
 import androidx.health.connect.client.impl.HealthConnectClientUpsideDownImpl
+import androidx.health.connect.client.impl.platform.toLocalTimeWithDefaultZoneFallback
 import androidx.health.connect.client.permission.HealthPermission
 import androidx.health.connect.client.records.CyclingPedalingCadenceRecord
 import androidx.health.connect.client.records.HeartRateRecord
 import androidx.health.connect.client.records.SpeedRecord
 import androidx.health.connect.client.records.StepsCadenceRecord
 import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.request.AggregateGroupByPeriodRequest
 import androidx.health.connect.client.request.AggregateRequest
 import androidx.health.connect.client.time.TimeRangeFilter
 import androidx.health.connect.client.units.metersPerSecond
@@ -40,13 +41,12 @@
 import java.time.Duration
 import java.time.LocalDate
 import java.time.LocalDateTime
+import java.time.Period
 import java.time.ZoneOffset
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.test.runTest
 import org.junit.After
 import org.junit.Assert.assertThrows
-import org.junit.Assume.assumeFalse
-import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -84,12 +84,6 @@
                 .toTypedArray())
         )
 
-    @Before
-    fun setUp() = runTest {
-        // SDK ext 10 and above don't process any fallback metrics
-        assumeFalse(SdkExtensions.getExtensionVersion(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) >= 10)
-    }
-
     @After
     fun tearDown() = runTest {
         for (recordType in SERIES_AGGREGATION_FALLBACK_RECORD_TYPES) {
@@ -140,6 +134,119 @@
     }
 
     @Test
+    fun aggregateCyclingPedalingCadence_groupByPeriod() = runTest {
+        healthConnectClient.insertRecords(
+            listOf(
+                CyclingPedalingCadenceRecord(
+                    startTime = START_TIME,
+                    endTime = START_TIME + 30.minutes,
+                    startZoneOffset = ZoneOffset.UTC,
+                    endZoneOffset = ZoneOffset.UTC,
+                    samples =
+                        listOf(
+                            CyclingPedalingCadenceRecord.Sample(
+                                time = START_TIME + 5.minutes,
+                                revolutionsPerMinute = 80.0
+                            ),
+                            CyclingPedalingCadenceRecord.Sample(
+                                time = START_TIME + 15.minutes,
+                                revolutionsPerMinute = 90.0
+                            )
+                        )
+                ),
+                CyclingPedalingCadenceRecord(
+                    startTime = START_TIME,
+                    endTime = START_TIME + 2.days + 30.minutes,
+                    startZoneOffset = ZoneOffset.UTC,
+                    endZoneOffset = ZoneOffset.UTC,
+                    samples =
+                        listOf(
+                            CyclingPedalingCadenceRecord.Sample(
+                                time = START_TIME + 10.minutes,
+                                revolutionsPerMinute = 220.0
+                            ),
+                            CyclingPedalingCadenceRecord.Sample(
+                                time = START_TIME + 2.days + 15.minutes,
+                                revolutionsPerMinute = 100.0
+                            )
+                        )
+                ),
+                SpeedRecord(
+                    startTime = START_TIME,
+                    endTime = START_TIME + 15.minutes,
+                    startZoneOffset = ZoneOffset.UTC,
+                    endZoneOffset = ZoneOffset.UTC,
+                    samples =
+                        listOf(
+                            SpeedRecord.Sample(
+                                time = START_TIME + 5.minutes,
+                                speed = 2.8.metersPerSecond
+                            ),
+                            SpeedRecord.Sample(
+                                time = START_TIME + 10.minutes,
+                                speed = 2.7.metersPerSecond
+                            )
+                        )
+                )
+            )
+        )
+
+        val aggregationResult =
+            healthConnectClient.aggregateFallback(
+                AggregateGroupByPeriodRequest(
+                    metrics =
+                        setOf(
+                            CyclingPedalingCadenceRecord.RPM_AVG,
+                            CyclingPedalingCadenceRecord.RPM_MAX,
+                            CyclingPedalingCadenceRecord.RPM_MIN,
+                            SpeedRecord.SPEED_AVG,
+                        ),
+                    timeRangeSlicer = Period.ofDays(1),
+                    timeRangeFilter =
+                        TimeRangeFilter.after(
+                            START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                        )
+                )
+            )
+
+        assertThat(aggregationResult).hasSize(2)
+
+        with(aggregationResult[0]) {
+            assertThat(startTime)
+                .isEqualTo(START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC))
+            assertThat(endTime)
+                .isEqualTo(
+                    START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC).plusDays(1)
+                )
+            assertThat(result[CyclingPedalingCadenceRecord.RPM_AVG]).isEqualTo(130.0)
+            assertThat(result[CyclingPedalingCadenceRecord.RPM_MAX]).isEqualTo(220.0)
+            assertThat(result[CyclingPedalingCadenceRecord.RPM_MIN]).isEqualTo(80.0)
+
+            assertThat(result[SpeedRecord.SPEED_AVG]).isEqualTo(2.75.metersPerSecond)
+
+            assertThat(result.dataOrigins).containsExactly(DataOrigin(context.packageName))
+        }
+
+        with(aggregationResult[1]) {
+            assertThat(startTime)
+                .isEqualTo(
+                    START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC).plusDays(2)
+                )
+            assertThat(endTime)
+                .isEqualTo(
+                    START_TIME.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC).plusDays(3)
+                )
+            assertThat(result[CyclingPedalingCadenceRecord.RPM_AVG]).isEqualTo(100.0)
+            assertThat(result[CyclingPedalingCadenceRecord.RPM_MAX]).isEqualTo(100.0)
+            assertThat(result[CyclingPedalingCadenceRecord.RPM_MIN]).isEqualTo(100.0)
+
+            assertThat(SpeedRecord.SPEED_AVG in result).isFalse()
+
+            assertThat(result.dataOrigins).containsExactly(DataOrigin(context.packageName))
+        }
+    }
+
+    @Test
     fun aggregateCyclingSpeed() = runTest {
         healthConnectClient.insertRecords(
             listOf(
@@ -595,9 +702,7 @@
                         TimeRangeFilter.none(),
                         emptySet()
                     )
-                ) {
-                    samples.map { SampleInfo(time = it.time, value = it.rate) }
-                }
+                )
             }
         }
     }
@@ -617,99 +722,13 @@
                         TimeRangeFilter.none(),
                         emptySet()
                     )
-                ) {
-                    samples.map { SampleInfo(time = it.time, value = it.beatsPerMinute.toDouble()) }
-                }
+                )
             }
         }
     }
 
-    @Test
-    fun sampleInfoIsWithin_noneTimeRangeFilter_returnsTrue() {
-        val sampleInfo = SampleInfo(time = START_TIME, value = 0.0)
-        val timeRangeFilter = TimeRangeFilter.none()
-
-        assertThat(sampleInfo.isWithin(timeRangeFilter = timeRangeFilter, zoneOffset = null))
-            .isTrue()
-    }
-
-    @Test
-    fun sampleInfoIsWithin_instantTimeRangeFilter_between() {
-        val sampleInfo = SampleInfo(time = START_TIME, value = 0.0)
-        val zoneOffset = ZoneOffset.ofHours(2)
-
-        var timeRangeFilter =
-            TimeRangeFilter.between(START_TIME - 2.minutes, START_TIME + 2.minutes)
-        assertThat(sampleInfo.isWithin(timeRangeFilter, zoneOffset)).isTrue()
-
-        timeRangeFilter = TimeRangeFilter.between(START_TIME - 2.minutes, START_TIME)
-        assertThat(sampleInfo.isWithin(timeRangeFilter, zoneOffset)).isFalse()
-
-        timeRangeFilter = TimeRangeFilter.between(START_TIME, START_TIME + 2.minutes)
-        assertThat(sampleInfo.isWithin(timeRangeFilter, zoneOffset)).isTrue()
-
-        timeRangeFilter = TimeRangeFilter.between(START_TIME + 1.minutes, START_TIME + 2.minutes)
-        assertThat(sampleInfo.isWithin(timeRangeFilter, zoneOffset)).isFalse()
-    }
-
-    @Test
-    fun sampleInfoIsWithin_instantTimeRangeFilter_openEnded() {
-        val sampleInfo = SampleInfo(time = START_TIME, value = 0.0)
-        val zoneOffset = ZoneOffset.ofHours(2)
-
-        var timeRangeFilter = TimeRangeFilter.after(START_TIME)
-        assertThat(sampleInfo.isWithin(timeRangeFilter, zoneOffset)).isTrue()
-
-        timeRangeFilter = TimeRangeFilter.after(START_TIME + 1.minutes)
-        assertThat(sampleInfo.isWithin(timeRangeFilter, zoneOffset)).isFalse()
-
-        timeRangeFilter = TimeRangeFilter.before(START_TIME)
-        assertThat(sampleInfo.isWithin(timeRangeFilter, zoneOffset)).isFalse()
-
-        timeRangeFilter = TimeRangeFilter.before(START_TIME + 1.minutes)
-        assertThat(sampleInfo.isWithin(timeRangeFilter, zoneOffset)).isTrue()
-    }
-
-    @Test
-    fun sampleInfoIsWithin_localTimeRangeFilter_between() {
-        val sampleInfo = SampleInfo(time = START_TIME, value = 0.0)
-        val zoneOffset = ZoneOffset.ofHours(2)
-
-        var timeRangeFilter =
-            TimeRangeFilter.between(
-                LocalDateTime.ofInstant(START_TIME - 2.minutes, ZoneOffset.UTC),
-                LocalDateTime.ofInstant(START_TIME + 2.minutes, ZoneOffset.UTC)
-            )
-        assertThat(sampleInfo.isWithin(timeRangeFilter, zoneOffset)).isFalse()
-
-        timeRangeFilter =
-            TimeRangeFilter.between(
-                LocalDateTime.ofInstant(START_TIME - 2.minutes, zoneOffset),
-                LocalDateTime.ofInstant(START_TIME + 2.minutes, zoneOffset)
-            )
-        assertThat(sampleInfo.isWithin(timeRangeFilter, zoneOffset)).isTrue()
-
-        timeRangeFilter =
-            TimeRangeFilter.between(
-                LocalDateTime.ofInstant(START_TIME - 2.minutes, zoneOffset),
-                LocalDateTime.ofInstant(START_TIME, zoneOffset)
-            )
-        assertThat(sampleInfo.isWithin(timeRangeFilter, zoneOffset)).isFalse()
-
-        timeRangeFilter =
-            TimeRangeFilter.between(
-                LocalDateTime.ofInstant(START_TIME, zoneOffset),
-                LocalDateTime.ofInstant(START_TIME + 2.minutes, zoneOffset)
-            )
-        assertThat(sampleInfo.isWithin(timeRangeFilter, zoneOffset)).isTrue()
-
-        timeRangeFilter =
-            TimeRangeFilter.between(
-                LocalDateTime.ofInstant(START_TIME + 1.minutes, zoneOffset),
-                LocalDateTime.ofInstant(START_TIME + 2.minutes, zoneOffset)
-            )
-        assertThat(sampleInfo.isWithin(timeRangeFilter, zoneOffset)).isFalse()
-    }
+    private val Int.days: Duration
+        get() = Duration.ofDays(this.toLong())
 
     private val Int.hours: Duration
         get() = Duration.ofHours(this.toLong())
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/aggregate/AggregationResult.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/aggregate/AggregationResult.kt
index 921fa90..c5d0a4d 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/aggregate/AggregationResult.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/aggregate/AggregationResult.kt
@@ -69,4 +69,36 @@
             is Converter.FromLong -> longValues[metric.metricKey]?.let(metric.converter)
             is Converter.FromDouble -> doubleValues[metric.metricKey]?.let(metric.converter)
         }
+
+    internal operator fun plus(other: AggregationResult): AggregationResult {
+        return AggregationResult(
+            longValues + other.longValues,
+            doubleValues + other.doubleValues,
+            dataOrigins + other.dataOrigins
+        )
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (javaClass != other?.javaClass) return false
+
+        other as AggregationResult
+
+        if (longValues != other.longValues) return false
+        if (doubleValues != other.doubleValues) return false
+        if (dataOrigins != other.dataOrigins) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = longValues.hashCode()
+        result = 31 * result + doubleValues.hashCode()
+        result = 31 * result + dataOrigins.hashCode()
+        return result
+    }
+
+    override fun toString(): String {
+        return "AggregationResult(longValues=$longValues, doubleValues=$doubleValues, dataOrigins=$dataOrigins)"
+    }
 }
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/aggregate/AggregationResultGroupedByPeriod.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/aggregate/AggregationResultGroupedByPeriod.kt
index fb23130..61597ab 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/aggregate/AggregationResultGroupedByPeriod.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/aggregate/AggregationResultGroupedByPeriod.kt
@@ -36,4 +36,35 @@
     init {
         require(startTime.isBefore(endTime)) { "start time must be before end time" }
     }
+
+    internal fun mergedWith(
+        other: AggregationResultGroupedByPeriod
+    ): AggregationResultGroupedByPeriod {
+        require(startTime == other.startTime && endTime == other.endTime)
+        return AggregationResultGroupedByPeriod(result + other.result, startTime, endTime)
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (javaClass != other?.javaClass) return false
+
+        other as AggregationResultGroupedByPeriod
+
+        if (result != other.result) return false
+        if (startTime != other.startTime) return false
+        if (endTime != other.endTime) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var hash = result.hashCode()
+        hash = 31 * hash + startTime.hashCode()
+        hash = 31 * hash + endTime.hashCode()
+        return hash
+    }
+
+    override fun toString(): String {
+        return "AggregationResultGroupedByPeriod(result=$result, startTime=$startTime, endTime=$endTime)"
+    }
 }
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/HealthConnectClientUpsideDownImpl.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/HealthConnectClientUpsideDownImpl.kt
index 72298c5..9e87032 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/HealthConnectClientUpsideDownImpl.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/HealthConnectClientUpsideDownImpl.kt
@@ -46,7 +46,6 @@
 import androidx.health.connect.client.impl.platform.aggregate.AGGREGATE_METRICS_ADDED_IN_SDK_EXT_10
 import androidx.health.connect.client.impl.platform.aggregate.aggregateFallback
 import androidx.health.connect.client.impl.platform.aggregate.isPlatformSupportedMetric
-import androidx.health.connect.client.impl.platform.aggregate.plus
 import androidx.health.connect.client.impl.platform.records.toPlatformRecord
 import androidx.health.connect.client.impl.platform.records.toPlatformRecordClass
 import androidx.health.connect.client.impl.platform.records.toSdkRecord
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/TimeExtensions.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/TimeExtensions.kt
index a8705ff..2b99ace 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/TimeExtensions.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/TimeExtensions.kt
@@ -16,8 +16,10 @@
 
 package androidx.health.connect.client.impl.platform
 
+import androidx.health.connect.client.impl.platform.aggregate.InstantTimeRange
+import androidx.health.connect.client.impl.platform.aggregate.LocalTimeRange
+import androidx.health.connect.client.impl.platform.aggregate.TimeRange
 import androidx.health.connect.client.records.IntervalRecord
-import androidx.health.connect.client.time.TimeRangeFilter
 import java.time.Duration
 import java.time.Instant
 import java.time.LocalDateTime
@@ -25,9 +27,9 @@
 import java.time.ZoneOffset
 
 internal operator fun Duration.div(divisor: Duration): Double {
-    if (divisor.isZero) {
-        return 0.0
-    }
+    // We don't expect division by zero to occur. If it does, there is a mistake in the business
+    // logic and the best way to surface it is to let this return the default Infinity value kotlin
+    // returns on floating point division
     return toMillis().toDouble() / divisor.toMillis()
 }
 
@@ -35,13 +37,24 @@
     return Duration.between(other, this)
 }
 
-internal fun TimeRangeFilter.useLocalTime(): Boolean {
-    return localStartTime != null || localEndTime != null
+internal fun LocalDateTime.toInstantWithDefaultZoneFallback(
+    zoneOffset: ZoneOffset? = null
+): Instant {
+    return atZone(zoneOffset ?: ZoneId.systemDefault()).toInstant()
 }
 
-internal fun LocalDateTime.toInstantWithDefaultZoneFallback(zoneOffset: ZoneOffset?): Instant {
-    return atZone(zoneOffset ?: ZoneId.systemDefault()).toInstant()
+internal fun Instant.toLocalTimeWithDefaultZoneFallback(zoneOffset: ZoneId? = null): LocalDateTime {
+    return LocalDateTime.ofInstant(this, zoneOffset ?: ZoneId.systemDefault())
 }
 
 internal val IntervalRecord.duration: Duration
     get() = endTime - startTime
+
+internal fun Instant.isWithin(timeRange: TimeRange<*>, zoneOffset: ZoneOffset? = null): Boolean {
+    return when (timeRange) {
+        is InstantTimeRange -> !isBefore(timeRange.startTime) && isBefore(timeRange.endTime)
+        is LocalTimeRange ->
+            !isBefore(timeRange.startTime.toInstantWithDefaultZoneFallback(zoneOffset)) &&
+                isBefore(timeRange.endTime.toInstantWithDefaultZoneFallback(zoneOffset))
+    }
+}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregationExtensions.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregationExtensions.kt
index 31f7abb..9af8176 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregationExtensions.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregationExtensions.kt
@@ -22,17 +22,27 @@
 import android.os.ext.SdkExtensions
 import androidx.annotation.RequiresApi
 import androidx.health.connect.client.aggregate.AggregateMetric
-import androidx.health.connect.client.aggregate.AggregationResult
 import androidx.health.connect.client.records.BloodPressureRecord
 import androidx.health.connect.client.records.CyclingPedalingCadenceRecord
 import androidx.health.connect.client.records.NutritionRecord
 import androidx.health.connect.client.records.SpeedRecord
 import androidx.health.connect.client.records.StepsCadenceRecord
+import androidx.health.connect.client.request.AggregateGroupByPeriodRequest
 import androidx.health.connect.client.request.AggregateRequest
 
 internal fun AggregateRequest.withFilteredMetrics(predicate: (AggregateMetric<*>) -> Boolean) =
     AggregateRequest(metrics.filter(predicate).toSet(), timeRangeFilter, dataOriginFilter)
 
+internal fun AggregateGroupByPeriodRequest.withFilteredMetrics(
+    predicate: (AggregateMetric<*>) -> Boolean
+) =
+    AggregateGroupByPeriodRequest(
+        metrics.filter(predicate).toSet(),
+        timeRangeFilter,
+        timeRangeSlicer,
+        dataOriginFilter
+    )
+
 // Only check against aggregate metrics added in sdk extension 10, to address b/326414908
 // Metrics added later on will be present dependent on feature availability
 internal fun AggregateMetric<*>.isPlatformSupportedMetric(): Boolean {
@@ -43,14 +53,6 @@
     }
 }
 
-internal operator fun AggregationResult.plus(other: AggregationResult): AggregationResult {
-    return AggregationResult(
-        longValues + other.longValues,
-        doubleValues + other.doubleValues,
-        dataOrigins + other.dataOrigins
-    )
-}
-
 internal val AGGREGATE_METRICS_ADDED_IN_SDK_EXT_10: Set<AggregateMetric<*>> =
     setOf(
         BloodPressureRecord.DIASTOLIC_AVG,
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregationProcessor.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregationProcessor.kt
new file mode 100644
index 0000000..cdf2d0e
--- /dev/null
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregationProcessor.kt
@@ -0,0 +1,31 @@
+/*
+ * 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.health.connect.client.impl.platform.aggregate
+
+import androidx.health.connect.client.aggregate.AggregationResult
+import androidx.health.connect.client.records.Record
+
+/**
+ * Interface to calculate aggregation taking into account every record passed into [processRecord].
+ */
+internal interface AggregationProcessor<T : Record> {
+
+    /** Processes every record that it receives into the final [AggregationResult]. */
+    fun processRecord(record: T)
+
+    fun getProcessedAggregationResult(): AggregationResult
+}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/Aggregator.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/Aggregator.kt
index 0729b1a..2972265 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/Aggregator.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/Aggregator.kt
@@ -14,32 +14,18 @@
  * limitations under the License.
  */
 
-@file:RequiresApi(api = 34)
-
 package androidx.health.connect.client.impl.platform.aggregate
 
-import androidx.annotation.RequiresApi
-import androidx.health.connect.client.aggregate.AggregationResult
-import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.records.Record
 
-internal interface Aggregator<T, R> {
-    operator fun plusAssign(value: T)
+/**
+ * Interface to filter and aggregate records. Response [R] should be one of the aggregation response
+ * types defined by the API.
+ */
+internal interface Aggregator<T : Record, R> {
+
+    /** Filters and aggregates the parts of the record that are relevant for aggregation. */
+    fun filterAndAggregate(record: T)
 
     fun getResult(): R
 }
-
-internal abstract class SingeResultAggregator<T> : Aggregator<T, AggregationResult> {
-    abstract val doubleValues: Map<String, Double>
-    abstract val dataOrigins: Set<DataOrigin>
-
-    override fun getResult(): AggregationResult {
-        if (dataOrigins.isEmpty()) {
-            return emptyAggregationResult()
-        }
-        return AggregationResult(
-            longValues = emptyMap(),
-            doubleValues = doubleValues,
-            dataOrigins = dataOrigins
-        )
-    }
-}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregatorUtils.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregatorUtils.kt
new file mode 100644
index 0000000..636b179
--- /dev/null
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/AggregatorUtils.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.health.connect.client.impl.platform.aggregate
+
+import androidx.health.connect.client.impl.converters.datatype.RECORDS_CLASS_NAME_MAP
+import androidx.health.connect.client.impl.platform.div
+import androidx.health.connect.client.impl.platform.duration
+import androidx.health.connect.client.impl.platform.isWithin
+import androidx.health.connect.client.impl.platform.minus
+import androidx.health.connect.client.impl.platform.toInstantWithDefaultZoneFallback
+import androidx.health.connect.client.records.BloodPressureRecord
+import androidx.health.connect.client.records.CyclingPedalingCadenceRecord
+import androidx.health.connect.client.records.IntervalRecord
+import androidx.health.connect.client.records.NutritionRecord
+import androidx.health.connect.client.records.Record
+import androidx.health.connect.client.records.SeriesRecord
+import androidx.health.connect.client.records.SpeedRecord
+import androidx.health.connect.client.records.StepsCadenceRecord
+import java.time.Instant
+import kotlin.math.max
+
+internal object AggregatorUtils {
+
+    internal fun contributesToAggregation(record: Record, timeRange: TimeRange<*>): Boolean {
+        return when (record) {
+            is BloodPressureRecord -> record.time.isWithin(timeRange, record.zoneOffset)
+            is NutritionRecord -> record.transFat != null && sliceFactor(record, timeRange) > 0
+            is SeriesRecord<*> ->
+                record.samples.any { it.time.isWithin(timeRange, record.startZoneOffset) }
+            else ->
+                error(
+                    "Unsupported record type for aggregation fallback: ${RECORDS_CLASS_NAME_MAP[record::class]}"
+                )
+        }
+    }
+
+    internal fun sliceFactor(record: IntervalRecord, timeRange: TimeRange<*>): Double {
+        val rangeStartTime =
+            when (timeRange) {
+                is InstantTimeRange -> timeRange.startTime
+                is LocalTimeRange ->
+                    timeRange.startTime.toInstantWithDefaultZoneFallback(record.startZoneOffset)
+            }
+
+        val rangeEndTime =
+            when (timeRange) {
+                is InstantTimeRange -> timeRange.endTime
+                is LocalTimeRange ->
+                    timeRange.endTime.toInstantWithDefaultZoneFallback(record.endZoneOffset)
+            }
+
+        return max(
+            0.0,
+            (minOf(record.endTime, rangeEndTime) - maxOf(record.startTime, rangeStartTime)) /
+                record.duration
+        )
+    }
+
+    // Series records referenced here all have time and value
+    // The extension values below are added because the SeriesRecord interface doesn't expose them
+    internal val Any.time: Instant
+        get() =
+            when (this) {
+                is CyclingPedalingCadenceRecord.Sample -> time
+                is SpeedRecord.Sample -> time
+                is StepsCadenceRecord.Sample -> time
+                else -> error("Unsupported type for time: $this")
+            }
+
+    internal val Any.value: Double
+        get() =
+            when (this) {
+                is CyclingPedalingCadenceRecord.Sample -> revolutionsPerMinute
+                is SpeedRecord.Sample -> speed.inMetersPerSecond
+                is StepsCadenceRecord.Sample -> rate
+                else -> error("Unsupported type for value: $this")
+            }
+}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensions.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensions.kt
index 89f8b86..1fdb8bf 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensions.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/BloodPressureAggregationExtensions.kt
@@ -22,8 +22,10 @@
 import androidx.health.connect.client.HealthConnectClient
 import androidx.health.connect.client.aggregate.AggregateMetric
 import androidx.health.connect.client.aggregate.AggregationResult
+import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod
 import androidx.health.connect.client.records.BloodPressureRecord
 import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.request.AggregateGroupByPeriodRequest
 import androidx.health.connect.client.request.AggregateRequest
 import androidx.health.connect.client.request.ReadRecordsRequest
 import androidx.health.connect.client.units.Pressure
@@ -41,53 +43,51 @@
     )
 
 internal suspend fun HealthConnectClient.aggregateBloodPressure(
-    aggregateRequest: AggregateRequest
-): AggregationResult {
-    val aggregator = BloodPressureAggregator(aggregateRequest.metrics)
-    readRecordsFlow(
-            ReadRecordsRequest(
-                BloodPressureRecord::class,
-                aggregateRequest.timeRangeFilter,
-                aggregateRequest.dataOriginFilter
-            )
-        )
-        .collect { records -> records.forEach { aggregator += it } }
-    return aggregator.getResult()
+    aggregateRequest: AggregateGroupByPeriodRequest
+): List<AggregationResultGroupedByPeriod> {
+    return aggregate(
+        ReadRecordsRequest(
+            BloodPressureRecord::class,
+            aggregateRequest.timeRangeFilter,
+            aggregateRequest.dataOriginFilter
+        ),
+        ResultGroupedByPeriodAggregator(
+            createLocalTimeRange(aggregateRequest.timeRangeFilter),
+            aggregateRequest.timeRangeSlicer
+        ) {
+            BloodPressureAggregationProcessor(aggregateRequest.metrics)
+        }
+    )
 }
 
-private class BloodPressureAggregator(val bloodPressureMetrics: Set<AggregateMetric<*>>) :
-    SingeResultAggregator<BloodPressureRecord>() {
-    val avgDataMap = mutableMapOf<AggregateMetric<Pressure>, AvgData>()
-    val minMaxMap = mutableMapOf<AggregateMetric<Pressure>, Double?>()
+internal suspend fun HealthConnectClient.aggregateBloodPressure(
+    aggregateRequest: AggregateRequest
+): AggregationResult {
+    return aggregate(
+        ReadRecordsRequest(
+            BloodPressureRecord::class,
+            aggregateRequest.timeRangeFilter,
+            aggregateRequest.dataOriginFilter
+        ),
+        ResultAggregator(
+            createTimeRange(aggregateRequest.timeRangeFilter),
+            BloodPressureAggregationProcessor(aggregateRequest.metrics)
+        )
+    )
+}
 
-    override val dataOrigins = mutableSetOf<DataOrigin>()
-    override val doubleValues: Map<String, Double>
-        get() = buildMap {
-            for (metric in bloodPressureMetrics) {
-                val aggregatedValue =
-                    when (metric) {
-                        BloodPressureRecord.DIASTOLIC_AVG,
-                        BloodPressureRecord.SYSTOLIC_AVG -> avgDataMap[metric]!!.average()
-                        BloodPressureRecord.DIASTOLIC_MAX,
-                        BloodPressureRecord.DIASTOLIC_MIN,
-                        BloodPressureRecord.SYSTOLIC_MAX,
-                        BloodPressureRecord.SYSTOLIC_MIN -> minMaxMap[metric]!!
-                        else ->
-                            error(
-                                "Invalid blood pressure fallback aggregation type ${metric.metricKey}"
-                            )
-                    }
-
-                put(metric.metricKey, aggregatedValue)
-            }
-        }
+internal class BloodPressureAggregationProcessor(val metrics: Set<AggregateMetric<*>>) :
+    AggregationProcessor<BloodPressureRecord> {
+    private val avgDataMap = mutableMapOf<AggregateMetric<Pressure>, AvgData>()
+    private val minMaxMap = mutableMapOf<AggregateMetric<Pressure>, Double?>()
+    private val dataOrigins = mutableSetOf<DataOrigin>()
 
     init {
-        check(BLOOD_PRESSURE_METRICS.containsAll(bloodPressureMetrics)) {
-            "Invalid set of blood pressure fallback aggregation metrics ${bloodPressureMetrics.map { it.metricKey }}"
+        check(BLOOD_PRESSURE_METRICS.containsAll(metrics)) {
+            "Invalid set of blood pressure fallback aggregation metrics ${metrics.map { it.metricKey }}"
         }
 
-        for (metric in bloodPressureMetrics) {
+        for (metric in metrics) {
             when (metric) {
                 BloodPressureRecord.DIASTOLIC_AVG,
                 BloodPressureRecord.SYSTOLIC_AVG -> avgDataMap[metric] = AvgData()
@@ -101,11 +101,11 @@
         }
     }
 
-    override fun plusAssign(value: BloodPressureRecord) {
-        val diastolic = value.diastolic.inMillimetersOfMercury
-        val systolic = value.systolic.inMillimetersOfMercury
+    override fun processRecord(record: BloodPressureRecord) {
+        val diastolic = record.diastolic.inMillimetersOfMercury
+        val systolic = record.systolic.inMillimetersOfMercury
 
-        for (metric in bloodPressureMetrics) {
+        for (metric in metrics) {
             when (metric) {
                 BloodPressureRecord.DIASTOLIC_AVG -> avgDataMap[metric]!! += diastolic
                 BloodPressureRecord.DIASTOLIC_MAX ->
@@ -119,7 +119,29 @@
                     minMaxMap[metric] = min(minMaxMap[metric] ?: systolic, systolic)
             }
 
-            dataOrigins += value.metadata.dataOrigin
+            dataOrigins += record.metadata.dataOrigin
         }
     }
+
+    override fun getProcessedAggregationResult(): AggregationResult {
+        val doubleValues =
+            if (dataOrigins.isEmpty()) emptyMap()
+            else
+                metrics.associateBy({ it.metricKey }) { metric ->
+                    when (metric) {
+                        BloodPressureRecord.DIASTOLIC_AVG,
+                        BloodPressureRecord.SYSTOLIC_AVG -> avgDataMap[metric]!!.average()
+                        BloodPressureRecord.DIASTOLIC_MAX,
+                        BloodPressureRecord.DIASTOLIC_MIN,
+                        BloodPressureRecord.SYSTOLIC_MAX,
+                        BloodPressureRecord.SYSTOLIC_MIN -> minMaxMap[metric]!!
+                        else ->
+                            error(
+                                "Invalid blood pressure fallback aggregation type ${metric.metricKey}"
+                            )
+                    }
+                }
+
+        return AggregationResult(emptyMap(), doubleValues, dataOrigins)
+    }
 }
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensions.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensions.kt
index 1adb5f6..e56add5 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensions.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/HealthConnectClientAggregationExtensions.kt
@@ -21,21 +21,19 @@
 import androidx.annotation.RequiresApi
 import androidx.health.connect.client.HealthConnectClient
 import androidx.health.connect.client.aggregate.AggregationResult
+import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod
 import androidx.health.connect.client.impl.converters.datatype.RECORDS_CLASS_NAME_MAP
-import androidx.health.connect.client.impl.platform.toInstantWithDefaultZoneFallback
-import androidx.health.connect.client.impl.platform.useLocalTime
 import androidx.health.connect.client.records.BloodPressureRecord
 import androidx.health.connect.client.records.CyclingPedalingCadenceRecord
-import androidx.health.connect.client.records.IntervalRecord
 import androidx.health.connect.client.records.NutritionRecord
 import androidx.health.connect.client.records.Record
 import androidx.health.connect.client.records.SpeedRecord
 import androidx.health.connect.client.records.StepsCadenceRecord
+import androidx.health.connect.client.request.AggregateGroupByPeriodRequest
 import androidx.health.connect.client.request.AggregateRequest
 import androidx.health.connect.client.request.ReadRecordsRequest
 import androidx.health.connect.client.time.TimeRangeFilter
 import java.time.Duration
-import kotlin.reflect.KClass
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.flow
 
@@ -54,48 +52,96 @@
 internal suspend fun HealthConnectClient.aggregateFallback(
     request: AggregateRequest
 ): AggregationResult {
-    var aggregationResult = emptyAggregationResult()
+    val aggregationResult =
+        AGGREGATION_FALLBACK_RECORD_TYPES.associateWith { recordType ->
+                request.withFilteredMetrics {
+                    it.dataTypeName == RECORDS_CLASS_NAME_MAP[recordType]!!
+                }
+            }
+            .filterValues { it.metrics.isNotEmpty() }
+            .map {
+                val recordType = it.key
+                val recordTypeRequest = it.value
 
-    for (recordType in AGGREGATION_FALLBACK_RECORD_TYPES) {
-        aggregationResult +=
-            aggregate(recordType, request.withFilteredMetrics { !it.isPlatformSupportedMetric() })
-    }
-
-    return aggregationResult
+                // Calculate the aggregation result for a single record type
+                when (recordType) {
+                    BloodPressureRecord::class -> aggregateBloodPressure(recordTypeRequest)
+                    CyclingPedalingCadenceRecord::class ->
+                        aggregateSeriesRecord(
+                            CyclingPedalingCadenceRecord::class,
+                            recordTypeRequest
+                        )
+                    NutritionRecord::class -> aggregateNutritionTransFatTotal(recordTypeRequest)
+                    SpeedRecord::class ->
+                        aggregateSeriesRecord(SpeedRecord::class, recordTypeRequest)
+                    StepsCadenceRecord::class ->
+                        aggregateSeriesRecord(StepsCadenceRecord::class, recordTypeRequest)
+                    else -> error("Invalid record type for aggregation fallback: $recordType")
+                }
+            }
+            .reduceOrNull {
+                // Reduce into a single AggregationResult containing metrics across all the record
+                // types above
+                accumulator,
+                element ->
+                accumulator + element
+            }
+    return aggregationResult ?: AggregationResult(emptyMap(), emptyMap(), emptySet())
 }
 
-private suspend fun <T : Record> HealthConnectClient.aggregate(
-    recordType: KClass<T>,
-    request: AggregateRequest,
-): AggregationResult {
-    val dataTypeName = RECORDS_CLASS_NAME_MAP[recordType]
-    val recordTypeRequest = request.withFilteredMetrics { it.dataTypeName == dataTypeName }
+internal suspend fun HealthConnectClient.aggregateFallback(
+    request: AggregateGroupByPeriodRequest
+): List<AggregationResultGroupedByPeriod> {
+    return AGGREGATION_FALLBACK_RECORD_TYPES.associateWith { recordType ->
+            request.withFilteredMetrics { it.dataTypeName == RECORDS_CLASS_NAME_MAP[recordType]!! }
+        }
+        .filterValues { it.metrics.isNotEmpty() }
+        .flatMap {
+            val recordType = it.key
+            val recordTypeRequest = it.value
 
-    if (recordTypeRequest.metrics.isEmpty()) {
-        return emptyAggregationResult()
-    }
+            val buckets: List<AggregationResultGroupedByPeriod> =
+                when (recordType) {
+                    BloodPressureRecord::class -> aggregateBloodPressure(recordTypeRequest)
+                    CyclingPedalingCadenceRecord::class ->
+                        aggregateSeriesRecord(
+                            CyclingPedalingCadenceRecord::class,
+                            recordTypeRequest
+                        )
+                    NutritionRecord::class -> aggregateNutritionTransFatTotal(recordTypeRequest)
+                    SpeedRecord::class ->
+                        aggregateSeriesRecord(SpeedRecord::class, recordTypeRequest)
+                    StepsCadenceRecord::class ->
+                        aggregateSeriesRecord(StepsCadenceRecord::class, recordTypeRequest)
+                    else -> error("Invalid record type for aggregation fallback: $recordType")
+                }
 
-    return when (recordType) {
-        BloodPressureRecord::class -> aggregateBloodPressure(recordTypeRequest)
-        CyclingPedalingCadenceRecord::class ->
-            aggregateSeriesRecord(CyclingPedalingCadenceRecord::class, recordTypeRequest) {
-                samples.map { SampleInfo(it.time, it.revolutionsPerMinute) }
-            }
-        NutritionRecord::class -> aggregateNutritionTransFatTotal(recordTypeRequest)
-        SpeedRecord::class ->
-            aggregateSeriesRecord(SpeedRecord::class, recordTypeRequest) {
-                samples.map { SampleInfo(it.time, it.speed.inMetersPerSecond) }
-            }
-        StepsCadenceRecord::class ->
-            aggregateSeriesRecord(StepsCadenceRecord::class, recordTypeRequest) {
-                samples.map { SampleInfo(it.time, it.rate) }
-            }
-        else -> error("Invalid record type for aggregation fallback: $recordType")
+            buckets
+        }
+        .groupingBy { it.startTime }
+        .reduce { _, accumulator, element ->
+            AggregationResultGroupedByPeriod(
+                startTime = accumulator.startTime,
+                endTime = accumulator.endTime,
+                result = accumulator.result + element.result
+            )
+        }
+        .values
+        .sortedBy { it.startTime }
+}
+
+internal suspend fun <T : Record, R> HealthConnectClient.aggregate(
+    readRecordsRequest: ReadRecordsRequest<T>,
+    aggregator: Aggregator<T, R>
+): R {
+    readRecordsFlow(readRecordsRequest).collect { records ->
+        records.forEach { aggregator.filterAndAggregate(it) }
     }
+    return aggregator.getResult()
 }
 
 /** Reads all existing records that satisfy [request]. */
-fun <T : Record> HealthConnectClient.readRecordsFlow(
+internal fun <T : Record> HealthConnectClient.readRecordsFlow(
     request: ReadRecordsRequest<T>
 ): Flow<List<T>> {
     return flow {
@@ -108,29 +154,6 @@
     }
 }
 
-internal fun IntervalRecord.overlaps(timeRangeFilter: TimeRangeFilter): Boolean {
-    val startTimeOverlaps: Boolean
-    val endTimeOverlaps: Boolean
-    if (timeRangeFilter.useLocalTime()) {
-        startTimeOverlaps =
-            timeRangeFilter.localEndTime == null ||
-                startTime.isBefore(
-                    timeRangeFilter.localEndTime.toInstantWithDefaultZoneFallback(startZoneOffset)
-                )
-        endTimeOverlaps =
-            timeRangeFilter.localStartTime == null ||
-                endTime.isAfter(
-                    timeRangeFilter.localStartTime.toInstantWithDefaultZoneFallback(endZoneOffset)
-                )
-    } else {
-        startTimeOverlaps =
-            timeRangeFilter.endTime == null || startTime.isBefore(timeRangeFilter.endTime)
-        endTimeOverlaps =
-            timeRangeFilter.startTime == null || endTime.isAfter(timeRangeFilter.startTime)
-    }
-    return startTimeOverlaps && endTimeOverlaps
-}
-
 internal fun TimeRangeFilter.withBufferedStart(): TimeRangeFilter {
     return TimeRangeFilter(
         startTime = startTime?.minus(RECORD_START_TIME_BUFFER),
@@ -140,9 +163,6 @@
     )
 }
 
-internal fun emptyAggregationResult() =
-    AggregationResult(longValues = mapOf(), doubleValues = mapOf(), dataOrigins = setOf())
-
 internal data class AvgData(var count: Int = 0, var total: Double = 0.0) {
     operator fun plusAssign(value: Double) {
         count++
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensions.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensions.kt
index 583f581..c27d07c 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensions.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/NutritionAggregationExtensions.kt
@@ -19,74 +19,64 @@
 package androidx.health.connect.client.impl.platform.aggregate
 
 import androidx.annotation.RequiresApi
+import androidx.annotation.VisibleForTesting
 import androidx.health.connect.client.HealthConnectClient
 import androidx.health.connect.client.aggregate.AggregationResult
-import androidx.health.connect.client.impl.platform.div
-import androidx.health.connect.client.impl.platform.duration
-import androidx.health.connect.client.impl.platform.minus
-import androidx.health.connect.client.impl.platform.toInstantWithDefaultZoneFallback
-import androidx.health.connect.client.impl.platform.useLocalTime
-import androidx.health.connect.client.records.IntervalRecord
+import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod
 import androidx.health.connect.client.records.NutritionRecord
 import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.request.AggregateGroupByPeriodRequest
 import androidx.health.connect.client.request.AggregateRequest
 import androidx.health.connect.client.request.ReadRecordsRequest
-import androidx.health.connect.client.time.TimeRangeFilter
-import java.time.Instant
-import kotlin.math.max
 
 internal suspend fun HealthConnectClient.aggregateNutritionTransFatTotal(
     aggregateRequest: AggregateRequest
 ): AggregationResult {
-    val aggregator = TransFatTotalAggregator(aggregateRequest.timeRangeFilter)
-
-    readRecordsFlow(
-            ReadRecordsRequest(
-                NutritionRecord::class,
-                aggregateRequest.timeRangeFilter.withBufferedStart(),
-                aggregateRequest.dataOriginFilter
-            )
-        )
-        .collect { records ->
-            records
-                .filter { it.overlaps(aggregateRequest.timeRangeFilter) }
-                .forEach { aggregator += it }
-        }
-
-    return aggregator.getResult()
+    val timeRange = createTimeRange(aggregateRequest.timeRangeFilter)
+    return aggregate(
+        ReadRecordsRequest(
+            NutritionRecord::class,
+            aggregateRequest.timeRangeFilter.withBufferedStart(),
+            aggregateRequest.dataOriginFilter
+        ),
+        ResultAggregator(timeRange, TransFatTotalAggregationProcessor(timeRange))
+    )
 }
 
-internal fun IntervalRecord.sliceFactor(timeRangeFilter: TimeRangeFilter): Double {
-    val startTime: Instant
-    val endTime: Instant
+internal suspend fun HealthConnectClient.aggregateNutritionTransFatTotal(
+    aggregateRequest: AggregateGroupByPeriodRequest
+): List<AggregationResultGroupedByPeriod> {
+    return aggregate(
+        ReadRecordsRequest(
+            NutritionRecord::class,
+            aggregateRequest.timeRangeFilter.withBufferedStart(),
+            aggregateRequest.dataOriginFilter
+        ),
+        ResultGroupedByPeriodAggregator(
+            createLocalTimeRange(aggregateRequest.timeRangeFilter),
+            aggregateRequest.timeRangeSlicer
+        ) {
+            TransFatTotalAggregationProcessor(it)
+        }
+    )
+}
 
-    if (timeRangeFilter.useLocalTime()) {
-        val requestStartTime =
-            timeRangeFilter.localStartTime?.toInstantWithDefaultZoneFallback(startZoneOffset)
-        val requestEndTime =
-            timeRangeFilter.localEndTime?.toInstantWithDefaultZoneFallback(endZoneOffset)
-        startTime = maxOf(this.startTime, requestStartTime ?: this.startTime)
-        endTime = minOf(this.endTime, requestEndTime ?: this.endTime)
-    } else {
-        startTime = maxOf(this.startTime, timeRangeFilter.startTime ?: this.startTime)
-        endTime = minOf(this.endTime, timeRangeFilter.endTime ?: this.endTime)
+@VisibleForTesting
+internal class TransFatTotalAggregationProcessor(private val timeRange: TimeRange<*>) :
+    AggregationProcessor<NutritionRecord> {
+
+    private var total = 0.0
+    private val dataOrigins = mutableSetOf<DataOrigin>()
+
+    override fun processRecord(record: NutritionRecord) {
+        total += record.transFat!!.inGrams * AggregatorUtils.sliceFactor(record, timeRange)
+        dataOrigins += record.metadata.dataOrigin
     }
 
-    return max(0.0, (endTime - startTime) / duration)
-}
-
-private class TransFatTotalAggregator(val timeRangeFilter: TimeRangeFilter) :
-    SingeResultAggregator<NutritionRecord>() {
-    var total = 0.0
-
-    override val dataOrigins = mutableSetOf<DataOrigin>()
-    override val doubleValues: Map<String, Double>
-        get() = mapOf(NutritionRecord.TRANS_FAT_TOTAL.metricKey to total)
-
-    override operator fun plusAssign(value: NutritionRecord) {
-        if (value.transFat != null && value.sliceFactor(timeRangeFilter) > 0) {
-            total += value.transFat.inGrams * value.sliceFactor(timeRangeFilter)
-            dataOrigins += value.metadata.dataOrigin
-        }
+    override fun getProcessedAggregationResult(): AggregationResult {
+        val doubleValues =
+            if (dataOrigins.isEmpty()) emptyMap()
+            else mapOf(NutritionRecord.TRANS_FAT_TOTAL.metricKey to total)
+        return AggregationResult(emptyMap(), doubleValues, dataOrigins)
     }
 }
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/ResultAggregator.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/ResultAggregator.kt
new file mode 100644
index 0000000..3795f69
--- /dev/null
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/ResultAggregator.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.health.connect.client.impl.platform.aggregate
+
+import androidx.health.connect.client.aggregate.AggregationResult
+import androidx.health.connect.client.records.Record
+import java.time.temporal.Temporal
+
+/**
+ * Implementation of [Aggregator] that aggregates into [AggregationResult].
+ *
+ * @param processor the [AggregationProcessor] that does the actual computation after records are
+ *   filtered.
+ */
+internal class ResultAggregator<T : Record, U : Temporal>(
+    private val timeRange: TimeRange<U>,
+    private val processor: AggregationProcessor<T>
+) : Aggregator<T, AggregationResult> {
+
+    override fun filterAndAggregate(record: T) {
+        if (AggregatorUtils.contributesToAggregation(record, timeRange)) {
+            processor.processRecord(record)
+        }
+    }
+
+    override fun getResult(): AggregationResult {
+        return processor.getProcessedAggregationResult()
+    }
+}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/ResultGroupedByPeriodAggregator.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/ResultGroupedByPeriodAggregator.kt
new file mode 100644
index 0000000..dc4881d
--- /dev/null
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/ResultGroupedByPeriodAggregator.kt
@@ -0,0 +1,123 @@
+/*
+ * 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.health.connect.client.impl.platform.aggregate
+
+import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod
+import androidx.health.connect.client.impl.platform.toLocalTimeWithDefaultZoneFallback
+import androidx.health.connect.client.records.InstantaneousRecord
+import androidx.health.connect.client.records.IntervalRecord
+import androidx.health.connect.client.records.Record
+import java.time.LocalDateTime
+import java.time.Period
+import kotlin.math.max
+import kotlin.math.min
+
+/**
+ * Implementation of [ResultGroupedByPeriodAggregator] that aggregates into
+ * [AggregationResultGroupedByPeriod] buckets.
+ *
+ * @param initProcessor initialization function for an [AggregationProcessor] that does the actual
+ *   computation per bucket.
+ */
+internal class ResultGroupedByPeriodAggregator<T : Record>(
+    private val timeRange: LocalTimeRange,
+    private val bucketPeriod: Period,
+    private val initProcessor: (LocalTimeRange) -> AggregationProcessor<T>
+) : Aggregator<T, List<AggregationResultGroupedByPeriod>> {
+
+    private val totalBuckets: Int
+
+    private val bucketProcessors = mutableMapOf<Int, AggregationProcessor<T>>()
+
+    init {
+        val bucketIndexOfEndTime = getBucketIndex(timeRange.endTime)
+        val isEndTimeAlsoBucketEnd =
+            (timeRange.startTime + (bucketPeriod.multipliedBy(bucketIndexOfEndTime))) ==
+                timeRange.endTime
+
+        // Bucked index is zero-based and end time is exclusive. When the end time matches a bucket
+        // end its index will correspond to a start of a bucket outside of the query range, which
+        // matches the number of buckets.
+        totalBuckets =
+            if (isEndTimeAlsoBucketEnd) bucketIndexOfEndTime else bucketIndexOfEndTime + 1
+    }
+
+    override fun filterAndAggregate(record: T) {
+        if (!AggregatorUtils.contributesToAggregation(record, timeRange)) {
+            return
+        }
+
+        val startBucketIndex: Int
+        val endBucketIndex: Int
+
+        when (record) {
+            is InstantaneousRecord -> {
+                startBucketIndex =
+                    getBucketIndex(
+                        record.time.toLocalTimeWithDefaultZoneFallback(record.zoneOffset)
+                    )
+                endBucketIndex = startBucketIndex
+            }
+            is IntervalRecord -> {
+                startBucketIndex =
+                    getBucketIndex(
+                        record.startTime.toLocalTimeWithDefaultZoneFallback(record.startZoneOffset)
+                    )
+                endBucketIndex =
+                    getBucketIndex(
+                        record.endTime.toLocalTimeWithDefaultZoneFallback(record.endZoneOffset)
+                    )
+            }
+            else -> error("Unsupported value for aggregation: $record")
+        }
+
+        val bucketRange = max(startBucketIndex, 0)..min(endBucketIndex, totalBuckets - 1)
+
+        for (index in bucketRange) {
+            val timeRange = getBucketTimeRange(index)
+            if (AggregatorUtils.contributesToAggregation(record, timeRange)) {
+                bucketProcessors.getOrPut(index) { initProcessor(timeRange) }.processRecord(record)
+            }
+        }
+    }
+
+    override fun getResult(): List<AggregationResultGroupedByPeriod> {
+        return bucketProcessors.map {
+            AggregationResultGroupedByPeriod(
+                result = it.value.getProcessedAggregationResult(),
+                startTime = getBucketTimeRange(it.key).startTime,
+                endTime = getBucketTimeRange(it.key).endTime
+            )
+        }
+    }
+
+    private fun getBucketIndex(time: LocalDateTime): Int {
+        var bucketEndTime = timeRange.startTime
+        var index = -1
+        while (time >= bucketEndTime) {
+            bucketEndTime += bucketPeriod
+            index++
+        }
+        return index
+    }
+
+    private fun getBucketTimeRange(index: Int): LocalTimeRange {
+        val bucketStartTime = timeRange.startTime + bucketPeriod.multipliedBy(index)
+        val bucketEndTime = minOf(bucketStartTime + bucketPeriod, timeRange.endTime)
+        return LocalTimeRange(bucketStartTime, bucketEndTime)
+    }
+}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensions.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensions.kt
index 01265d5e..696ac33 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensions.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/SeriesRecordAggregationExtensions.kt
@@ -23,18 +23,18 @@
 import androidx.health.connect.client.HealthConnectClient
 import androidx.health.connect.client.aggregate.AggregateMetric
 import androidx.health.connect.client.aggregate.AggregationResult
-import androidx.health.connect.client.impl.platform.toInstantWithDefaultZoneFallback
-import androidx.health.connect.client.impl.platform.useLocalTime
+import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod
+import androidx.health.connect.client.impl.platform.aggregate.AggregatorUtils.time
+import androidx.health.connect.client.impl.platform.aggregate.AggregatorUtils.value
+import androidx.health.connect.client.impl.platform.isWithin
 import androidx.health.connect.client.records.CyclingPedalingCadenceRecord
 import androidx.health.connect.client.records.SeriesRecord
 import androidx.health.connect.client.records.SpeedRecord
 import androidx.health.connect.client.records.StepsCadenceRecord
 import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.request.AggregateGroupByPeriodRequest
 import androidx.health.connect.client.request.AggregateRequest
 import androidx.health.connect.client.request.ReadRecordsRequest
-import androidx.health.connect.client.time.TimeRangeFilter
-import java.time.Instant
-import java.time.ZoneOffset
 import kotlin.math.max
 import kotlin.math.min
 import kotlin.reflect.KClass
@@ -63,86 +63,89 @@
 
 internal suspend fun <T : SeriesRecord<*>> HealthConnectClient.aggregateSeriesRecord(
     recordType: KClass<T>,
-    aggregateRequest: AggregateRequest,
-    getSampleInfo: T.() -> List<SampleInfo>
+    aggregateRequest: AggregateRequest
 ): AggregationResult {
-    val readRecordsFlow =
-        readRecordsFlow(
-            ReadRecordsRequest(
-                recordType,
-                aggregateRequest.timeRangeFilter.withBufferedStart(),
-                aggregateRequest.dataOriginFilter
-            )
+    val timeRange = createTimeRange(aggregateRequest.timeRangeFilter)
+    return aggregate(
+        ReadRecordsRequest(
+            recordType,
+            aggregateRequest.timeRangeFilter.withBufferedStart(),
+            aggregateRequest.dataOriginFilter
+        ),
+        ResultAggregator(
+            timeRange,
+            SeriesAggregationProcessor(recordType, aggregateRequest.metrics, timeRange)
         )
-
-    val aggregator = SeriesAggregator(recordType, aggregateRequest.metrics)
-    readRecordsFlow.collect { records ->
-        records
-            .asSequence()
-            .map {
-                RecordInfo(
-                    dataOrigin = it.metadata.dataOrigin,
-                    samples =
-                        it.getSampleInfo().filter { sample ->
-                            sample.isWithin(
-                                timeRangeFilter = aggregateRequest.timeRangeFilter,
-                                zoneOffset = it.startZoneOffset
-                            )
-                        }
-                )
-            }
-            .filter { it.samples.isNotEmpty() }
-            .forEach { recordInfo -> aggregator += recordInfo }
-    }
-
-    return aggregator.getResult()
+    )
 }
 
-private class SeriesAggregator<T : SeriesRecord<*>>(
+internal suspend fun <T : SeriesRecord<*>> HealthConnectClient.aggregateSeriesRecord(
     recordType: KClass<T>,
-    val aggregateMetrics: Set<AggregateMetric<*>>
-) : SingeResultAggregator<RecordInfo>() {
+    aggregateRequest: AggregateGroupByPeriodRequest
+): List<AggregationResultGroupedByPeriod> {
+    return aggregate(
+        ReadRecordsRequest(
+            recordType,
+            aggregateRequest.timeRangeFilter.withBufferedStart(),
+            aggregateRequest.dataOriginFilter
+        ),
+        ResultGroupedByPeriodAggregator(
+            createLocalTimeRange(aggregateRequest.timeRangeFilter),
+            aggregateRequest.timeRangeSlicer
+        ) {
+            SeriesAggregationProcessor(recordType, aggregateRequest.metrics, it)
+        }
+    )
+}
 
+private class SeriesAggregationProcessor<T : SeriesRecord<*>>(
+    recordType: KClass<T>,
+    val metrics: Set<AggregateMetric<*>>,
+    val timeRange: TimeRange<*>,
+) : AggregationProcessor<T> {
     val avgData = AvgData()
     var min: Double? = null
     var max: Double? = null
 
-    override val dataOrigins = mutableSetOf<DataOrigin>()
+    private val dataOrigins = mutableSetOf<DataOrigin>()
 
-    override val doubleValues: Map<String, Double>
-        get() = buildMap {
-            for (metric in aggregateMetrics) {
-                val result =
-                    when (metric) {
-                        aggregateInfo.averageMetric -> avgData.average()
-                        aggregateInfo.maxMetric -> max!!
-                        aggregateInfo.minMetric -> min!!
-                        else -> error("Invalid fallback aggregation metric ${metric.metricKey}")
-                    }
-                put(metric.metricKey, result)
-            }
-        }
-
-    val aggregateInfo =
+    private val aggregateInfo =
         RECORDS_TO_AGGREGATE_METRICS_INFO_MAP[recordType]
             ?: throw IllegalArgumentException("Non supported fallback series record $recordType")
 
     init {
         check(
             setOf(aggregateInfo.averageMetric, aggregateInfo.minMetric, aggregateInfo.maxMetric)
-                .containsAll(aggregateMetrics)
+                .containsAll(metrics)
         ) {
-            "Invalid set of metrics ${aggregateMetrics.map { it.metricKey }}"
+            "Invalid set of metrics ${metrics.map { it.metricKey }}"
         }
     }
 
-    override fun plusAssign(value: RecordInfo) {
-        value.samples.forEach {
-            avgData += it.value
-            min = min(min ?: it.value, it.value)
-            max = max(max ?: it.value, it.value)
-        }
-        dataOrigins += value.dataOrigin
+    override fun processRecord(record: T) {
+        record.samples
+            .filter { it.time.isWithin(timeRange, record.startZoneOffset) }
+            .forEach {
+                avgData += it.value
+                min = min(min ?: it.value, it.value)
+                max = max(max ?: it.value, it.value)
+            }
+        dataOrigins += record.metadata.dataOrigin
+    }
+
+    override fun getProcessedAggregationResult(): AggregationResult {
+        val doubleValues =
+            if (dataOrigins.isEmpty()) emptyMap()
+            else
+                metrics.associateBy({ it.metricKey }) { metric ->
+                    when (metric) {
+                        aggregateInfo.averageMetric -> avgData.average()
+                        aggregateInfo.maxMetric -> max!!
+                        aggregateInfo.minMetric -> min!!
+                        else -> error("Invalid fallback aggregation metric ${metric.metricKey}")
+                    }
+                }
+        return AggregationResult(emptyMap(), doubleValues, dataOrigins)
     }
 }
 
@@ -152,37 +155,3 @@
     val minMetric: AggregateMetric<T>,
     val maxMetric: AggregateMetric<T>
 )
-
-@VisibleForTesting
-internal data class RecordInfo(val dataOrigin: DataOrigin, val samples: List<SampleInfo>)
-
-internal data class SampleInfo(val time: Instant, val value: Double) {
-    fun isWithin(timeRangeFilter: TimeRangeFilter, zoneOffset: ZoneOffset?): Boolean {
-        if (timeRangeFilter.useLocalTime()) {
-            if (
-                timeRangeFilter.localStartTime != null &&
-                    time.isBefore(
-                        timeRangeFilter.localStartTime.toInstantWithDefaultZoneFallback(zoneOffset)
-                    )
-            ) {
-                return false
-            }
-            if (
-                timeRangeFilter.localEndTime != null &&
-                    !time.isBefore(
-                        timeRangeFilter.localEndTime.toInstantWithDefaultZoneFallback(zoneOffset)
-                    )
-            ) {
-                return false
-            }
-            return true
-        }
-        if (timeRangeFilter.startTime != null && time.isBefore(timeRangeFilter.startTime)) {
-            return false
-        }
-        if (timeRangeFilter.endTime != null && !time.isBefore(timeRangeFilter.endTime)) {
-            return false
-        }
-        return true
-    }
-}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/TimeRanges.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/TimeRanges.kt
new file mode 100644
index 0000000..55e604e
--- /dev/null
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/impl/platform/aggregate/TimeRanges.kt
@@ -0,0 +1,67 @@
+/*
+ * 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.health.connect.client.impl.platform.aggregate
+
+import androidx.health.connect.client.time.TimeRangeFilter
+import java.time.Duration
+import java.time.Instant
+import java.time.LocalDateTime
+import java.time.ZoneOffset
+import java.time.temporal.Temporal
+
+internal sealed interface TimeRange<T : Temporal> {
+    val startTime: T
+    val endTime: T
+}
+
+internal data class InstantTimeRange(
+    override val startTime: Instant,
+    override val endTime: Instant
+) : TimeRange<Instant>
+
+internal data class LocalTimeRange(
+    override val startTime: LocalDateTime,
+    override val endTime: LocalDateTime
+) : TimeRange<LocalDateTime>
+
+internal fun createTimeRange(timeRangeFilter: TimeRangeFilter): TimeRange<*> {
+    if (timeRangeFilter.isBasedOnLocalTime()) {
+        return createLocalTimeRange(timeRangeFilter)
+    }
+    return createInstantTimeRange(timeRangeFilter)
+}
+
+internal fun createInstantTimeRange(timeRangeFilter: TimeRangeFilter): InstantTimeRange {
+    require(!timeRangeFilter.isBasedOnLocalTime()) {
+        "TimeRangeFilter should be based on instant time"
+    }
+    val startTime = timeRangeFilter.startTime ?: Instant.EPOCH
+    val endTime = timeRangeFilter.endTime ?: Instant.now()
+    return InstantTimeRange(startTime, endTime)
+}
+
+internal fun createLocalTimeRange(timeRangeFilter: TimeRangeFilter): LocalTimeRange {
+    require(timeRangeFilter.isBasedOnLocalTime()) {
+        "TimeRangeFilter should be based on local time"
+    }
+    val startTime =
+        timeRangeFilter.localStartTime ?: LocalDateTime.ofInstant(Instant.EPOCH, ZoneOffset.MIN)
+    val endTime =
+        timeRangeFilter.localEndTime
+            ?: LocalDateTime.ofInstant(Instant.now().plus(Duration.ofDays(1)), ZoneOffset.MAX)
+    return LocalTimeRange(startTime, endTime)
+}
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/time/TimeRangeFilter.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/time/TimeRangeFilter.kt
index 864e010..f470e16 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/time/TimeRangeFilter.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/time/TimeRangeFilter.kt
@@ -144,6 +144,10 @@
     internal fun isOpenEnded(): Boolean =
         (localStartTime == null || localEndTime == null) && (startTime == null || endTime == null)
 
+    internal fun isBasedOnLocalTime(): Boolean {
+        return localStartTime != null || localEndTime != null
+    }
+
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (other !is TimeRangeFilter) return false
diff --git a/health/connect/connect-client/src/test/java/androidx/health/connect/client/impl/platform/TimeExtensionsTest.kt b/health/connect/connect-client/src/test/java/androidx/health/connect/client/impl/platform/TimeExtensionsTest.kt
index ceed1c5..a565d75 100644
--- a/health/connect/connect-client/src/test/java/androidx/health/connect/client/impl/platform/TimeExtensionsTest.kt
+++ b/health/connect/connect-client/src/test/java/androidx/health/connect/client/impl/platform/TimeExtensionsTest.kt
@@ -16,6 +16,10 @@
 
 package androidx.health.connect.client.impl.platform
 
+import androidx.health.connect.client.impl.platform.aggregate.InstantTimeRange
+import androidx.health.connect.client.impl.platform.aggregate.LocalTimeRange
+import androidx.health.connect.client.impl.platform.aggregate.createInstantTimeRange
+import androidx.health.connect.client.impl.platform.aggregate.createLocalTimeRange
 import androidx.health.connect.client.records.NutritionRecord
 import androidx.health.connect.client.time.TimeRangeFilter
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -38,13 +42,6 @@
     }
 
     @Test
-    fun dibByZero_returnsZero() {
-        val dividend = Duration.ofHours(1)
-        val divisor = Duration.ofSeconds(0)
-        assertThat(dividend / divisor).isEqualTo(0.0)
-    }
-
-    @Test
     fun minus() {
         val a = Instant.now()
         val b = a.plusSeconds(5)
@@ -52,25 +49,6 @@
     }
 
     @Test
-    fun useLocalTime() {
-        assertThat(TimeRangeFilter.none().useLocalTime()).isFalse()
-        assertThat(
-                TimeRangeFilter.between(Instant.now(), Instant.now().plusSeconds(2)).useLocalTime()
-            )
-            .isFalse()
-        assertThat(TimeRangeFilter.after(Instant.now()).useLocalTime()).isFalse()
-        assertThat(TimeRangeFilter.before(Instant.now()).useLocalTime()).isFalse()
-
-        assertThat(
-                TimeRangeFilter.between(LocalDateTime.now(), LocalDateTime.now().plusSeconds(2))
-                    .useLocalTime()
-            )
-            .isTrue()
-        assertThat(TimeRangeFilter.after(LocalDateTime.now()).useLocalTime()).isTrue()
-        assertThat(TimeRangeFilter.before(LocalDateTime.now()).useLocalTime()).isTrue()
-    }
-
-    @Test
     fun toInstantWithDefaultZoneFallback() {
         val instant = Instant.now()
         val localDateTime = LocalDateTime.ofInstant(instant, ZoneOffset.UTC)
@@ -82,6 +60,94 @@
     }
 
     @Test
+    fun isWithin_instantTimeRange_outOfBounds_returnsFalse() {
+        var timeRange = createInstantTimeRange(TimeRangeFilter.after(Instant.ofEpochMilli(100)))
+        assertThat(Instant.ofEpochMilli(99).isWithin(timeRange)).isFalse()
+
+        timeRange = createInstantTimeRange(TimeRangeFilter.before(Instant.ofEpochMilli(100)))
+        assertThat(Instant.ofEpochMilli(100).isWithin(timeRange)).isFalse()
+        assertThat(Instant.ofEpochMilli(101).isWithin(timeRange)).isFalse()
+
+        timeRange = InstantTimeRange(Instant.ofEpochMilli(100), Instant.ofEpochMilli(200))
+        assertThat(Instant.ofEpochMilli(99).isWithin(timeRange)).isFalse()
+        assertThat(Instant.ofEpochMilli(200).isWithin(timeRange)).isFalse()
+        assertThat(Instant.ofEpochMilli(201).isWithin(timeRange)).isFalse()
+    }
+
+    @Test
+    fun isWithin_localTimeRange_outOfBounds_returnsFalse() {
+        var timeRange =
+            createLocalTimeRange(
+                TimeRangeFilter.after(
+                    Instant.ofEpochMilli(100).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                )
+            )
+        assertThat(Instant.ofEpochMilli(99).isWithin(timeRange, ZoneOffset.UTC)).isFalse()
+
+        timeRange =
+            createLocalTimeRange(
+                TimeRangeFilter.before(
+                    Instant.ofEpochMilli(100).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                )
+            )
+        assertThat(Instant.ofEpochMilli(100).isWithin(timeRange, ZoneOffset.UTC)).isFalse()
+        assertThat(Instant.ofEpochMilli(101).isWithin(timeRange, ZoneOffset.UTC)).isFalse()
+
+        timeRange =
+            LocalTimeRange(
+                Instant.ofEpochMilli(100).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC),
+                Instant.ofEpochMilli(200).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+            )
+        assertThat(Instant.ofEpochMilli(99).isWithin(timeRange, ZoneOffset.UTC)).isFalse()
+        assertThat(Instant.ofEpochMilli(200).isWithin(timeRange, ZoneOffset.UTC)).isFalse()
+        assertThat(Instant.ofEpochMilli(201).isWithin(timeRange, ZoneOffset.UTC)).isFalse()
+    }
+
+    @Test
+    fun isWithin_instantTimeRange_withinBounds_returnsTrue() {
+        var timeRange = createInstantTimeRange(TimeRangeFilter.after(Instant.ofEpochMilli(100)))
+        assertThat(Instant.ofEpochMilli(100).isWithin(timeRange)).isTrue()
+        assertThat(Instant.ofEpochMilli(101).isWithin(timeRange)).isTrue()
+
+        timeRange = createInstantTimeRange(TimeRangeFilter.before(Instant.ofEpochMilli(100)))
+        assertThat(Instant.ofEpochMilli(99).isWithin(timeRange)).isTrue()
+
+        timeRange = InstantTimeRange(Instant.ofEpochMilli(100), Instant.ofEpochMilli(200))
+        assertThat(Instant.ofEpochMilli(100).isWithin(timeRange)).isTrue()
+        assertThat(Instant.ofEpochMilli(101).isWithin(timeRange)).isTrue()
+        assertThat(Instant.ofEpochMilli(199).isWithin(timeRange)).isTrue()
+    }
+
+    @Test
+    fun isWithin_localTimeRange_withinBounds_returnsTrue() {
+        var timeRange =
+            createLocalTimeRange(
+                TimeRangeFilter.after(
+                    Instant.ofEpochMilli(100).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                )
+            )
+        assertThat(Instant.ofEpochMilli(100).isWithin(timeRange, ZoneOffset.UTC)).isTrue()
+        assertThat(Instant.ofEpochMilli(101).isWithin(timeRange, ZoneOffset.UTC)).isTrue()
+
+        timeRange =
+            createLocalTimeRange(
+                TimeRangeFilter.before(
+                    Instant.ofEpochMilli(100).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                )
+            )
+        assertThat(Instant.ofEpochMilli(99).isWithin(timeRange, ZoneOffset.UTC)).isTrue()
+
+        timeRange =
+            LocalTimeRange(
+                Instant.ofEpochMilli(100).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC),
+                Instant.ofEpochMilli(200).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+            )
+        assertThat(Instant.ofEpochMilli(100).isWithin(timeRange, ZoneOffset.UTC)).isTrue()
+        assertThat(Instant.ofEpochMilli(101).isWithin(timeRange, ZoneOffset.UTC)).isTrue()
+        assertThat(Instant.ofEpochMilli(199).isWithin(timeRange, ZoneOffset.UTC)).isTrue()
+    }
+
+    @Test
     fun intervalRecord_duration() {
         val startTime = Instant.now()
         val nutritionRecord =
diff --git a/health/connect/connect-client/src/test/java/androidx/health/connect/client/impl/platform/aggregate/ResultGroupByPeriodAggregatorTest.kt b/health/connect/connect-client/src/test/java/androidx/health/connect/client/impl/platform/aggregate/ResultGroupByPeriodAggregatorTest.kt
new file mode 100644
index 0000000..cf59415
--- /dev/null
+++ b/health/connect/connect-client/src/test/java/androidx/health/connect/client/impl/platform/aggregate/ResultGroupByPeriodAggregatorTest.kt
@@ -0,0 +1,461 @@
+/*
+ * 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.health.connect.client.impl.platform.aggregate
+
+import android.annotation.SuppressLint
+import androidx.health.connect.client.aggregate.AggregationResult
+import androidx.health.connect.client.aggregate.AggregationResultGroupedByPeriod
+import androidx.health.connect.client.impl.platform.toInstantWithDefaultZoneFallback
+import androidx.health.connect.client.impl.platform.toLocalTimeWithDefaultZoneFallback
+import androidx.health.connect.client.records.NutritionRecord
+import androidx.health.connect.client.records.metadata.DataOrigin
+import androidx.health.connect.client.records.metadata.Metadata
+import androidx.health.connect.client.time.TimeRangeFilter
+import androidx.health.connect.client.units.Mass
+import androidx.health.connect.client.units.grams
+import androidx.health.connect.client.units.kilograms
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import java.time.Duration
+import java.time.Instant
+import java.time.LocalDateTime
+import java.time.Period
+import java.time.ZoneOffset
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SuppressLint("NewApi")
+@RunWith(AndroidJUnit4::class)
+class ResultGroupByPeriodAggregatorTest {
+
+    @Test
+    fun getResult_filterShorterThanPeriod_singleBucket() {
+        val aggregator =
+            ResultGroupedByPeriodAggregator(
+                LocalTimeRange(
+                    Instant.ofEpochMilli(100).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC),
+                    Instant.ofEpochMilli(1000).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                ),
+                bucketPeriod = Period.ofDays(1)
+            ) {
+                TransFatTotalAggregationProcessor(it)
+            }
+
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = Instant.ofEpochMilli(100),
+                endTime = Instant.ofEpochMilli(1000),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("some.package")),
+                transFat = 5.grams
+            )
+        )
+
+        assertThat(aggregator.getResult())
+            .containsExactly(
+                AggregationResultGroupedByPeriod(
+                    result = aggregationResult(5.grams, "some.package"),
+                    startTime =
+                        Instant.ofEpochMilli(100)
+                            .toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC),
+                    endTime =
+                        Instant.ofEpochMilli(1000)
+                            .toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                )
+            )
+    }
+
+    @Test
+    fun getResult_filterEndTimeMatchingBucketEnd_bucketBoundariesMatchFilterBoundaries() {
+        val filterStartTime =
+            Instant.ofEpochMilli(100).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+        val filterEndTime = filterStartTime + Period.ofDays(2)
+
+        val aggregator =
+            ResultGroupedByPeriodAggregator(
+                LocalTimeRange(filterStartTime, filterEndTime),
+                bucketPeriod = Period.ofDays(1)
+            ) {
+                TransFatTotalAggregationProcessor(it)
+            }
+
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = filterStartTime.minusDays(1).toInstant(ZoneOffset.UTC),
+                endTime = filterEndTime.plusDays(1).toInstant(ZoneOffset.UTC),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("some.package")),
+                transFat = 10.grams
+            )
+        )
+
+        // Slice factor is 0.25 for each bucket, multiplied by 10 grams, remaining 0.5 is outside of
+        // time range filter
+        val bucketResult = aggregationResult(2.5.grams, "some.package")
+
+        assertThat(aggregator.getResult())
+            .containsExactly(
+                AggregationResultGroupedByPeriod(
+                    bucketResult,
+                    startTime = filterStartTime,
+                    endTime = filterStartTime.plusDays(1)
+                ),
+                AggregationResultGroupedByPeriod(
+                    bucketResult,
+                    startTime = filterStartTime.plusDays(1),
+                    filterEndTime
+                )
+            )
+    }
+
+    @Test
+    fun getResult_recordsAcrossMultipleBuckets_onlyReturnsBucketsWithRecords() {
+        val filterStartTime = Instant.ofEpochMilli(100)
+        val filterEndTime = filterStartTime + Period.ofDays(5)
+
+        val aggregator =
+            ResultGroupedByPeriodAggregator(
+                LocalTimeRange(
+                    filterStartTime.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC),
+                    filterEndTime.toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                ),
+                bucketPeriod = Period.ofDays(1)
+            ) {
+                TransFatTotalAggregationProcessor(it)
+            }
+
+        // Out of bounds records
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = Instant.ofEpochMilli(1),
+                endTime = Instant.ofEpochMilli(99),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("out.package")),
+                transFat = 10.grams
+            )
+        )
+
+        // Record in bucket 1 (skip bucket 0)
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = filterStartTime.plus(Duration.ofDays(1)).plusMillis(1),
+                endTime = filterStartTime.plus(Duration.ofDays(1)).plusMillis(100),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("bucket_1.package")),
+                transFat = 10.grams
+            )
+        )
+
+        // Record in bucket 2
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = filterStartTime.plus(Duration.ofDays(2)),
+                endTime = filterStartTime.plus(Duration.ofDays(2)).plusMillis(100),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("bucket_2.package")),
+                transFat = 100.grams
+            )
+        )
+
+        // Record split in half between buckets 1 and 2
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = filterStartTime.plus(Duration.ofDays(1)).plus(Duration.ofHours(12)),
+                endTime = filterStartTime.plus(Duration.ofDays(2)).plus(Duration.ofHours(12)),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("buckets_1_2.package")),
+                transFat = 1.kilograms
+            )
+        )
+
+        // Record 0.25 slice factor in bucket 4, remaining is beyond end of time range filter
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = filterStartTime.plus(Duration.ofDays(4)).plus(Duration.ofHours(18)),
+                endTime = filterStartTime.plus(Duration.ofDays(5)).plus(Duration.ofHours(18)),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("bucket_4.package")),
+                transFat = 10.kilograms
+            )
+        )
+
+        assertThat(aggregator.getResult())
+            .containsExactly(
+                AggregationResultGroupedByPeriod(
+                    aggregationResult(510.grams, "bucket_1.package", "buckets_1_2.package"),
+                    startTime =
+                        filterStartTime
+                            .toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                            .plusDays(1),
+                    endTime =
+                        filterStartTime
+                            .toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                            .plusDays(2)
+                ),
+                AggregationResultGroupedByPeriod(
+                    aggregationResult(600.grams, "bucket_2.package", "buckets_1_2.package"),
+                    startTime =
+                        filterStartTime
+                            .toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                            .plusDays(2),
+                    endTime =
+                        filterStartTime
+                            .toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                            .plusDays(3)
+                ),
+                AggregationResultGroupedByPeriod(
+                    aggregationResult(2.5.kilograms, "bucket_4.package"),
+                    startTime =
+                        filterStartTime
+                            .toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                            .plusDays(4),
+                    endTime =
+                        filterStartTime
+                            .toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                            .plusDays(5)
+                ),
+            )
+    }
+
+    @Test
+    fun getResult_multipleZoneOffsets_resultCalculatedBasedOnLocalTime() {
+        val filterStartTime = LocalDateTime.parse("2024-12-13T00:00:00")
+        val filterEndTime = filterStartTime.plusDays(2)
+
+        val aggregator =
+            ResultGroupedByPeriodAggregator(
+                LocalTimeRange(filterStartTime, filterEndTime),
+                bucketPeriod = Period.ofDays(1)
+            ) {
+                TransFatTotalAggregationProcessor(it)
+            }
+
+        // Record only in first bucket
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = filterStartTime.toInstantWithDefaultZoneFallback(ZoneOffset.ofHours(2)),
+                endTime =
+                    filterStartTime
+                        .toInstantWithDefaultZoneFallback(ZoneOffset.ofHours(3))
+                        .plus(Duration.ofDays(1))
+                        .minusMillis(100),
+                startZoneOffset = ZoneOffset.ofHours(2),
+                endZoneOffset = ZoneOffset.ofHours(3),
+                metadata = Metadata(dataOrigin = DataOrigin("first.package")),
+                transFat = 10.grams
+            )
+        )
+
+        // Record split in half between first and second bucket
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime =
+                    filterStartTime
+                        .toInstantWithDefaultZoneFallback(ZoneOffset.UTC)
+                        .plus(Duration.ofHours(12)),
+                endTime =
+                    filterStartTime
+                        .toInstantWithDefaultZoneFallback(ZoneOffset.UTC)
+                        .plus(Duration.ofDays(1))
+                        .plus(Duration.ofHours(12)),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("first_second.package")),
+                transFat = 100.grams
+            )
+        )
+
+        assertThat(aggregator.getResult())
+            .containsExactly(
+                AggregationResultGroupedByPeriod(
+                    aggregationResult(60.grams, "first.package", "first_second.package"),
+                    startTime = filterStartTime,
+                    endTime = filterStartTime.plusDays(1)
+                ),
+                AggregationResultGroupedByPeriod(
+                    aggregationResult(50.grams, "first_second.package"),
+                    startTime = filterStartTime.plusDays(1),
+                    endTime = filterEndTime
+                )
+            )
+    }
+
+    @Test
+    fun getResult_monthlyBucket_bucketsSplitByMonth() {
+        val filterStartTime = LocalDateTime.parse("2024-01-27T00:00:00")
+        val filterEndTime = LocalDateTime.parse("2024-03-31T13:00:00")
+
+        val aggregator =
+            ResultGroupedByPeriodAggregator(
+                LocalTimeRange(filterStartTime, filterEndTime),
+                bucketPeriod = Period.ofMonths(1)
+            ) {
+                TransFatTotalAggregationProcessor(it)
+            }
+
+        // January (out of range)
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = Instant.parse("2024-01-04T10:12:30.00Z"),
+                endTime = Instant.parse("2024-01-15T10:11:30.00Z"),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("january_out.package")),
+                transFat = 100.kilograms
+            )
+        )
+
+        // January (within range)
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = Instant.parse("2024-01-28T10:15:30.00Z"),
+                endTime = Instant.parse("2024-01-28T10:17:30.00Z"),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("january.package")),
+                transFat = 10.grams
+            )
+        )
+
+        // February
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = Instant.parse("2024-02-28T10:15:30.00Z"),
+                endTime = Instant.parse("2024-02-29T10:17:30.00Z"),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("february.package")),
+                transFat = 100.grams
+            )
+        )
+
+        // March
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = Instant.parse("2024-03-27T10:15:30.00Z"),
+                endTime = Instant.parse("2024-03-27T10:17:30.00Z"),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("march.package")),
+                transFat = 1.kilograms
+            )
+        )
+
+        // March (half within_range)
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = Instant.parse("2024-03-31T12:00:00.00Z"),
+                endTime = Instant.parse("2024-03-31T14:00:00.00Z"),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("march_half.package")),
+                transFat = 10.kilograms
+            )
+        )
+
+        assertThat(aggregator.getResult())
+            .containsExactly(
+                AggregationResultGroupedByPeriod(
+                    aggregationResult(10.grams, "january.package"),
+                    filterStartTime,
+                    endTime = LocalDateTime.parse("2024-02-27T00:00:00")
+                ),
+                AggregationResultGroupedByPeriod(
+                    aggregationResult(100.grams, "february.package"),
+                    startTime = LocalDateTime.parse("2024-02-27T00:00:00"),
+                    endTime = LocalDateTime.parse("2024-03-27T00:00:00")
+                ),
+                AggregationResultGroupedByPeriod(
+                    aggregationResult(6.kilograms, "march.package", "march_half.package"),
+                    startTime = LocalDateTime.parse("2024-03-27T00:00:00"),
+                    filterEndTime
+                ),
+            )
+    }
+
+    @Test
+    fun getResult_recordNeededForCalculation_returnsMapWithResult() {
+        val aggregator =
+            ResultGroupedByPeriodAggregator(
+                createLocalTimeRange(
+                    TimeRangeFilter.after(
+                        Instant.ofEpochMilli(100).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                    )
+                ),
+                bucketPeriod = Period.ofDays(1)
+            ) {
+                TransFatTotalAggregationProcessor(it)
+            }
+
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = Instant.ofEpochMilli(100),
+                endTime = Instant.ofEpochMilli(1000),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("some.package")),
+                transFat = 5.grams
+            )
+        )
+
+        assertThat(aggregator.getResult()).isNotEmpty()
+    }
+
+    @Test
+    fun getResult_recordOutOfBounds_returnsEmptyMap() {
+        val aggregator =
+            ResultGroupedByPeriodAggregator(
+                LocalTimeRange(
+                    Instant.ofEpochMilli(100).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC),
+                    Instant.ofEpochMilli(200).toLocalTimeWithDefaultZoneFallback(ZoneOffset.UTC)
+                ),
+                bucketPeriod = Period.ofDays(1)
+            ) {
+                TransFatTotalAggregationProcessor(it)
+            }
+
+        aggregator.filterAndAggregate(
+            NutritionRecord(
+                startTime = Instant.ofEpochMilli(100).plus(Duration.ofDays(10)),
+                endTime = Instant.ofEpochMilli(1000).plus(Duration.ofDays(10)),
+                startZoneOffset = ZoneOffset.UTC,
+                endZoneOffset = ZoneOffset.UTC,
+                metadata = Metadata(dataOrigin = DataOrigin("some.package")),
+                transFat = 5.grams
+            )
+        )
+
+        assertThat(aggregator.getResult()).isEmpty()
+    }
+
+    private companion object {
+        private fun aggregationResult(transFatTotalMass: Mass, vararg packageNames: String) =
+            AggregationResult(
+                longValues = emptyMap(),
+                doubleValues =
+                    mapOf(NutritionRecord.TRANS_FAT_TOTAL.metricKey to transFatTotalMass.inGrams),
+                dataOrigins = packageNames.map { DataOrigin(it) }.toSet()
+            )
+    }
+}
diff --git a/leanback/leanback/src/main/res/values-te/strings.xml b/leanback/leanback/src/main/res/values-te/strings.xml
index 73556b5..535cfaa 100644
--- a/leanback/leanback/src/main/res/values-te/strings.xml
+++ b/leanback/leanback/src/main/res/values-te/strings.xml
@@ -26,7 +26,7 @@
     <string name="lb_control_display_fast_forward_multiplier" msgid="4657191930956702614">"%1$dX"</string>
     <string name="lb_control_display_rewind_multiplier" msgid="4597148235912710942">"%1$dX"</string>
     <string name="lb_playback_controls_play" msgid="7088090604803481121">"ప్లే చేయి"</string>
-    <string name="lb_playback_controls_pause" msgid="917331776961802657">"పాజ్ చేయి"</string>
+    <string name="lb_playback_controls_pause" msgid="917331776961802657">"పాజ్ చేయండి"</string>
     <string name="lb_playback_controls_fast_forward" msgid="740570111678243493">"వేగంగా ఫార్వర్డ్ చేయి"</string>
     <string name="lb_playback_controls_fast_forward_multiplier" msgid="5734614175721471329">"%1$dX ఫాస్ట్ ఫార్వర్డ్ చేయి"</string>
     <string name="lb_playback_controls_rewind" msgid="2866333981131020771">"రివైండ్ చేయి"</string>
diff --git a/libraryversions.toml b/libraryversions.toml
index 2b64a7c..91c7048 100644
--- a/libraryversions.toml
+++ b/libraryversions.toml
@@ -27,9 +27,9 @@
 COMPOSE_MATERIAL3_COMMON = "1.0.0-alpha01"
 COMPOSE_MATERIAL3_XR = "1.0.0-alpha02"
 COMPOSE_RUNTIME = "1.8.0-beta01"
-CONSTRAINTLAYOUT = "2.2.0-beta01"
-CONSTRAINTLAYOUT_COMPOSE = "1.1.0-beta01"
-CONSTRAINTLAYOUT_CORE = "1.1.0-beta01"
+CONSTRAINTLAYOUT = "2.3.0-alpha01"
+CONSTRAINTLAYOUT_COMPOSE = "1.2.0-alpha01"
+CONSTRAINTLAYOUT_CORE = "1.2.0-alpha01"
 CONTENTPAGER = "1.1.0-alpha01"
 COORDINATORLAYOUT = "1.3.0-alpha03"
 CORE = "1.16.0-alpha01"
@@ -108,6 +108,7 @@
 PALETTE = "1.1.0-alpha01"
 PDF = "1.0.0-alpha05"
 PERCENTLAYOUT = "1.1.0-alpha01"
+PERFORMANCE = "1.0.0-alpha01"
 PREFERENCE = "1.3.0-alpha01"
 PRINT = "1.1.0-beta01"
 PRIVACYSANDBOX_ACTIVITY = "1.0.0-alpha01"
@@ -270,6 +271,7 @@
 PALETTE = { group = "androidx.palette", atomicGroupVersion = "versions.PALETTE" }
 PDF = { group = "androidx.pdf", atomicGroupVersion = "versions.PDF" }
 PERCENTLAYOUT = { group = "androidx.percentlayout", atomicGroupVersion = "versions.PERCENTLAYOUT" }
+PERFORMANCE = { group = "androidx.performance", atomicGroupVersion = "versions.PERFORMANCE" }
 PREFERENCE = { group = "androidx.preference", atomicGroupVersion = "versions.PREFERENCE" }
 PRINT = { group = "androidx.print", atomicGroupVersion = "versions.PRINT" }
 PRIVACYSANDBOX_ACTIVITY = { group = "androidx.privacysandbox.activity", atomicGroupVersion = "versions.PRIVACYSANDBOX_ACTIVITY" }
diff --git a/license-baseline.txt b/license-baseline.txt
index cefd13f..79f5149 100644
--- a/license-baseline.txt
+++ b/license-baseline.txt
@@ -34,6 +34,7 @@
 com/sun/xml/bind/mvn/jaxb-runtime-parent/2.3.2/jaxb-runtime-parent-2.3.2.pom
 com/sun/xml/bind/mvn/jaxb-txw-parent/2.3.2/jaxb-txw-parent-2.3.2.pom
 commons-io/commons-io/2.13.0/commons-io-2.13.0.pom
+commons-io/commons-io/2.16.1/commons-io-2.16.1.pom
 commons-io/commons-io/2.6/commons-io-2.6.pom
 gradle/plugin/org/jetbrains/intellij/plugins/gradle-intellij-plugin/0.4.8/gradle-intellij-plugin-0.4.8.pom
 io/netty/netty-buffer/4.1.52.Final/netty-buffer-4.1.52.Final.pom
@@ -93,6 +94,7 @@
 org/apache/commons/commons-parent/48/commons-parent-48.pom
 org/apache/commons/commons-parent/52/commons-parent-52.pom
 org/apache/commons/commons-parent/58/commons-parent-58.pom
+org/apache/commons/commons-parent/69/commons-parent-69.pom
 org/apache/commons/commons-parent/74/commons-parent-74.pom
 org/apache/geronimo/genesis/genesis-default-flava/2.0/genesis-default-flava-2.0.pom
 org/apache/geronimo/genesis/genesis-java5-flava/2.0/genesis-java5-flava-2.0.pom
@@ -111,4 +113,4 @@
 org/apache/xbean/xbean-reflect/3.7/xbean-reflect-3.7.pom
 org/apache/xbean/xbean/3.7/xbean-3.7.pom
 org/jetbrains/kotlinx/benchmark/org.jetbrains.kotlinx.benchmark.gradle.plugin/0.4.11/org.jetbrains.kotlinx.benchmark.gradle.plugin-0.4.11.pom
-org/tensorflow/tensorflow-lite-metadata/0.1.0-rc2/tensorflow-lite-metadata-0.1.0-rc2.pom
\ No newline at end of file
+org/tensorflow/tensorflow-lite-metadata/0.1.0-rc2/tensorflow-lite-metadata-0.1.0-rc2.pom
diff --git a/lifecycle/lifecycle-runtime-compose/build.gradle b/lifecycle/lifecycle-runtime-compose/build.gradle
index 5484709..0184579 100644
--- a/lifecycle/lifecycle-runtime-compose/build.gradle
+++ b/lifecycle/lifecycle-runtime-compose/build.gradle
@@ -27,31 +27,12 @@
 
 plugins {
     id("AndroidXPlugin")
+    id("com.android.library")
     id("AndroidXComposePlugin")
 }
 
 androidXMultiplatform {
-    androidLibrary {
-        namespace = "androidx.lifecycle.runtime.compose"
-        withAndroidTestOnDeviceBuilder {
-            it.compilationName = "instrumentedTest"
-            it.defaultSourceSetName = "androidInstrumentedTest"
-            it.sourceSetTreeName = "test"
-        }
-        withAndroidTestOnJvmBuilder {
-            it.defaultSourceSetName = "androidUnitTest"
-        }
-
-        compileSdk = 35
-        aarMetadata.minCompileSdk = 35
-
-        optimization {
-            it.consumerKeepRules.publish = true
-            it.consumerKeepRules.files.add(
-                new File(project.projectDir, "proguard-rules.pro")
-            )
-        }
-    }
+    android()
     jvmStubs()
     linuxX64Stubs()
 
@@ -111,3 +92,12 @@
     samples(project(":lifecycle:lifecycle-runtime-compose:lifecycle-runtime-compose-samples"))
 }
 
+android {
+    compileSdk 35
+
+    buildTypes.configureEach {
+        consumerProguardFiles "proguard-rules.pro"
+    }
+
+    namespace "androidx.lifecycle.runtime.compose"
+}
diff --git a/mediarouter/mediarouter/src/main/res/values-te/strings.xml b/mediarouter/mediarouter/src/main/res/values-te/strings.xml
index cc2df86..47395fa 100644
--- a/mediarouter/mediarouter/src/main/res/values-te/strings.xml
+++ b/mediarouter/mediarouter/src/main/res/values-te/strings.xml
@@ -29,7 +29,7 @@
     <string name="mr_controller_stop_casting" msgid="804210341192624074">"ప్రసారాన్ని ఆపివేయి"</string>
     <string name="mr_controller_close_description" msgid="5684434439232634509">"మూసివేయండి"</string>
     <string name="mr_controller_play" msgid="1253345086594430054">"ప్లే చేయి"</string>
-    <string name="mr_controller_pause" msgid="747801650871398383">"పాజ్ చేయి"</string>
+    <string name="mr_controller_pause" msgid="747801650871398383">"పాజ్ చేయండి"</string>
     <string name="mr_controller_stop" msgid="5497722768305745508">"ఆపు"</string>
     <string name="mr_controller_expand_group" msgid="4521419834052044261">"విస్తరించు"</string>
     <string name="mr_controller_collapse_group" msgid="2585048604188129749">"కుదించు"</string>
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
index 1174a14..d592f33 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
@@ -571,7 +571,7 @@
         inclusive: Boolean,
         saveState: Boolean = false
     ): Boolean {
-        val id = route.serializer().generateHashCode().also { println("pop hashcode:$it") }
+        val id = route.serializer().generateHashCode()
         requireNotNull(graph.findDestinationComprehensive(id, true)) {
             "Destination with route ${route.simpleName} cannot be found in navigation " +
                 "graph $graph"
diff --git a/pdf/integration-tests/testapp/src/androidTest/kotlin/androidx/pdf/ToolBoxViewTest.kt b/pdf/integration-tests/testapp/src/androidTest/kotlin/androidx/pdf/ToolBoxViewTest.kt
index e6575d5..0d73f69 100644
--- a/pdf/integration-tests/testapp/src/androidTest/kotlin/androidx/pdf/ToolBoxViewTest.kt
+++ b/pdf/integration-tests/testapp/src/androidTest/kotlin/androidx/pdf/ToolBoxViewTest.kt
@@ -25,6 +25,8 @@
 import androidx.fragment.app.testing.launchFragmentInContainer
 import androidx.lifecycle.Lifecycle
 import androidx.pdf.util.AnnotationUtils
+import androidx.pdf.view.ToolBoxView
+import androidx.pdf.view.ToolBoxView.Companion.EXTRA_STARTING_PAGE
 import androidx.pdf.viewer.fragment.PdfViewerFragmentV2
 import androidx.test.espresso.Espresso.onView
 import androidx.test.espresso.UiController
@@ -34,6 +36,7 @@
 import androidx.test.espresso.intent.Intents
 import androidx.test.espresso.intent.Intents.intended
 import androidx.test.espresso.intent.matcher.IntentMatchers.hasAction
+import androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra
 import androidx.test.espresso.intent.matcher.IntentMatchers.hasFlags
 import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
 import androidx.test.espresso.matcher.ViewMatchers.isRoot
@@ -118,6 +121,41 @@
         intended(expectedIntent)
     }
 
+    @Test
+    fun testEditButtonOnClickListener_onSpecificPage() {
+        scenarioLoadDocument(
+            TEST_DOCUMENT_FILE,
+            Lifecycle.State.STARTED,
+            ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
+        )
+
+        // TODO(b/387444890): Remove this once IdlingResources is used
+        onView(isRoot()).perform(waitFor(2000))
+
+        val pageNum = 3
+        scenario.onFragment { fragment ->
+            fragment.view?.let {
+                var toolBoxView: ToolBoxView? =
+                    it.findViewById(androidx.pdf.viewer.fragment.R.id.toolBoxView) as ToolBoxView
+                toolBoxView?.setOnCurrentPageRequested { pageNum }
+            }
+        }
+
+        // Ensure the toolbox view is displayed
+        onView(withId(androidx.pdf.viewer.fragment.R.id.toolBoxView)).check(matches(isDisplayed()))
+
+        onView(withId(androidx.pdf.viewer.fragment.R.id.toolBoxView)).perform(click())
+
+        // Verify that the action was performed (e.g., intent was launched)
+        val expectedIntent =
+            allOf(
+                hasAction(AnnotationUtils.ACTION_ANNOTATE_PDF),
+                hasFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION),
+                hasExtra(EXTRA_STARTING_PAGE, pageNum)
+            )
+        intended(expectedIntent)
+    }
+
     fun waitFor(delay: Long): ViewAction {
         return object : ViewAction {
             override fun getConstraints(): Matcher<View> = isRoot()
diff --git a/pdf/pdf-viewer-fragment/build.gradle b/pdf/pdf-viewer-fragment/build.gradle
index cb1755b..d5e576b 100644
--- a/pdf/pdf-viewer-fragment/build.gradle
+++ b/pdf/pdf-viewer-fragment/build.gradle
@@ -44,6 +44,11 @@
     androidTestImplementation(libs.junit)
     androidTestImplementation(libs.testExtJunit)
     androidTestImplementation(libs.kotlinCoroutinesTest)
+
+    testImplementation(libs.junit)
+    testImplementation(libs.testRunner)
+    testImplementation(libs.robolectric)
+    testImplementation(libs.truth)
 }
 
 android {
diff --git a/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/PdfDocumentViewModel.kt b/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/PdfDocumentViewModel.kt
index 5eecee0..f8ff8bf 100644
--- a/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/PdfDocumentViewModel.kt
+++ b/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/PdfDocumentViewModel.kt
@@ -38,6 +38,7 @@
 import androidx.pdf.viewer.fragment.model.PdfFragmentUiState
 import androidx.pdf.viewer.fragment.model.SearchViewUiState
 import androidx.pdf.viewer.fragment.util.fetchCounterData
+import androidx.pdf.viewer.fragment.util.getCenter
 import androidx.pdf.viewer.fragment.util.toHighlightsData
 import java.util.concurrent.Executors
 import kotlinx.coroutines.Job
@@ -360,7 +361,7 @@
         viewModelScope.launch(searchJob) {
             searchRepository.produceSearchResults(
                 query = query,
-                currentVisiblePage = visiblePageRange.getCenterPage()
+                currentVisiblePage = visiblePageRange.getCenter()
             )
         }
     }
diff --git a/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/PdfViewerFragmentV2.kt b/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/PdfViewerFragmentV2.kt
index 86ff8d3..ec8233d 100644
--- a/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/PdfViewerFragmentV2.kt
+++ b/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/PdfViewerFragmentV2.kt
@@ -50,6 +50,7 @@
 import androidx.pdf.viewer.fragment.model.PdfFragmentUiState.Loading
 import androidx.pdf.viewer.fragment.model.PdfFragmentUiState.PasswordRequested
 import androidx.pdf.viewer.fragment.search.PdfSearchViewManager
+import androidx.pdf.viewer.fragment.util.getCenter
 import androidx.pdf.viewer.fragment.view.PdfViewManager
 import com.google.android.material.color.MaterialColors
 import kotlinx.coroutines.Job
@@ -220,6 +221,8 @@
         onPdfSearchViewCreated(pdfSearchView)
 
         collectFlowOnLifecycleScope { collectFragmentUiScreenState() }
+
+        toolboxView.setOnCurrentPageRequested { pdfView.visiblePages.getCenter() }
     }
 
     /**
diff --git a/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/util/IntRangeExtensions.kt b/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/util/IntRangeExtensions.kt
new file mode 100644
index 0000000..49643d1
--- /dev/null
+++ b/pdf/pdf-viewer-fragment/src/main/kotlin/androidx/pdf/viewer/fragment/util/IntRangeExtensions.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2025 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.fragment.util
+
+internal fun IntRange.getCenter(): Int {
+    return start + (endInclusive - start) / 2
+}
diff --git a/pdf/pdf-viewer-fragment/src/main/res/layout/pdf_viewer_fragment.xml b/pdf/pdf-viewer-fragment/src/main/res/layout/pdf_viewer_fragment.xml
index aeedc97..931ab6b 100644
--- a/pdf/pdf-viewer-fragment/src/main/res/layout/pdf_viewer_fragment.xml
+++ b/pdf/pdf-viewer-fragment/src/main/res/layout/pdf_viewer_fragment.xml
@@ -23,6 +23,8 @@
         android:id="@+id/pdfView"
         android:layout_width="match_parent"
         android:layout_height="0dp"
+        android:paddingStart="@dimen/pdf_horizontal_padding"
+        android:paddingEnd="@dimen/pdf_horizontal_padding"
         app:layout_constraintBottom_toTopOf="@+id/pdfSearchView"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
@@ -57,8 +59,6 @@
         android:id="@+id/toolBoxView"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginEnd="@dimen/viewer_edit_fab_margin_right"
-        android:layout_marginBottom="@dimen/viewer_edit_fab_margin_bottom"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent" />
 
diff --git a/pdf/pdf-viewer-fragment/src/test/kotlin/androidx/pdf/viewer/fragment/util/IntRangeExtensionsTest.kt b/pdf/pdf-viewer-fragment/src/test/kotlin/androidx/pdf/viewer/fragment/util/IntRangeExtensionsTest.kt
new file mode 100644
index 0000000..744aaf2
--- /dev/null
+++ b/pdf/pdf-viewer-fragment/src/test/kotlin/androidx/pdf/viewer/fragment/util/IntRangeExtensionsTest.kt
@@ -0,0 +1,51 @@
+/*
+ * 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.view
+
+import androidx.pdf.viewer.fragment.util.getCenter
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+@RunWith(RobolectricTestRunner::class)
+class IntRangeExtensionsTest {
+
+    @Test
+    fun getCenter_emptyRange() {
+        val range = 0..0
+        assertThat(range.getCenter()).isEqualTo(0)
+    }
+
+    @Test
+    fun getCenter_oneElementRange() {
+        val range = 0..1
+        assertThat(range.getCenter()).isEqualTo(0)
+    }
+
+    @Test
+    fun getCenter_oddRange() {
+        val range = 0..2
+        assertThat(range.getCenter()).isEqualTo(1)
+    }
+
+    @Test
+    fun getCenter_evenRange() {
+        val range = 0..3
+        assertThat(range.getCenter()).isEqualTo(1)
+    }
+}
diff --git a/pdf/pdf-viewer/src/androidTest/kotlin/androidx/pdf/view/PdfViewPaginationTest.kt b/pdf/pdf-viewer/src/androidTest/kotlin/androidx/pdf/view/PdfViewPaginationTest.kt
index ad814a5..0f2b372 100644
--- a/pdf/pdf-viewer/src/androidTest/kotlin/androidx/pdf/view/PdfViewPaginationTest.kt
+++ b/pdf/pdf-viewer/src/androidTest/kotlin/androidx/pdf/view/PdfViewPaginationTest.kt
@@ -42,8 +42,8 @@
 
     @Test
     fun testPageVisibility() = runTest {
-        // Layout at 500x1000, and expect to see pages [0, 4] at 100x200
-        val pdfDocument = FakePdfDocument(List(10) { Point(100, 200) })
+        // Layout at 500x1000, and expect to see pages [0, 4] at 500x200
+        val pdfDocument = FakePdfDocument(List(10) { Point(500, 200) })
         setupPdfView(500, 1000, pdfDocument)
 
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
@@ -67,8 +67,8 @@
 
     @Test
     fun testPageVisibility_onSizeDecreased() = runTest {
-        // Layout at 500x1000 initially, and expect to see pages [0, 3] at 100x300
-        val pdfDocument = FakePdfDocument(List(10) { Point(100, 300) })
+        // Layout at 500x1000 initially, and expect to see pages [0, 3] at 500x300
+        val pdfDocument = FakePdfDocument(List(10) { Point(500, 300) })
         setupPdfView(500, 1000, pdfDocument)
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
             pdfDocument.waitForLayout(untilPage = 3)
@@ -94,8 +94,8 @@
 
     @Test
     fun testPageVisibility_onScrollChanged() = runTest {
-        // Layout at 1000x2000 initially, and expect to see pages [0, 3] at 200x500
-        val pdfDocument = FakePdfDocument(List(10) { Point(200, 500) })
+        // Layout at 1000x2000 initially, and expect to see pages [0, 3] at 1000x500
+        val pdfDocument = FakePdfDocument(List(10) { Point(1000, 500) })
         setupPdfView(1000, 2000, pdfDocument)
 
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
@@ -115,8 +115,8 @@
 
     @Test
     fun testPageVisibility_onZoomChanged() = runTest {
-        // Layout at 100x500 initially, and expect to see pages [0, 5] at 30x80
-        val pdfDocument = FakePdfDocument(List(10) { Point(30, 80) })
+        // Layout at 100x500 initially, and expect to see pages [0, 5] at 100x80
+        val pdfDocument = FakePdfDocument(List(10) { Point(100, 80) })
         setupPdfView(100, 500, pdfDocument)
 
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
@@ -135,7 +135,7 @@
 
     @Test
     fun testScrollToPage() = runTest {
-        val pdfDocument = FakePdfDocument(List(10) { Point(100, 300) })
+        val pdfDocument = FakePdfDocument(List(10) { Point(500, 1000) })
         setupPdfView(500, 1000, pdfDocument)
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
 
@@ -152,7 +152,7 @@
 
     @Test
     fun testScrollToPosition() = runTest {
-        val pdfDocument = FakePdfDocument(List(10) { Point(100, 300) })
+        val pdfDocument = FakePdfDocument(List(10) { Point(500, 1000) })
         setupPdfView(500, 1000, pdfDocument)
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
 
diff --git a/pdf/pdf-viewer/src/androidTest/kotlin/androidx/pdf/view/PdfViewRenderingTest.kt b/pdf/pdf-viewer/src/androidTest/kotlin/androidx/pdf/view/PdfViewRenderingTest.kt
index 95ecb56..a0333b6 100644
--- a/pdf/pdf-viewer/src/androidTest/kotlin/androidx/pdf/view/PdfViewRenderingTest.kt
+++ b/pdf/pdf-viewer/src/androidTest/kotlin/androidx/pdf/view/PdfViewRenderingTest.kt
@@ -40,8 +40,8 @@
 
     @Test
     fun testPageRendering() = runTest {
-        // Layout at 500x1000, and expect to render pages [0, 4] at 100x200
-        val pdfDocument = FakePdfDocument(List(10) { Point(100, 200) })
+        // Layout at 500x1000, and expect to render pages [0, 4] at 500x200
+        val pdfDocument = FakePdfDocument(List(10) { Point(500, 200) })
         setupPdfView(500, 1000, pdfDocument)
 
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
@@ -51,7 +51,7 @@
             assertThat(requestedBitmaps.size).isEqualTo(5)
             for (i in 0..4) {
                 assertThat((requestedBitmaps[i] as? FullBitmap)?.scaledPageSizePx?.width)
-                    .isEqualTo(100)
+                    .isEqualTo(500)
                 assertThat((requestedBitmaps[i] as? FullBitmap)?.scaledPageSizePx?.height)
                     .isEqualTo(200)
             }
@@ -62,8 +62,8 @@
 
     @Test
     fun testPageRendering_renderNewPagesOnScroll() = runTest {
-        // Layout at 500x1000, and expect to render pages [0, 4] at 100x200
-        val pdfDocument = FakePdfDocument(List(10) { Point(100, 200) })
+        // Layout at 500x1000, and expect to render pages [0, 4] at 500x200
+        val pdfDocument = FakePdfDocument(List(10) { Point(500, 200) })
         setupPdfView(500, 1000, pdfDocument)
 
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
@@ -78,7 +78,7 @@
             assertThat(requestedBitmaps.size).isEqualTo(10)
             for (i in 0..9) {
                 assertThat((requestedBitmaps[i] as? FullBitmap)?.scaledPageSizePx?.width)
-                    .isEqualTo(100)
+                    .isEqualTo(500)
                 assertThat((requestedBitmaps[i] as? FullBitmap)?.scaledPageSizePx?.height)
                     .isEqualTo(200)
             }
@@ -89,8 +89,8 @@
 
     @Test
     fun testPageRendering_renderNewBitmapsOnZoom() = runTest {
-        // Layout at 500x1000, and expect to render pages [0, 4] at 100x200
-        val pdfDocument = FakePdfDocument(List(10) { Point(100, 200) })
+        // Layout at 500x1000, and expect to render pages [0, 4] at 500x200
+        val pdfDocument = FakePdfDocument(List(10) { Point(500, 200) })
         setupPdfView(500, 1000, pdfDocument)
 
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
@@ -107,7 +107,7 @@
             assertThat(requestedBitmaps.size).isEqualTo(3)
             for (i in 0..2) {
                 assertThat((requestedBitmaps[i] as? FullBitmap)?.scaledPageSizePx?.width)
-                    .isEqualTo(200)
+                    .isEqualTo(1000)
                 assertThat((requestedBitmaps[i] as? FullBitmap)?.scaledPageSizePx?.height)
                     .isEqualTo(400)
             }
diff --git a/pdf/pdf-viewer/src/androidTest/kotlin/androidx/pdf/view/PdfViewStateChangeTest.kt b/pdf/pdf-viewer/src/androidTest/kotlin/androidx/pdf/view/PdfViewStateChangeTest.kt
index d88e729..2f63ad0 100644
--- a/pdf/pdf-viewer/src/androidTest/kotlin/androidx/pdf/view/PdfViewStateChangeTest.kt
+++ b/pdf/pdf-viewer/src/androidTest/kotlin/androidx/pdf/view/PdfViewStateChangeTest.kt
@@ -42,13 +42,15 @@
 
     @Test
     fun restorePositionState() = runTest {
-        val pdfDocument = FakePdfDocument(List(10) { Point(100, 200) })
-        withContext(Dispatchers.Main) { setupPdfView(500, 1000, pdfDocument) }
+        val pdfDocument =
+            FakePdfDocument(List(10) { Point(VIEW_AND_PAGE_WIDTH, VIEW_AND_PAGE_HEIGHT) })
+        withContext(Dispatchers.Main) {
+            setupPdfView(VIEW_AND_PAGE_WIDTH, VIEW_AND_PAGE_HEIGHT, pdfDocument)
+        }
 
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
             // Scroll to page 3, and make sure it's visible
-            pdfDocument.waitForLayout(untilPage = 4)
-            Espresso.onView(withId(PDF_VIEW_ID)).scrollToPage(3)
+            scrollToPage(3, pdfDocument)
             Espresso.onView(withId(PDF_VIEW_ID))
                 .checkPagesAreVisible(firstVisiblePage = 3, visiblePages = 1)
 
@@ -65,19 +67,21 @@
 
     @Test
     fun restorePositionState_afterPdfDocument() = runTest {
-        val pdfDocument = FakePdfDocument(List(10) { Point(100, 200) })
+        val pdfDocument =
+            FakePdfDocument(List(10) { Point(VIEW_AND_PAGE_WIDTH, VIEW_AND_PAGE_HEIGHT) })
         // Don't supply PdfDocument to setupPdfView, as it will cause that document to be set each
         // time our Activity is created. In this case, we'd like to test recreating the Activity
         // without setting a PdfDocument.
-        withContext(Dispatchers.Main) { setupPdfView(500, 1000, fakePdfDocument = null) }
+        withContext(Dispatchers.Main) {
+            setupPdfView(VIEW_AND_PAGE_WIDTH, VIEW_AND_PAGE_HEIGHT, fakePdfDocument = null)
+        }
 
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
             // Set PdfDocument, scroll to page 3, and make sure it's visible
             onActivity { activity ->
                 activity.findViewById<PdfView>(PDF_VIEW_ID)?.also { it.pdfDocument = pdfDocument }
             }
-            Espresso.onView(withId(PDF_VIEW_ID)).scrollToPage(3)
-            pdfDocument.waitForLayout(untilPage = 4)
+            scrollToPage(3, pdfDocument)
             Espresso.onView(withId(PDF_VIEW_ID))
                 .checkPagesAreVisible(firstVisiblePage = 3, visiblePages = 1)
 
@@ -101,21 +105,22 @@
     fun dontRestorePositionState_withDifferentDocument() = runTest {
         val pdfDocument =
             FakePdfDocument(
-                pages = List(10) { Point(100, 200) },
+                pages = List(10) { Point(VIEW_AND_PAGE_WIDTH, VIEW_AND_PAGE_HEIGHT) },
                 uri = Uri.parse("content://my.app/my.pdf")
             )
         // Don't supply PdfDocument to setupPdfView, as it will cause that document to be set each
         // time our Activity is created. In this case, we'd like to test recreating the Activity
         // and setting a *different* PdfDocument
-        withContext(Dispatchers.Main) { setupPdfView(500, 1000, fakePdfDocument = null) }
+        withContext(Dispatchers.Main) {
+            setupPdfView(VIEW_AND_PAGE_WIDTH, VIEW_AND_PAGE_HEIGHT, fakePdfDocument = null)
+        }
 
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
             // Set PdfDocument, scroll to page 3, and make sure it's visible
             onActivity { activity ->
                 activity.findViewById<PdfView>(PDF_VIEW_ID)?.also { it.pdfDocument = pdfDocument }
             }
-            Espresso.onView(withId(PDF_VIEW_ID)).scrollToPage(3)
-            pdfDocument.waitForLayout(untilPage = 4)
+            scrollToPage(3, pdfDocument)
             Espresso.onView(withId(PDF_VIEW_ID))
                 .checkPagesAreVisible(firstVisiblePage = 3, visiblePages = 1)
 
@@ -129,7 +134,7 @@
             // previous document
             val differentDocument =
                 FakePdfDocument(
-                    pages = List(15) { Point(50, 150) },
+                    pages = List(15) { Point(VIEW_AND_PAGE_WIDTH, 150) },
                     uri = Uri.parse("content://another.app/pdf.pdf")
                 )
             onActivity { activity ->
@@ -144,19 +149,21 @@
 
     @Test
     fun recreate_withoutPdfDocument() = runTest {
-        withContext(Dispatchers.Main) { setupPdfView(500, 1000, fakePdfDocument = null) }
+        withContext(Dispatchers.Main) {
+            setupPdfView(VIEW_AND_PAGE_WIDTH, VIEW_AND_PAGE_HEIGHT, fakePdfDocument = null)
+        }
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
             // Recreate without ever setting a document on PdfView initially
             recreate()
 
             // Set PdfDocument on the new PdfView instance, and make sure we can interact with it
-            val pdfDocument = FakePdfDocument(List(10) { Point(100, 200) })
+            val pdfDocument =
+                FakePdfDocument(List(10) { Point(VIEW_AND_PAGE_WIDTH, VIEW_AND_PAGE_HEIGHT) })
             onActivity { activity ->
                 activity.findViewById<PdfView>(PDF_VIEW_ID)?.also { it.pdfDocument = pdfDocument }
             }
 
-            Espresso.onView(withId(PDF_VIEW_ID)).scrollToPage(3)
-            pdfDocument.waitForLayout(untilPage = 4)
+            scrollToPage(3, pdfDocument)
             Espresso.onView(withId(PDF_VIEW_ID))
                 .checkPagesAreVisible(firstVisiblePage = 3, visiblePages = 1)
             close()
@@ -167,22 +174,23 @@
     fun resetDocument() = runTest {
         val pdfDocument =
             FakePdfDocument(
-                pages = List(10) { Point(100, 200) },
+                pages = List(10) { Point(VIEW_AND_PAGE_WIDTH, VIEW_AND_PAGE_HEIGHT) },
                 uri = Uri.parse("content://my.app/my.pdf")
             )
-        withContext(Dispatchers.Main) { setupPdfView(500, 1000, pdfDocument) }
+        withContext(Dispatchers.Main) {
+            setupPdfView(VIEW_AND_PAGE_WIDTH, VIEW_AND_PAGE_HEIGHT, pdfDocument)
+        }
 
         with(ActivityScenario.launch(PdfViewTestActivity::class.java)) {
             // Scroll to page 3, and make sure it's visible
-            Espresso.onView(withId(PDF_VIEW_ID)).scrollToPage(3)
-            pdfDocument.waitForLayout(untilPage = 4)
+            scrollToPage(3, pdfDocument)
             Espresso.onView(withId(PDF_VIEW_ID))
                 .checkPagesAreVisible(firstVisiblePage = 3, visiblePages = 1)
 
             // Set a different PdfDocument
             val differentDocument =
                 FakePdfDocument(
-                    List(10) { Point(100, 500) },
+                    List(10) { Point(VIEW_AND_PAGE_WIDTH, VIEW_AND_PAGE_HEIGHT) },
                     uri = Uri.parse("content://browser/downloads/menu.pdf")
                 )
             onActivity { activity ->
@@ -194,8 +202,7 @@
             Espresso.onView(withId(PDF_VIEW_ID)).checkPagesAreVisible(firstVisiblePage = 0)
             // Then, make sure we can interact with the new document: scroll to page 3, and make
             // sure it's visible
-            Espresso.onView(withId(PDF_VIEW_ID)).scrollToPage(3)
-            pdfDocument.waitForLayout(untilPage = 3)
+            scrollToPage(3, pdfDocument)
             Espresso.onView(withId(PDF_VIEW_ID))
                 .checkPagesAreVisible(firstVisiblePage = 3, visiblePages = 1)
 
@@ -204,6 +211,12 @@
     }
 }
 
+private suspend fun scrollToPage(pageNum: Int, pdfDocument: FakePdfDocument) {
+    Espresso.onView(withId(PDF_VIEW_ID)).scrollToPage(pageNum)
+    // scrollToPage will not actually scroll until that page is laid out, so wait for that to happen
+    pdfDocument.waitForLayout(untilPage = pageNum + 1)
+}
+
 /** Create, measure, and layout a [PdfView] at the specified [width] and [height] */
 private fun setupPdfView(width: Int, height: Int, fakePdfDocument: FakePdfDocument?) {
     PdfViewTestActivity.onCreateCallback = { activity ->
@@ -221,3 +234,8 @@
 
 /** Arbitrary fixed ID for PdfView */
 private const val PDF_VIEW_ID = 123456789
+
+// We use pages that match the View size to make it simpler to reason about what ought to be visible
+// when we scrollToPage(N)
+private const val VIEW_AND_PAGE_WIDTH = 500
+private const val VIEW_AND_PAGE_HEIGHT = 1000
diff --git a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PageLayoutManager.kt b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PageLayoutManager.kt
index 1a468ec..a70993a 100644
--- a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PageLayoutManager.kt
+++ b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PageLayoutManager.kt
@@ -103,6 +103,13 @@
         return paginationModel.getPageLocation(pageNum, viewport)
     }
 
+    /** Returns the size of the page at [pageNum], or null if we don't know that page's size yet */
+    fun getPageSize(pageNum: Int): Point? {
+        val size = paginationModel.getPageSize(pageNum)
+        if (size == PaginationModel.UNKNOWN_SIZE) return null
+        return size
+    }
+
     /**
      * Returns the [PdfPoint] that exists at [contentCoordinates], or null if no page content is
      * laid out at [contentCoordinates].
@@ -129,6 +136,18 @@
     }
 
     /**
+     * Returns a View-relative [RectF] corresponding to a page-relative [PdfRect], or null if the
+     * page hasn't been laid out
+     */
+    fun getViewRect(pdfRect: PdfRect, viewport: Rect): RectF? {
+        if (pdfRect.pageNum > paginationModel.reach) return null
+        val pageBounds = paginationModel.getPageLocation(pdfRect.pageNum, viewport)
+        val out = RectF(pdfRect.pageRect)
+        out.offset(pageBounds.left.toFloat(), pageBounds.top.toFloat())
+        return out
+    }
+
+    /**
      * Emits a new [Range] to [visiblePages] based on the current [scrollY], [height], and [zoom] of
      * a [PdfView]
      */
diff --git a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PdfView.kt b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PdfView.kt
index d734d3c..cf73661 100644
--- a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PdfView.kt
+++ b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PdfView.kt
@@ -17,29 +17,37 @@
 package androidx.pdf.view
 
 import android.animation.ValueAnimator
+import android.content.ClipData
+import android.content.ClipboardManager
 import android.content.Context
 import android.content.Intent
 import android.graphics.Canvas
 import android.graphics.Point
 import android.graphics.PointF
 import android.graphics.Rect
+import android.graphics.RectF
 import android.net.Uri
 import android.os.Looper
 import android.os.Parcelable
 import android.util.AttributeSet
 import android.util.Range
+import android.view.ActionMode
 import android.view.KeyEvent
+import android.view.Menu
+import android.view.MenuItem
 import android.view.MotionEvent
 import android.view.ScaleGestureDetector
 import android.view.View
+import androidx.annotation.CallSuper
 import androidx.annotation.RestrictTo
 import androidx.annotation.VisibleForTesting
+import androidx.core.graphics.toRectF
 import androidx.core.os.HandlerCompat
 import androidx.core.view.ViewCompat
 import androidx.pdf.PdfDocument
+import androidx.pdf.R
 import androidx.pdf.util.Accessibility
 import androidx.pdf.util.MathUtils
-import androidx.pdf.util.Screen
 import androidx.pdf.util.ZoomUtils
 import java.util.LinkedList
 import java.util.Queue
@@ -141,6 +149,10 @@
     /** The listener that is notified when a link in the PDF is clicked. */
     public var linkClickListener: LinkClickListener? = null
 
+    /** The [ActionMode.Callback2] for selection */
+    public var selectionActionModeCallback: DefaultSelectionActionModeCallback =
+        DefaultSelectionActionModeCallback()
+
     /** The currently selected PDF content, as [Selection] */
     public val currentSelection: Selection?
         get() {
@@ -195,6 +207,8 @@
 
     private var selectionStateManager: SelectionStateManager? = null
     private val selectionRenderer = SelectionRenderer(context)
+    private var selectionActionMode: ActionMode? = null
+    private var gestureInProgress = false
 
     /**
      * Scrolls to the 0-indexed [pageNum], optionally animating the scroll
@@ -348,20 +362,30 @@
     }
 
     override fun onTouchEvent(event: MotionEvent?): Boolean {
-        val handled = event?.let { gestureTracker.feed(it) } ?: false
+        var handled = maybeDragSelectionHandle(event)
+        handled = handled || event?.let { gestureTracker.feed(it) } ?: false
         return handled || super.onTouchEvent(event)
     }
 
+    private fun maybeDragSelectionHandle(event: MotionEvent?): Boolean {
+        if (event == null) return false
+        val touchPoint =
+            pageLayoutManager?.getPdfPointAt(
+                PointF(toContentX(event.x), toContentY(event.y)),
+                getVisibleAreaInContentCoords()
+            )
+        return selectionStateManager?.maybeDragSelectionHandle(event.action, touchPoint, zoom) ==
+            true
+    }
+
     override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
         super.onSizeChanged(w, h, oldw, oldh)
-        pageLayoutManager?.onViewportChanged(scrollY, height, zoom)
-        accessibilityPageHelper?.invalidateRoot()
+        onViewportChanged()
     }
 
     override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
         super.onScrollChanged(l, t, oldl, oldt)
-        pageLayoutManager?.onViewportChanged(scrollY, height, zoom)
-        accessibilityPageHelper?.invalidateRoot()
+        onViewportChanged()
     }
 
     override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
@@ -409,6 +433,7 @@
         }
         state.documentUri = pdfDocument?.uri
         state.paginationModel = pageLayoutManager?.paginationModel
+        state.selectionModel = selectionStateManager?.selectionModel
         return state
     }
 
@@ -434,6 +459,8 @@
             // Once the fling has ended, prompt the page manager to start fetching data for pages
             // that we don't fetch during a fling
             pageManager?.maybeUpdatePageState(visiblePages, zoom, isFling)
+            // We hide the action mode during a fling, so reveal it when the fling is over
+            updateSelectionActionModeVisibility()
         }
     }
 
@@ -483,16 +510,7 @@
 
     private fun getDefaultZoom(): Float {
         if (contentWidth == 0 || viewportWidth == 0) return DEFAULT_INIT_ZOOM
-        val screenUtils = Screen(context)
-        val screenWidthPx = context.resources.displayMetrics.widthPixels
-        val screenWidthDp = screenUtils.dpFromPx(screenWidthPx)
-        val effectiveViewportWidth =
-            if (screenWidthDp >= 840) {
-                viewportWidth - screenUtils.pxFromDp(80)
-            } else {
-                viewportWidth
-            }
-        val widthZoom = effectiveViewportWidth.toFloat() / contentWidth
+        val widthZoom = viewportWidth.toFloat() / contentWidth
         return MathUtils.clamp(widthZoom, minZoom, maxZoom)
     }
 
@@ -517,9 +535,16 @@
                     localPdfDocument,
                     backgroundScope,
                     DEFAULT_PAGE_PREFETCH_RADIUS,
-                    paginationModel = localStateToRestore.paginationModel!!
+                    paginationModel = requireNotNull(localStateToRestore.paginationModel)
                 )
                 .apply { onViewportChanged(scrollY, height, zoom) }
+        selectionStateManager =
+            SelectionStateManager(
+                localPdfDocument,
+                backgroundScope,
+                resources.getDimensionPixelSize(R.dimen.text_select_handle_touch_size),
+                localStateToRestore.selectionModel
+            )
 
         val positionToRestore =
             PointF(localStateToRestore.contentCenterX, localStateToRestore.contentCenterY)
@@ -594,7 +619,7 @@
                 mainScope.launch(start = CoroutineStart.UNDISPATCHED) {
                     // Prevent 2 copies from running concurrently
                     selectionToJoin?.join()
-                    manager.invalidationSignalFlow.collect { invalidate() }
+                    manager.selectionUiSignalBus.collect { onSelectionUiSignal(it) }
                 }
         }
     }
@@ -606,6 +631,25 @@
         selectionStateCollector?.cancel()
     }
 
+    private fun onSelectionUiSignal(signal: SelectionUiSignal) {
+        when (signal) {
+            is SelectionUiSignal.PlayHapticFeedback -> {
+                performHapticFeedback(signal.level)
+            }
+            is SelectionUiSignal.Invalidate -> {
+                invalidate()
+            }
+            is SelectionUiSignal.ToggleActionMode -> {
+                if (signal.show && selectionActionMode == null && currentSelection != null) {
+                    startActionMode(selectionActionModeCallback, ActionMode.TYPE_FLOATING)
+                } else if (!signal.show) {
+                    selectionActionMode?.finish()
+                    selectionActionMode = null
+                }
+            }
+        }
+    }
+
     /** Start using the [PdfDocument] to present PDF content */
     // Display.width and height are deprecated in favor of WindowMetrics, but in this case we
     // actually want to use the size of the display and not the size of the window.
@@ -626,16 +670,18 @@
                 Point(maxBitmapDimensionPx, maxBitmapDimensionPx),
                 isTouchExplorationEnabled
             )
-        selectionStateManager =
-            SelectionStateManager(
-                localPdfDocument,
-                backgroundScope,
-            )
-        // We'll either create our layout manager from restored state, or instantiate a new one
+        // We'll either create our layout and selection managers from restored state, or
+        // instantiate new ones
         if (!maybeRestoreState()) {
             pageLayoutManager =
                 PageLayoutManager(localPdfDocument, backgroundScope, DEFAULT_PAGE_PREFETCH_RADIUS)
                     .apply { onViewportChanged(scrollY, height, zoom) }
+            selectionStateManager =
+                SelectionStateManager(
+                    localPdfDocument,
+                    backgroundScope,
+                    resources.getDimensionPixelSize(R.dimen.text_select_handle_touch_size)
+                )
             setAccessibility()
         }
         // If not, we'll start doing this when we _are_ attached to a visible window
@@ -652,13 +698,72 @@
      * position or size changes.
      */
     private fun onZoomChanged() {
-        pageLayoutManager?.onViewportChanged(scrollY, height, zoom)
+        onViewportChanged()
         // Don't fetch new Bitmaps while the user is actively zooming, to avoid jank and rendering
         // churn
         if (!gestureTracker.matches(GestureTracker.Gesture.ZOOM)) {
             pageManager?.maybeUpdatePageState(visiblePages, zoom, isFling)
         }
+    }
+
+    private fun onViewportChanged() {
+        pageLayoutManager?.onViewportChanged(scrollY, height, zoom)
         accessibilityPageHelper?.invalidateRoot()
+        updateSelectionActionModeVisibility()
+    }
+
+    /**
+     * Shows or hides the selection action mode, as appropriate. If the current selection is visible
+     * and a gesture is not in progress, the action mode will be shown. Otherwise, it will be
+     * hidden.
+     */
+    private fun updateSelectionActionModeVisibility() {
+        // isFlinging != gestureInProgress. isFlinging refers to the animation that continues after
+        // the gesture stops
+        if (selectionIsVisible() && !gestureInProgress && !isFling) {
+            selectionStateManager?.maybeShowActionMode()
+            selectionActionMode?.invalidateContentRect()
+        } else {
+            selectionStateManager?.maybeHideActionMode()
+        }
+    }
+
+    private fun selectionIsVisible(): Boolean {
+        // If we don't have a selection or any way to understand the layout of our pages, the
+        // selection is not visible
+        val localSelection = currentSelection ?: return false
+        val localPageLayoutManager = pageLayoutManager ?: return false
+
+        val viewport = getVisibleAreaInContentCoords()
+        val firstPage = localSelection.bounds.minOf { it.pageNum }
+        val lastPage = localSelection.bounds.maxOf { it.pageNum }
+        // Top and bottom edge must be on the first and last page, respectively
+        // If we can't locate any edge of the selection, we consider it invisible
+        val topEdge =
+            localSelection.bounds
+                .filter { it.pageNum == firstPage }
+                .minByOrNull { it.pageRect.top }
+                ?.let { localPageLayoutManager.getViewRect(it, viewport) }
+                ?.top ?: return false
+        val bottomEdge =
+            localSelection.bounds
+                .filter { it.pageNum == lastPage }
+                .maxByOrNull { it.pageRect.bottom }
+                ?.let { localPageLayoutManager.getViewRect(it, viewport) }
+                ?.bottom ?: return false
+        // The left or right edge may be on any page
+        val leftEdge =
+            localSelection.bounds
+                .minByOrNull { it.pageRect.left }
+                ?.let { localPageLayoutManager.getViewRect(it, viewport) }
+                ?.left ?: return false
+        val rightEdge =
+            localSelection.bounds
+                .maxByOrNull { it.pageRect.right }
+                ?.let { localPageLayoutManager.getViewRect(it, viewport) }
+                ?.right ?: return false
+
+        return RectF(viewport).intersects(leftEdge, topEdge, rightEdge, bottomEdge)
     }
 
     /**
@@ -673,7 +778,7 @@
         // Stop any in progress fling when we open a new document
         scroller.forceFinished(true)
         scrollTo(0, 0)
-        zoom = getDefaultZoom()
+        zoom = DEFAULT_INIT_ZOOM
         pageManager = null
         pageLayoutManager = null
         backgroundScope.coroutineContext.cancelChildren()
@@ -748,10 +853,10 @@
      */
     internal fun getVisibleAreaInContentCoords(): Rect {
         visibleAreaRect.set(
-            toContentX(-paddingLeft.toFloat()).toInt(),
-            toContentY(-paddingTop.toFloat()).toInt(),
-            toContentX(viewportWidth.toFloat() + paddingRight).toInt(),
-            toContentY(viewportHeight.toFloat() + paddingBottom).toInt(),
+            toContentX(0F).toInt(),
+            toContentY(0F).toInt(),
+            toContentX(viewportWidth.toFloat() + paddingRight + paddingLeft).toInt(),
+            toContentY(viewportHeight.toFloat() + paddingBottom + paddingTop).toInt(),
         )
         return visibleAreaRect
     }
@@ -807,6 +912,103 @@
     private val contentHeight: Int
         get() = pageLayoutManager?.paginationModel?.totalEstimatedHeight ?: 0
 
+    /** The default [ActionMode.Callback2] for selection */
+    public open inner class DefaultSelectionActionModeCallback : ActionMode.Callback2() {
+        @CallSuper
+        override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
+            selectionActionMode = mode
+
+            // Inflate the menu resource providing context menu items.
+            val inflater = mode.menuInflater
+            inflater.inflate(R.menu.context_menu, menu)
+            return true
+        }
+
+        override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
+            return false
+        }
+
+        @CallSuper
+        override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
+            if (item.itemId == R.id.action_selectAll) {
+                // We can't select all if we don't know what page the selection is on, or if
+                // we don't know the size of that page
+                val page = currentSelection?.bounds?.first()?.pageNum ?: return false
+                val pageSize = pageLayoutManager?.getPageSize(page) ?: return false
+                selectionStateManager?.selectAllTextOnPageAsync(page, pageSize)
+                return true
+            } else if (item.itemId == R.id.action_copy) {
+                // We can't copy the current selection if no text is selected
+                val text = (currentSelection as? TextSelection)?.text ?: return false
+                copyToClipboard(text)
+                return true
+            }
+            return false
+        }
+
+        private fun copyToClipboard(text: String) {
+            val manager = context.getSystemService(ClipboardManager::class.java)
+            val clip = ClipData.newPlainText(context.getString(R.string.clipboard_label), text)
+            manager.setPrimaryClip(clip)
+        }
+
+        override fun onDestroyActionMode(mode: ActionMode) {
+            // No-op
+        }
+
+        override fun onGetContentRect(mode: ActionMode, view: View, outRect: Rect) {
+            // If we don't know about page layout, defer to the default implementation
+            val localPageLayoutManager =
+                pageLayoutManager ?: return super.onGetContentRect(mode, view, outRect)
+            val viewport = getVisibleAreaInContentCoords()
+            val viewportF = viewport.toRectF()
+            val firstSelection = currentSelection?.bounds?.first()
+            val lastSelection = currentSelection?.bounds?.last()
+
+            // Try to position the context menu near the first selection if it's visible
+            if (firstSelection != null) {
+                // Copy bounds to avoid mutating the real data
+                val boundsInView = localPageLayoutManager.getViewRect(firstSelection, viewport)
+                if (
+                    boundsInView?.let {
+                        viewportF.intersects(it.left, it.top, it.right, it.bottom)
+                    } == true
+                ) {
+                    outRect.set(boundsInView.toViewRect())
+                    return
+                }
+            }
+
+            // Else, try to position the context menu near the last selection if it's visible
+            if (lastSelection != null) {
+                // Copy bounds to avoid mutating the real data
+                val boundsInView = localPageLayoutManager.getViewRect(lastSelection, viewport)
+                if (
+                    boundsInView?.let {
+                        viewportF.intersects(it.left, it.top, it.right, it.bottom)
+                    } == true
+                ) {
+                    outRect.set(boundsInView.toViewRect())
+                    return
+                }
+            }
+
+            // Else, center the context menu in view
+            val centerX = (x + width / 2).roundToInt()
+            val centerY = (x + height / 2).roundToInt()
+            outRect.set(centerX, centerY, centerX + 1, centerY + 1)
+        }
+    }
+
+    private fun RectF.toViewRect(): Rect {
+        return Rect(
+            toViewCoord(left, zoom, scrollX).roundToInt(),
+            toViewCoord(top, zoom, scrollY).roundToInt(),
+            toViewCoord(right, zoom, scrollX).roundToInt(),
+            toViewCoord(bottom, zoom, scrollY).roundToInt(),
+        )
+    }
+
     /** Adjusts the position of [PdfView] in response to gestures detected by [GestureTracker] */
     private inner class ZoomScrollGestureHandler : GestureTracker.GestureHandler() {
 
@@ -850,6 +1052,21 @@
         override fun onGestureStart() {
             // Stop any in-progress fling when a new gesture begins
             scroller.forceFinished(true)
+            selectionStateManager?.maybeHideActionMode()
+            gestureInProgress = true
+            // We should hide the action mode during a gesture
+            updateSelectionActionModeVisibility()
+        }
+
+        override fun onGestureEnd(gesture: GestureTracker.Gesture?) {
+            if (gesture == GestureTracker.Gesture.ZOOM) onStableZoom()
+            totalX = 0f
+            totalY = 0f
+            straightenCurrentVerticalScroll = true
+            scrollQueue.clear()
+            gestureInProgress = false
+            // We should reveal the action mode after a gesture
+            updateSelectionActionModeVisibility()
         }
 
         override fun onScroll(
@@ -936,7 +1153,6 @@
         }
 
         override fun onDoubleTap(e: MotionEvent): Boolean {
-
             val currentZoom = zoom
 
             val newZoom =
@@ -977,14 +1193,6 @@
             return true
         }
 
-        override fun onGestureEnd(gesture: GestureTracker.Gesture?) {
-            if (gesture == GestureTracker.Gesture.ZOOM) onStableZoom()
-            totalX = 0f
-            totalY = 0f
-            straightenCurrentVerticalScroll = true
-            scrollQueue.clear()
-        }
-
         override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
             selectionStateManager?.clearSelection()
             val pageLayoutManager = pageLayoutManager ?: return super.onSingleTapConfirmed(e)
diff --git a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PdfViewSavedState.kt b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PdfViewSavedState.kt
index 8a8ea83..c0c5047 100644
--- a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PdfViewSavedState.kt
+++ b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/PdfViewSavedState.kt
@@ -17,10 +17,10 @@
 package androidx.pdf.view
 
 import android.net.Uri
-import android.os.Build
 import android.os.Parcel
 import android.os.Parcelable
 import android.os.Parcelable.ClassLoaderCreator
+import androidx.core.os.ParcelCompat
 import androidx.customview.view.AbsSavedState
 
 /** [AbsSavedState] implementation for [PdfView] */
@@ -35,6 +35,7 @@
      * preserve the zoom level when the device is rotated.
      */
     var viewWidth: Int = 0
+    var selectionModel: SelectionModel? = null
 
     /**
      * If we don't know what document this state belongs to, we cannot restore it. If we do not have
@@ -57,18 +58,9 @@
         contentCenterX = parcel.readFloat()
         contentCenterY = parcel.readFloat()
         zoom = parcel.readFloat()
-        documentUri =
-            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) {
-                parcel.readParcelable(loader, Uri::class.java)
-            } else {
-                parcel.readParcelable(loader)
-            }
-        paginationModel =
-            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) {
-                parcel.readParcelable(loader, PaginationModel::class.java)
-            } else {
-                parcel.readParcelable(loader)
-            }
+        documentUri = ParcelCompat.readParcelable(parcel, loader, Uri::class.java)
+        paginationModel = ParcelCompat.readParcelable(parcel, loader, PaginationModel::class.java)
+        selectionModel = ParcelCompat.readParcelable(parcel, loader, SelectionModel::class.java)
     }
 
     override fun writeToParcel(dest: Parcel, flags: Int) {
@@ -78,6 +70,7 @@
         dest.writeFloat(zoom)
         dest.writeParcelable(documentUri, flags)
         dest.writeParcelable(paginationModel, flags)
+        dest.writeParcelable(selectionModel, flags)
     }
 
     companion object {
diff --git a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/SelectionModel.kt b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/SelectionModel.kt
index a52a63e..0ca14c12 100644
--- a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/SelectionModel.kt
+++ b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/SelectionModel.kt
@@ -16,21 +16,55 @@
 
 package androidx.pdf.view
 
+import android.annotation.SuppressLint
 import android.graphics.PointF
+import android.os.Parcel
+import android.os.Parcelable
 import androidx.annotation.VisibleForTesting
+import androidx.core.os.ParcelCompat
 import androidx.pdf.PdfDocument
 import androidx.pdf.content.PageSelection
 
 /** Value class containing all data necessary to display UI related to content selection */
+@SuppressLint("BanParcelableUsage")
 internal class SelectionModel
 @VisibleForTesting
 internal constructor(
     val selection: Selection,
     val startBoundary: UiSelectionBoundary,
     val endBoundary: UiSelectionBoundary
-) {
+) : Parcelable {
+    constructor(
+        parcel: Parcel
+    ) : this(
+        textSelectionFromParcel(parcel, TextSelection::class.java.classLoader),
+        requireNotNull(
+            ParcelCompat.readParcelable(
+                parcel,
+                UiSelectionBoundary::class.java.classLoader,
+                UiSelectionBoundary::class.java
+            )
+        ),
+        requireNotNull(
+            ParcelCompat.readParcelable(
+                parcel,
+                UiSelectionBoundary::class.java.classLoader,
+                UiSelectionBoundary::class.java
+            )
+        ),
+    )
+
+    override fun describeContents(): Int = 0
+
+    override fun writeToParcel(dest: Parcel, flags: Int) {
+        (selection as TextSelection).writeToParcel(dest, flags)
+        startBoundary.writeToParcel(dest, flags)
+        endBoundary.writeToParcel(dest, flags)
+    }
+
     companion object {
         /** Produces a [SelectionModel] from a single [PageSelection] on a single page */
+        // TODO(b/386398335) Add support for creating a SelectionModel from selections on 2 pages
         fun fromSinglePageSelection(pageSelection: PageSelection): SelectionModel {
             val startPoint =
                 requireNotNull(pageSelection.start.point) { "PageSelection is missing start point" }
@@ -65,6 +99,18 @@
             val concatenatedText = this.selectedTextContents.joinToString(" ") { it.text }
             return TextSelection(concatenatedText, flattenedBounds)
         }
+
+        @JvmField
+        val CREATOR =
+            object : Parcelable.Creator<SelectionModel> {
+                override fun createFromParcel(parcel: Parcel): SelectionModel {
+                    return SelectionModel(parcel)
+                }
+
+                override fun newArray(size: Int): Array<SelectionModel?> {
+                    return arrayOfNulls(size)
+                }
+            }
     }
 }
 
@@ -73,4 +119,29 @@
  * it exists (as [PdfPoint]), as well as the direction of the selection ([isRtl] is true if the
  * selection was made in a right-to-left direction).
  */
-internal class UiSelectionBoundary(val location: PdfPoint, val isRtl: Boolean)
+@SuppressLint("BanParcelableUsage")
+internal class UiSelectionBoundary(val location: PdfPoint, val isRtl: Boolean) : Parcelable {
+    constructor(
+        parcel: Parcel
+    ) : this(
+        pdfPointFromParcel(parcel, PdfPoint::class.java.classLoader),
+        parcel.readBoolean(),
+    )
+
+    override fun describeContents(): Int = 0
+
+    override fun writeToParcel(dest: Parcel, flags: Int) {
+        location.writeToParcel(dest, flags)
+        dest.writeBoolean(isRtl)
+    }
+
+    companion object CREATOR : Parcelable.Creator<UiSelectionBoundary> {
+        override fun createFromParcel(parcel: Parcel): UiSelectionBoundary {
+            return UiSelectionBoundary(parcel)
+        }
+
+        override fun newArray(size: Int): Array<UiSelectionBoundary?> {
+            return arrayOfNulls(size)
+        }
+    }
+}
diff --git a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/SelectionRenderer.kt b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/SelectionRenderer.kt
index fd8cb32..8d25a2c 100644
--- a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/SelectionRenderer.kt
+++ b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/SelectionRenderer.kt
@@ -67,6 +67,11 @@
         locationInView: Rect,
         currentZoom: Float
     ) {
+        // Draw the bounds first so the handles appear on top of them
+        model.selection.bounds
+            .filter { it.pageNum == pageNum }
+            .forEach { drawBoundsOnPage(canvas, it, locationInView) }
+
         model.startBoundary.let {
             val startLoc = it.location
             if (startLoc.pageNum == pageNum) {
@@ -75,6 +80,7 @@
                         locationInView.left + startLoc.pagePoint.x,
                         locationInView.top + startLoc.pagePoint.y
                     )
+
                 drawHandleAtPosition(canvas, pointInView, isRight = false xor it.isRtl, currentZoom)
             }
         }
@@ -90,10 +96,6 @@
                 drawHandleAtPosition(canvas, pointInView, isRight = true xor it.isRtl, currentZoom)
             }
         }
-
-        model.selection.bounds
-            .filter { it.pageNum == pageNum }
-            .forEach { drawBoundsOnPage(canvas, it, locationInView) }
     }
 
     private fun drawHandleAtPosition(
diff --git a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/SelectionStateManager.kt b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/SelectionStateManager.kt
index c4410d7..72ec107 100644
--- a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/SelectionStateManager.kt
+++ b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/SelectionStateManager.kt
@@ -16,6 +16,12 @@
 
 package androidx.pdf.view
 
+import android.graphics.Point
+import android.graphics.PointF
+import android.graphics.RectF
+import android.view.HapticFeedbackConstants
+import android.view.MotionEvent
+import androidx.annotation.VisibleForTesting
 import androidx.pdf.PdfDocument
 import androidx.pdf.content.PageSelection
 import kotlinx.coroutines.CoroutineScope
@@ -29,37 +35,198 @@
 internal class SelectionStateManager(
     private val pdfDocument: PdfDocument,
     private val backgroundScope: CoroutineScope,
+    private val handleTouchTargetSizePx: Int,
+    initialSelection: SelectionModel? = null,
 ) {
     /** The current [Selection] */
-    var selectionModel: SelectionModel? = null
-        private set
+    var selectionModel: SelectionModel? = initialSelection
+        @VisibleForTesting internal set
+
+    /** Replay at few values in case of an UI signal issued while [PdfView] is not collecting */
+    private val _selectionUiSignalBus = MutableSharedFlow<SelectionUiSignal>(replay = 3)
 
     /**
-     * Replay at least 1 value in case of an invalidation signal issued while [PdfView] is not
-     * collecting
+     * This [SharedFlow] serves as an event bus of sorts to signal our host [PdfView] to update its
+     * UI in a decoupled way
      */
-    private val _invalidationSignalFlow = MutableSharedFlow<Unit>(replay = 1)
-
-    /**
-     * This [SharedFlow] serves as an event bus of sorts to signal our host [PdfView] to invalidate
-     * itself in a decoupled way.
-     */
-    val invalidationSignalFlow: SharedFlow<Unit>
-        get() = _invalidationSignalFlow
+    val selectionUiSignalBus: SharedFlow<SelectionUiSignal>
+        get() = _selectionUiSignalBus
 
     private var setSelectionJob: Job? = null
 
+    private var draggingState: DraggingState? = null
+
+    /**
+     * Potentially updates the location of a drag handle given the [action] and [location] of a
+     * [MotionEvent] within the [PdfView]. If a drag handle is moved, the current selection is
+     * updated asynchronously.
+     *
+     * @param currentZoom is used only to scale the size of the drag handle's touch target based on
+     *   the zoom factor
+     */
+    fun maybeDragSelectionHandle(action: Int, location: PdfPoint?, currentZoom: Float): Boolean {
+        return when (action) {
+            MotionEvent.ACTION_DOWN -> {
+                location ?: return false // We can't handle an ACTION_DOWN without a location
+                maybeHandleActionDown(location, currentZoom)
+            }
+            MotionEvent.ACTION_MOVE -> {
+                maybeHandleActionMove(location)
+            }
+            MotionEvent.ACTION_UP,
+            MotionEvent.ACTION_CANCEL -> maybeHandleGestureEnd()
+            else -> false
+        }
+    }
+
     /** Asynchronously attempts to select the nearest block of text to [pdfPoint] */
     fun maybeSelectWordAtPoint(pdfPoint: PdfPoint) {
+        _selectionUiSignalBus.tryEmit(SelectionUiSignal.ToggleActionMode(show = false))
+        _selectionUiSignalBus.tryEmit(
+            SelectionUiSignal.PlayHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
+        )
         updateSelectionAsync(pdfPoint, pdfPoint)
     }
 
+    /** Synchronously resets all state of this manager */
+    fun clearSelection() {
+        draggingState = null
+        setSelectionJob?.cancel()
+        setSelectionJob = null
+        _selectionUiSignalBus.tryEmit(SelectionUiSignal.ToggleActionMode(show = false))
+        _selectionUiSignalBus.tryEmit(SelectionUiSignal.Invalidate)
+        selectionModel = null
+    }
+
+    fun maybeShowActionMode() {
+        if (selectionModel != null) {
+            _selectionUiSignalBus.tryEmit(SelectionUiSignal.ToggleActionMode(show = true))
+        }
+    }
+
+    fun maybeHideActionMode() {
+        _selectionUiSignalBus.tryEmit(SelectionUiSignal.ToggleActionMode(show = false))
+    }
+
+    /**
+     * Updates the selection to include all text on the 0-indexed [pageNum]. [pageSize] is used to
+     * tell [PdfDocument] to select the whole page.
+     */
+    // TODO(b/386398335) Update this to accept a range of pages for select all, once we support
+    // multi-page selections
+    // TODO(b/386417152) Update this to use index-based selection once that's supported by
+    // PdfDocument
+    fun selectAllTextOnPageAsync(pageNum: Int, pageSize: Point) {
+        updateSelectionAsync(
+            PdfPoint(pageNum, PointF(0F, 0F)),
+            PdfPoint(pageNum, PointF(pageSize.x.toFloat(), pageSize.y.toFloat()))
+        )
+    }
+
+    private fun maybeHandleActionDown(location: PdfPoint, currentZoom: Float): Boolean {
+        val currentSelection = selectionModel ?: return false
+        val start = currentSelection.startBoundary.location
+        val end = currentSelection.endBoundary.location
+        val touchTargetContentSize = handleTouchTargetSizePx / currentZoom
+
+        if (location.pageNum == start.pageNum) {
+            val startPoint = start.pagePoint
+            // Touch target is below and behind the start position, like the start handle
+            val startTarget =
+                RectF(
+                    startPoint.x - touchTargetContentSize,
+                    startPoint.y,
+                    startPoint.x,
+                    startPoint.y + touchTargetContentSize
+                )
+            if (startTarget.contains(location.pagePoint.x, location.pagePoint.y)) {
+                draggingState =
+                    DraggingState(
+                        currentSelection.endBoundary,
+                        currentSelection.startBoundary,
+                        location.pagePoint
+                    )
+                // Play haptic feedback when the user starts dragging the handles
+                _selectionUiSignalBus.tryEmit(
+                    SelectionUiSignal.PlayHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE)
+                )
+                return true
+            }
+        }
+        if (location.pageNum == end.pageNum) {
+            val endPoint = end.pagePoint
+            // Touch target is below and ahead of the end position, like the end handle
+            val endTarget =
+                RectF(
+                    endPoint.x,
+                    endPoint.y,
+                    endPoint.x + touchTargetContentSize,
+                    endPoint.y + touchTargetContentSize
+                )
+            if (endTarget.contains(location.pagePoint.x, location.pagePoint.y)) {
+                draggingState =
+                    DraggingState(
+                        currentSelection.startBoundary,
+                        currentSelection.endBoundary,
+                        location.pagePoint
+                    )
+                // Play haptic feedback when the user starts dragging the handles
+                _selectionUiSignalBus.tryEmit(
+                    SelectionUiSignal.PlayHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE)
+                )
+                return true
+            }
+        }
+        return false
+    }
+
+    private fun maybeHandleActionMove(location: PdfPoint?): Boolean {
+        val prevDraggingState = draggingState ?: return false
+        // location == null means the user dragged the handle just outside the bounds of any PDF
+        // page.
+        // TODO(b/386398335) Properly handle multi-page selections
+        if (location == null || location.pageNum != prevDraggingState.dragging.location.pageNum) {
+            // When the user drags outside the page, or to another page, we should still "capture"
+            // the gesture (i.e. return true) to prevent spurious scrolling while the user is
+            // attempting to adjust the selection. Return false if no drag is in progress.
+            // See b/385291020
+            return draggingState != null
+        }
+        val dx = location.pagePoint.x - prevDraggingState.downPoint.x
+        val dy = location.pagePoint.y - prevDraggingState.downPoint.y
+        val newEndPoint = prevDraggingState.dragging.location.translateBy(dx, dy)
+        updateSelectionAsync(prevDraggingState.fixed.location, newEndPoint)
+        // Hide the action mode while the user is actively dragging the handles
+        _selectionUiSignalBus.tryEmit(SelectionUiSignal.ToggleActionMode(show = false))
+        return true
+    }
+
+    private fun maybeHandleGestureEnd(): Boolean {
+        val result = draggingState != null
+        draggingState = null
+        // If this gesture actually ended a handle drag operation, trigger haptic feedback and
+        // reveal the action mode
+        if (result) {
+            _selectionUiSignalBus.tryEmit(
+                SelectionUiSignal.PlayHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE)
+            )
+            _selectionUiSignalBus.tryEmit(SelectionUiSignal.ToggleActionMode(show = true))
+        }
+        return result
+    }
+
+    private fun PdfPoint.translateBy(dx: Float, dy: Float): PdfPoint {
+        return PdfPoint(this.pageNum, PointF(this.pagePoint.x + dx, this.pagePoint.y + dy))
+    }
+
     private fun updateSelectionAsync(start: PdfPoint, end: PdfPoint) {
         val prevJob = setSelectionJob
         setSelectionJob =
             backgroundScope
                 .launch {
                     prevJob?.cancelAndJoin()
+                    // TODO(b/386398335) Adapt this logic to support selections that span multiple
+                    // pages
                     val newSelection =
                         pdfDocument.getSelectionBounds(
                             start.pageNum,
@@ -68,20 +235,18 @@
                         )
                     if (newSelection != null && newSelection.hasBounds) {
                         selectionModel = SelectionModel.fromSinglePageSelection(newSelection)
-                        _invalidationSignalFlow.emit(Unit)
+                        _selectionUiSignalBus.tryEmit(SelectionUiSignal.Invalidate)
+                        // Show the action mode if the user is not actively dragging the handles
+                        if (draggingState == null) {
+                            _selectionUiSignalBus.emit(
+                                SelectionUiSignal.ToggleActionMode(show = true)
+                            )
+                        }
                     }
                 }
                 .also { it.invokeOnCompletion { setSelectionJob = null } }
     }
 
-    /** Resets all state of this manager */
-    fun clearSelection() {
-        setSelectionJob?.cancel()
-        setSelectionJob = null
-        if (selectionModel != null) _invalidationSignalFlow.tryEmit(Unit)
-        selectionModel = null
-    }
-
     /**
      * Returns true if this [PageSelection] has selected content with bounds, and if its start and
      * end boundaries include their location. Any selection without this information cannot be
@@ -98,3 +263,27 @@
                 this.stop.point != null
         }
 }
+
+/** Signals to [PdfView] to update the UI in regards to a change in selection state */
+internal sealed interface SelectionUiSignal {
+    /** [PdfView] should invalidate itself to reflect a change in selection */
+    object Invalidate : SelectionUiSignal
+
+    /**
+     * [PdfView] should play haptic feedback to indicate the start or end of a change in selection
+     *
+     * @param level should be a value from [android.view.HapticFeedbackConstants] indicating the
+     *   type of haptic feedback to play
+     */
+    class PlayHapticFeedback(val level: Int) : SelectionUiSignal
+
+    /** [PdfView] should show or hide the selection action mode */
+    class ToggleActionMode(val show: Boolean) : SelectionUiSignal
+}
+
+/** Value class to hold state related to dragging a selection handle */
+private data class DraggingState(
+    val fixed: UiSelectionBoundary,
+    val dragging: UiSelectionBoundary,
+    val downPoint: PointF
+)
diff --git a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/ToolBoxView.kt b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/ToolBoxView.kt
index b94a0aa..42421a2 100644
--- a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/ToolBoxView.kt
+++ b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/ToolBoxView.kt
@@ -38,6 +38,9 @@
     private var pdfDocument: PdfDocument? = null
     private var editClickListener: OnClickListener? = null
 
+    /** A callback to get the current page number. */
+    private var onCurrentPageRequested: (() -> Int)? = null
+
     init {
         inflate(context, R.layout.tool_box_view, this)
         editButton = findViewById(R.id.edit_fab)
@@ -48,14 +51,38 @@
         }
     }
 
+    /**
+     * Sets a callback to get the current page number from the [PdfView].
+     *
+     * @param callback A callback to get the current page number.
+     */
+    public fun setOnCurrentPageRequested(callback: (() -> Int)?) {
+        this.onCurrentPageRequested = callback
+    }
+
+    /**
+     * Sets the [PdfDocument] that the [ToolBoxView] should use.
+     *
+     * @param pdfDocument The [PdfDocument] that the [ToolBoxView] should use.
+     */
     public fun setPdfDocument(pdfDocument: PdfDocument?) {
         this.pdfDocument = pdfDocument
     }
 
+    /**
+     * Sets the drawable that should be used for the edit icon.
+     *
+     * @param drawable The drawable that should be used for the edit icon.
+     */
     public fun setEditIconDrawable(drawable: Drawable?) {
         editButton.setImageDrawable(drawable)
     }
 
+    /**
+     * Sets a [OnClickListener] that will be called when the edit FAB is clicked.
+     *
+     * @param listener The [OnClickListener] that will be called when the edit FAB is clicked.
+     */
     public fun setOnEditClickListener(listener: OnClickListener) {
         editClickListener = listener
     }
@@ -69,7 +96,8 @@
                 AnnotationUtils.getAnnotationIntent(uri).apply {
                     setData(uri)
                     putExtra(EXTRA_PDF_FILE_NAME, Uris.extractName(uri, context.contentResolver))
-                    putExtra(EXTRA_STARTING_PAGE, 0)
+                    val pageNum = onCurrentPageRequested?.invoke() ?: 0
+                    putExtra(EXTRA_STARTING_PAGE, pageNum)
                 }
             startActivity(context, "", intent)
         }
diff --git a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/models.kt b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/models.kt
index c0f01b2..af963a2 100644
--- a/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/models.kt
+++ b/pdf/pdf-viewer/src/main/kotlin/androidx/pdf/view/models.kt
@@ -18,8 +18,10 @@
 
 import android.graphics.PointF
 import android.graphics.RectF
+import android.os.Parcel
 import androidx.annotation.ColorInt
 import androidx.annotation.RestrictTo
+import androidx.core.os.ParcelCompat
 
 /**
  * Represents a rectangle in PDF coordinates, where [pageNum] indicates a PDF page, and [pageRect]
@@ -54,6 +56,27 @@
 }
 
 /**
+ * Writes a [PdfRect] to [dest] with [flags].
+ *
+ * Not part of the public API because public APIs cannot be [android.os.Parcelable]
+ */
+internal fun PdfRect.writeToParcel(dest: Parcel, flags: Int) {
+    dest.writeInt(pageNum)
+    dest.writeParcelable(pageRect, flags)
+}
+
+/**
+ * Reads a [PdfRect] from [source], using [loader].
+ *
+ * Not part of the public API because public APIs cannot be [android.os.Parcelable]
+ */
+internal fun pdfRectFromParcel(source: Parcel, loader: ClassLoader?): PdfRect {
+    val pageNum = source.readInt()
+    val rect = requireNotNull(ParcelCompat.readParcelable(source, loader, RectF::class.java))
+    return PdfRect(pageNum, rect)
+}
+
+/**
  * Represents a point in PDF coordinates, where [pageNum] indicates a 0-indexed PDF page, and
  * [pagePoint] indicates a [PointF] in PDF points within the page, with the origin existing at the
  * top left corner of the page.
@@ -85,6 +108,27 @@
     }
 }
 
+/**
+ * Writes a [PdfPoint] to [dest] with [flags].
+ *
+ * Not part of the public API because public APIs cannot be [android.os.Parcelable]
+ */
+internal fun PdfPoint.writeToParcel(dest: Parcel, flags: Int) {
+    dest.writeInt(pageNum)
+    dest.writeParcelable(pagePoint, flags)
+}
+
+/**
+ * Reads a [PdfPoint] from [source], using [loader].
+ *
+ * Not part of the public API because public APIs cannot be [android.os.Parcelable]
+ */
+internal fun pdfPointFromParcel(source: Parcel, loader: ClassLoader?): PdfPoint {
+    val pageNum = source.readInt()
+    val pagePoint = requireNotNull(ParcelCompat.readParcelable(source, loader, PointF::class.java))
+    return PdfPoint(pageNum, pagePoint)
+}
+
 /** Represents an [area] that should be highlighted with [color]. */
 @RestrictTo(RestrictTo.Scope.LIBRARY)
 public class Highlight(public val area: PdfRect, @ColorInt public val color: Int) {
@@ -144,3 +188,31 @@
         return "TextSelection: text $text bounds $bounds"
     }
 }
+
+/**
+ * Writes a [TextSelection] to [dest] with [flags].
+ *
+ * Not part of the public API because public APIs cannot be [android.os.Parcelable]
+ */
+internal fun TextSelection.writeToParcel(dest: Parcel, flags: Int) {
+    dest.writeString(text)
+    dest.writeInt(bounds.size)
+    for (bound in bounds) {
+        bound.writeToParcel(dest, flags)
+    }
+}
+
+/**
+ * Reads a [TextSelection] from [source], using [loader].
+ *
+ * Not part of the public API because public APIs cannot be [android.os.Parcelable]
+ */
+internal fun textSelectionFromParcel(source: Parcel, loader: ClassLoader?): TextSelection {
+    val text = requireNotNull(source.readString())
+    val boundsSize = source.readInt()
+    val bounds = mutableListOf<PdfRect>()
+    for (i in 0 until boundsSize) {
+        bounds.add(pdfRectFromParcel(source, loader))
+    }
+    return TextSelection(text, bounds.toList())
+}
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 2fc1a5f..e17d86d 100644
--- a/pdf/pdf-viewer/src/main/res/values-af/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-af/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"bladsy <xliff:g id="PAGE">%1$d</xliff:g> van <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoem <xliff:g id="FIRST">%1$d</xliff:g> persent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Gaan na bladsy <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Bladsy <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Leë bladsy"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Bladsy <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Kan nie PDF vertoon nie (<xliff:g id="TITLE">%1$s</xliff:g> is ’n ongeldige formaat)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-am/strings.xml b/pdf/pdf-viewer/src/main/res/values-am/strings.xml
index 80a52f9..90f9b15 100644
--- a/pdf/pdf-viewer/src/main/res/values-am/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-am/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"ገጽ <xliff:g id="PAGE">%1$d</xliff:g> ከ<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> በመቶ ያጉሉ"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"ወደ ገጽ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> ይሂዱ"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"ገፅ <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"ባዶ ገፅ"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"ገፅ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>፦ <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF ማሳየት አልተቻለም (<xliff:g id="TITLE">%1$s</xliff:g> ልክ ያልኾነ ቅርጸት ያለው ነው)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ar/strings.xml b/pdf/pdf-viewer/src/main/res/values-ar/strings.xml
index 3cbb2c0..7531dc0 100644
--- a/pdf/pdf-viewer/src/main/res/values-ar/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ar/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"الصفحة <xliff:g id="PAGE">%1$d</xliff:g> من إجمالي <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"التكبير أو التصغير بنسبة <xliff:g id="FIRST">%1$d</xliff:g> في المئة"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"الانتقال إلى الصفحة <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"الصفحة <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"صفحة فارغة"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"الصفحة <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"‏يتعذَّر عرض ملف PDF (تنسيق الملف \"<xliff:g id="TITLE">%1$s</xliff:g>\" غير صالح)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-as/strings.xml b/pdf/pdf-viewer/src/main/res/values-as/strings.xml
index 5bc831a..ed565c3 100644
--- a/pdf/pdf-viewer/src/main/res/values-as/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-as/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g> খনৰ ভিতৰত <xliff:g id="PAGE">%1$d</xliff:g> নম্বৰ পৃষ্ঠাখন"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> শতাংশ জুম কৰক"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"পৃষ্ঠা <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>লৈ যাওক"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"পৃষ্ঠা <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"খালী পৃষ্ঠা"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"পৃষ্ঠা <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF দেখুৱাব নোৱাৰি (<xliff:g id="TITLE">%1$s</xliff:g>ৰ ফৰ্মেটটো মান্য নহয়)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-az/strings.xml b/pdf/pdf-viewer/src/main/res/values-az/strings.xml
index a6274e3..8c60f13 100644
--- a/pdf/pdf-viewer/src/main/res/values-az/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-az/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"səhifə <xliff:g id="PAGE">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> faiz zum"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g> səhifəsinə keçin"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Səhifə <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Boş səhifə"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Səhifə <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF göstərilmir (<xliff:g id="TITLE">%1$s</xliff:g> yanlış formatdadır)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-b+sr+Latn/strings.xml b/pdf/pdf-viewer/src/main/res/values-b+sr+Latn/strings.xml
index c00d2fd..f43a280 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
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="PAGE">%1$d</xliff:g>. stranica od <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"procenat zuma: <xliff:g id="FIRST">%1$d</xliff:g>"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Idi na stranicu <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Stranica <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Prazna stranica"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Stranica <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF ne može da se prikaže (<xliff:g id="TITLE">%1$s</xliff:g> ima nevažeći format)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-be/strings.xml b/pdf/pdf-viewer/src/main/res/values-be/strings.xml
index b76a7c1..b815f0c 100644
--- a/pdf/pdf-viewer/src/main/res/values-be/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-be/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"старонка <xliff:g id="PAGE">%1$d</xliff:g> з <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"маштаб <xliff:g id="FIRST">%1$d</xliff:g>%%"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"На старонку <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Старонка <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Пустая старонка"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Старонка <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Не ўдаецца паказаць PDF-файл \"<xliff:g id="TITLE">%1$s</xliff:g>\" (няправільны фармат)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-bg/strings.xml b/pdf/pdf-viewer/src/main/res/values-bg/strings.xml
index f5f3743..eae25dd 100644
--- a/pdf/pdf-viewer/src/main/res/values-bg/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-bg/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"страница <xliff:g id="PAGE">%1$d</xliff:g> от <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"Процент на промяна на мащаба: <xliff:g id="FIRST">%1$d</xliff:g>"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Към страница <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Страница <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Празна страница"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Страница <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF файлът <xliff:g id="TITLE">%1$s</xliff:g> не може да се покаже (форматът е невалиден)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-bn/strings.xml b/pdf/pdf-viewer/src/main/res/values-bn/strings.xml
index a559600..12df717 100644
--- a/pdf/pdf-viewer/src/main/res/values-bn/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-bn/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g>টির মধ্যে <xliff:g id="PAGE">%1$d</xliff:g> নম্বর পৃষ্ঠা"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> শতাংশ জুম করুন"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g> নম্বর পৃষ্ঠায় যান"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"পৃষ্ঠা নম্বর <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"খালি পৃষ্ঠা"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"পৃষ্ঠা <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"পিডিএফ দেখানো যাবে না (<xliff:g id="TITLE">%1$s</xliff:g> ভুল ফর্ম্যাটে আছে)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-bs/strings.xml b/pdf/pdf-viewer/src/main/res/values-bs/strings.xml
index e231411..aded442 100644
--- a/pdf/pdf-viewer/src/main/res/values-bs/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-bs/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="PAGE">%1$d</xliff:g>. stranica od <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zumiranje <xliff:g id="FIRST">%1$d</xliff:g> posto"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Odlazak na <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>. stranicu"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g>. stranica"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Prazna stranica"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>. stranica: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Nije moguće prikazati PDF (fajl <xliff:g id="TITLE">%1$s</xliff:g> ima nevažeći format)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ca/strings.xml b/pdf/pdf-viewer/src/main/res/values-ca/strings.xml
index 6d77cc0..c2cbf68 100644
--- a/pdf/pdf-viewer/src/main/res/values-ca/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ca/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"pàgina <xliff:g id="PAGE">%1$d</xliff:g> de <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom <xliff:g id="FIRST">%1$d</xliff:g> per cent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Ves a la pàgina <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Pàgina <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Pàgina buida"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Pàgina <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"No es pot mostrar el PDF (<xliff:g id="TITLE">%1$s</xliff:g> no és un format vàlid)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-cs/strings.xml b/pdf/pdf-viewer/src/main/res/values-cs/strings.xml
index 2bd1139..cb13104 100644
--- a/pdf/pdf-viewer/src/main/res/values-cs/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-cs/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"stránka <xliff:g id="PAGE">%1$d</xliff:g> z <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"lupa <xliff:g id="FIRST">%1$d</xliff:g> procent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Přejít na stránku <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Stránka <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Prázdná stránka"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Stránka <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF nelze zobrazit (<xliff:g id="TITLE">%1$s</xliff:g> má neplatný formát)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-da/strings.xml b/pdf/pdf-viewer/src/main/res/values-da/strings.xml
index f929b0e..cd5475f 100644
--- a/pdf/pdf-viewer/src/main/res/values-da/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-da/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"side <xliff:g id="PAGE">%1$d</xliff:g> af <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom <xliff:g id="FIRST">%1$d</xliff:g> %%"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Gå til side <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Side <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Tom side"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Side <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF kan ikke vises (<xliff:g id="TITLE">%1$s</xliff:g> er i et ugyldigt format)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-de/strings.xml b/pdf/pdf-viewer/src/main/res/values-de/strings.xml
index 2ce338a..48345c4 100644
--- a/pdf/pdf-viewer/src/main/res/values-de/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-de/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"Seite <xliff:g id="PAGE">%1$d</xliff:g> von <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"Zoom: <xliff:g id="FIRST">%1$d</xliff:g> %%"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Gehe zu Seite <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Seite <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Leere Seite"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Seite <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Anzeige von PDF nicht möglich („<xliff:g id="TITLE">%1$s</xliff:g>“ hat ungültiges Dateiformat)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-el/strings.xml b/pdf/pdf-viewer/src/main/res/values-el/strings.xml
index ced8549..d7e9e18 100644
--- a/pdf/pdf-viewer/src/main/res/values-el/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-el/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"σελίδα <xliff:g id="PAGE">%1$d</xliff:g> από <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"εστίαση <xliff:g id="FIRST">%1$d</xliff:g> τοις εκατό"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Μετάβαση στη σελίδα <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Σελίδα <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Κενή σελίδα"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Σελίδα <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Δεν είναι δυνατή η προβολή του PDF (μη έγκυρη μορφή του <xliff:g id="TITLE">%1$s</xliff:g>)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-en-rAU/strings.xml b/pdf/pdf-viewer/src/main/res/values-en-rAU/strings.xml
index bcfbee9..18652f6 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
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"page <xliff:g id="PAGE">%1$d</xliff:g> of <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom <xliff:g id="FIRST">%1$d</xliff:g> per cent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Go to page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Page <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Empty page"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Cannot display PDF (<xliff:g id="TITLE">%1$s</xliff:g> is of invalid format)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-en-rCA/strings.xml b/pdf/pdf-viewer/src/main/res/values-en-rCA/strings.xml
index f494f50..ab2748f 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
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"page <xliff:g id="PAGE">%1$d</xliff:g> of <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom <xliff:g id="FIRST">%1$d</xliff:g> percent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Go to page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Page <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Empty page"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Cannot display PDF (<xliff:g id="TITLE">%1$s</xliff:g> is of invalid format)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-en-rGB/strings.xml b/pdf/pdf-viewer/src/main/res/values-en-rGB/strings.xml
index bcfbee9..18652f6 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
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"page <xliff:g id="PAGE">%1$d</xliff:g> of <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom <xliff:g id="FIRST">%1$d</xliff:g> per cent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Go to page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Page <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Empty page"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Cannot display PDF (<xliff:g id="TITLE">%1$s</xliff:g> is of invalid format)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-en-rIN/strings.xml b/pdf/pdf-viewer/src/main/res/values-en-rIN/strings.xml
index bcfbee9..18652f6 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
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"page <xliff:g id="PAGE">%1$d</xliff:g> of <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom <xliff:g id="FIRST">%1$d</xliff:g> per cent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Go to page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Page <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Empty page"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Cannot display PDF (<xliff:g id="TITLE">%1$s</xliff:g> is of invalid format)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-es-rUS/strings.xml b/pdf/pdf-viewer/src/main/res/values-es-rUS/strings.xml
index da317ab..262b082 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
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"página <xliff:g id="PAGE">%1$d</xliff:g> de <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom <xliff:g id="FIRST">%1$d</xliff:g> por ciento"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Ir a la página <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Página <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Página vacía"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Página <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"No se puede mostrar el PDF (<xliff:g id="TITLE">%1$s</xliff:g> tiene un formato no válido)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-es/strings.xml b/pdf/pdf-viewer/src/main/res/values-es/strings.xml
index 52bdbcf..80c08b9 100644
--- a/pdf/pdf-viewer/src/main/res/values-es/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-es/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"página <xliff:g id="PAGE">%1$d</xliff:g> de <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom <xliff:g id="FIRST">%1$d</xliff:g> por ciento"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Ir a la página <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Página <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Página en blanco"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Página <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"No se puede mostrar el PDF (el formato de <xliff:g id="TITLE">%1$s</xliff:g> no es válido)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-et/strings.xml b/pdf/pdf-viewer/src/main/res/values-et/strings.xml
index 12fd575..c66d8c7 100644
--- a/pdf/pdf-viewer/src/main/res/values-et/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-et/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"lk <xliff:g id="PAGE">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"suum <xliff:g id="FIRST">%1$d</xliff:g> protsenti"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Mine lehele <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Leht <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Tühi leht"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>. leht: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF-i ei saa kuvada (<xliff:g id="TITLE">%1$s</xliff:g> on vales vormingus)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-eu/strings.xml b/pdf/pdf-viewer/src/main/res/values-eu/strings.xml
index 09c5afe..f8f77c2 100644
--- a/pdf/pdf-viewer/src/main/res/values-eu/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-eu/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g> orritatik <xliff:g id="PAGE">%1$d</xliff:g>garrena"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zooma ehuneko <xliff:g id="FIRST">%1$d</xliff:g>"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Joan <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>. orrira"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g>. orria"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Orri hutsa"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>. orria: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Ezin da erakutsi PDFa (<xliff:g id="TITLE">%1$s</xliff:g> fitxategiaren formatuak ez du balio)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-fa/strings.xml b/pdf/pdf-viewer/src/main/res/values-fa/strings.xml
index e371f5d..bd85b34 100644
--- a/pdf/pdf-viewer/src/main/res/values-fa/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-fa/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"صفحه <xliff:g id="PAGE">%1$d</xliff:g> از <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"بزرگ‌نمایی <xliff:g id="FIRST">%1$d</xliff:g> درصد"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"رفتن به صفحه <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"صفحه <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"صفحه خالی"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"صفحه <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"‏‫PDF نمایش داده نمی‌شود (قالب <xliff:g id="TITLE">%1$s</xliff:g> نامعتبر است)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-fi/strings.xml b/pdf/pdf-viewer/src/main/res/values-fi/strings.xml
index 6095b5f..7808d36 100644
--- a/pdf/pdf-viewer/src/main/res/values-fi/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-fi/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"sivu <xliff:g id="PAGE">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoomaus <xliff:g id="FIRST">%1$d</xliff:g> prosenttia"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Siirry sivulle <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Sivu <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Tyhjä sivu"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Sivu <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF:ää ei voi näyttää (<xliff:g id="TITLE">%1$s</xliff:g> on virheellinen muoto)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-fr-rCA/strings.xml b/pdf/pdf-viewer/src/main/res/values-fr-rCA/strings.xml
index c663d60..f5fffbd 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
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"page <xliff:g id="PAGE">%1$d</xliff:g> sur <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom <xliff:g id="FIRST">%1$d</xliff:g> pour cent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Accéder à la page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Page <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Page vide"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> : <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Impossible d\'afficher le PDF (format de <xliff:g id="TITLE">%1$s</xliff:g> non valide)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-fr/strings.xml b/pdf/pdf-viewer/src/main/res/values-fr/strings.xml
index b5c72b3..5f42dc2 100644
--- a/pdf/pdf-viewer/src/main/res/values-fr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-fr/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"page <xliff:g id="PAGE">%1$d</xliff:g> sur <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom : <xliff:g id="FIRST">%1$d</xliff:g> pour cent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Accéder à la page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Page <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Page vide"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> : <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Impossible d\'afficher le PDF (format non valide pour <xliff:g id="TITLE">%1$s</xliff:g>)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-gl/strings.xml b/pdf/pdf-viewer/src/main/res/values-gl/strings.xml
index 9d48171d..17acfbc 100644
--- a/pdf/pdf-viewer/src/main/res/values-gl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-gl/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"páxina <xliff:g id="PAGE">%1$d</xliff:g> de <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom ao <xliff:g id="FIRST">%1$d</xliff:g> por cento"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Vai á páxina <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Páxina <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Páxina baleira"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Páxina <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Non se puido mostrar o PDF (<xliff:g id="TITLE">%1$s</xliff:g> ten un formato non válido)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-gu/strings.xml b/pdf/pdf-viewer/src/main/res/values-gu/strings.xml
index a2038ad..5d0c8c5 100644
--- a/pdf/pdf-viewer/src/main/res/values-gu/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-gu/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g>માંથી પેજ <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> ટકા નાનું-મોટું કરો"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"પેજ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> પર જાઓ"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"પેજ <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"ખાલી પેજ"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"પેજ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF બતાવી શકાતી નથી (<xliff:g id="TITLE">%1$s</xliff:g>નું ફૉર્મેટ અમાન્ય છે)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-hi/strings.xml b/pdf/pdf-viewer/src/main/res/values-hi/strings.xml
index b67f06e..215e57a 100644
--- a/pdf/pdf-viewer/src/main/res/values-hi/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-hi/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g> में से <xliff:g id="PAGE">%1$d</xliff:g> नंबर का पेज"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> प्रतिशत ज़ूम करें"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g> पेज पर जाएं"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"पेज <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"पेज खाली है"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"पेज <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF फ़ाइल नहीं दिखाई जा सकती (<xliff:g id="TITLE">%1$s</xliff:g> अमान्य फ़ॉर्मैट में है)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-hr/strings.xml b/pdf/pdf-viewer/src/main/res/values-hr/strings.xml
index 626b4df..a1608c4 100644
--- a/pdf/pdf-viewer/src/main/res/values-hr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-hr/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"stranica <xliff:g id="PAGE">%1$d</xliff:g> od <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zumiranje <xliff:g id="FIRST">%1$d</xliff:g> posto"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Idite na stranicu <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Stranica <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Prazna stranica"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Stranica <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF se ne može prikazati (format <xliff:g id="TITLE">%1$s</xliff:g> nije važeći)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-hu/strings.xml b/pdf/pdf-viewer/src/main/res/values-hu/strings.xml
index e817843..c85e515 100644
--- a/pdf/pdf-viewer/src/main/res/values-hu/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-hu/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g>/<xliff:g id="PAGE">%1$d</xliff:g>. oldal"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> százalékos nagyítás"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Ugrás erre az oldalra: <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g>. oldal"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Üres oldal"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>. oldal: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Nem sikerült megjeleníteni a PDF-et (<xliff:g id="TITLE">%1$s</xliff:g> formátuma érvénytelen)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-hy/strings.xml b/pdf/pdf-viewer/src/main/res/values-hy/strings.xml
index 7ee24f3..eca3c77 100644
--- a/pdf/pdf-viewer/src/main/res/values-hy/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-hy/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"Էջ <xliff:g id="PAGE">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"մասշտաբ՝ <xliff:g id="FIRST">%1$d</xliff:g> տոկոս"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Անցեք <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> էջ"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Էջ <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Դատարկ էջ"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Էջ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>՝ <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Հնարավոր չէ ցուցադրել PDF-ը (<xliff:g id="TITLE">%1$s</xliff:g> ֆայլը անվավեր ձևաչափ ունի)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-in/strings.xml b/pdf/pdf-viewer/src/main/res/values-in/strings.xml
index 5fcd157..521fc2d 100644
--- a/pdf/pdf-viewer/src/main/res/values-in/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-in/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"halaman <xliff:g id="PAGE">%1$d</xliff:g> dari <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom <xliff:g id="FIRST">%1$d</xliff:g> persen"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Buka halaman <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Halaman <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Halaman kosong"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Halaman <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Tidak dapat menampilkan PDF (format <xliff:g id="TITLE">%1$s</xliff:g> tidak valid)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-is/strings.xml b/pdf/pdf-viewer/src/main/res/values-is/strings.xml
index 8c01997..0d923ae 100644
--- a/pdf/pdf-viewer/src/main/res/values-is/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-is/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"síða <xliff:g id="PAGE">%1$d</xliff:g> af <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"stækka/minnka <xliff:g id="FIRST">%1$d</xliff:g> prósent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Fara á síðu <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Síða <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Auð síða"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Síða <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Ekki hægt að birta PDF (<xliff:g id="TITLE">%1$s</xliff:g> er á ógildu sniði)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-it/strings.xml b/pdf/pdf-viewer/src/main/res/values-it/strings.xml
index 056c063..eaaba33 100644
--- a/pdf/pdf-viewer/src/main/res/values-it/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-it/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"pagina <xliff:g id="PAGE">%1$d</xliff:g> di <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom <xliff:g id="FIRST">%1$d</xliff:g>%%"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Vai alla pagina <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Pagina <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Pagina vuota"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Pagina <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Impossibile visualizzare PDF (<xliff:g id="TITLE">%1$s</xliff:g> è in un formato non valido)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-iw/strings.xml b/pdf/pdf-viewer/src/main/res/values-iw/strings.xml
index 4d4709d..03c20c6 100644
--- a/pdf/pdf-viewer/src/main/res/values-iw/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-iw/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"דף <xliff:g id="PAGE">%1$d</xliff:g> מתוך <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"שינוי מרחק התצוגה ב-<xliff:g id="FIRST">%1$d</xliff:g> אחוזים"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"מעבר לדף <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"דף <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"דף ריק"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"דף <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: ‏<xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"‏אי אפשר להציג קובץ PDF ‏(<xliff:g id="TITLE">%1$s</xliff:g> בפורמט לא תקין)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ja/strings.xml b/pdf/pdf-viewer/src/main/res/values-ja/strings.xml
index bc5e265..c98de41 100644
--- a/pdf/pdf-viewer/src/main/res/values-ja/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ja/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="PAGE">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g> ページ"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"ズーム <xliff:g id="FIRST">%1$d</xliff:g> %%"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g> ページに移動します"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g> ページ"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"空白のページ"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"ページ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF を表示できません(<xliff:g id="TITLE">%1$s</xliff:g> の形式が無効です)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ka/strings.xml b/pdf/pdf-viewer/src/main/res/values-ka/strings.xml
index 374c966c..38f52dd 100644
--- a/pdf/pdf-viewer/src/main/res/values-ka/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ka/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"გვერდი <xliff:g id="PAGE">%1$d</xliff:g> / <xliff:g id="TOTAL">%2$d</xliff:g>-დან"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"მასშტაბი <xliff:g id="FIRST">%1$d</xliff:g> პროცენტი"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>-ე გვერდზე გადასვლა"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"გვერდი <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"ცარიელი გვერდი"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"გვერდი <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF-ის ჩვენება შეუძლებელია (<xliff:g id="TITLE">%1$s</xliff:g> არასწორ ფორმატშია)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-kk/strings.xml b/pdf/pdf-viewer/src/main/res/values-kk/strings.xml
index 77ad8f4..fa832ad 100644
--- a/pdf/pdf-viewer/src/main/res/values-kk/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-kk/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"Бет: <xliff:g id="PAGE">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> пайызға масштабтау"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>-бетке өтіңіз."</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g>-бет"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Бос бет"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>-бет: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF файлын көрсету мүмкін емес (<xliff:g id="TITLE">%1$s</xliff:g> форматы жарамсыз)."</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-km/strings.xml b/pdf/pdf-viewer/src/main/res/values-km/strings.xml
index 66502ac..5657c3e 100644
--- a/pdf/pdf-viewer/src/main/res/values-km/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-km/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"ទំព័រទី <xliff:g id="PAGE">%1$d</xliff:g> នៃ <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"ពង្រីកបង្រួម <xliff:g id="FIRST">%1$d</xliff:g> ភាគរយ"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"ទៅទំព័រទី <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"ទំព័រទី <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"ទំព័រទទេ"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"ទំព័រទី <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>៖ <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"មិនអាច​បង្ហាញ PDF បានទេ (<xliff:g id="TITLE">%1$s</xliff:g> មានទម្រង់មិន​ត្រឹមត្រូវ)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-kn/strings.xml b/pdf/pdf-viewer/src/main/res/values-kn/strings.xml
index 8115670..e41ae2a 100644
--- a/pdf/pdf-viewer/src/main/res/values-kn/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-kn/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="PAGE">%1$d</xliff:g> ಪುಟ"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"ಶೇಕಡಾ <xliff:g id="FIRST">%1$d</xliff:g> ರಷ್ಟು ಝೂಮ್ ಮಾಡಿ"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"ಪುಟ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> ಕ್ಕೆ ತೆರಳಿ"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"ಪುಟ <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"ಖಾಲಿ ಪುಟ"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"ಪುಟ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF ಅನ್ನು ಪ್ರದರ್ಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ (<xliff:g id="TITLE">%1$s</xliff:g> ಅಮಾನ್ಯವಾದ ಫಾರ್ಮ್ಯಾಟ್ ಆಗಿದೆ)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ko/strings.xml b/pdf/pdf-viewer/src/main/res/values-ko/strings.xml
index d732f3d..1c91838 100644
--- a/pdf/pdf-viewer/src/main/res/values-ko/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ko/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g>페이지 중 <xliff:g id="PAGE">%1$d</xliff:g>페이지"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g>%% 확대/축소"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g> 페이지로 이동"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g>페이지"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"빈 페이지"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>페이지: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"<xliff:g id="TITLE">%1$s</xliff:g>의 형식이 잘못되어 PDF를 표시할 수 없음"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ky/strings.xml b/pdf/pdf-viewer/src/main/res/values-ky/strings.xml
index 00289d9..a5da24f 100644
--- a/pdf/pdf-viewer/src/main/res/values-ky/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ky/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g> ичинен <xliff:g id="PAGE">%1$d</xliff:g>-бет"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> пайыз чоңойтуу/кичирейтүү"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g> бетине өтүңүз"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g>-бет"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Бош бет"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>-бет: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF\'ти көрсөтүү мүмкүн эмес (<xliff:g id="TITLE">%1$s</xliff:g> форматы жараксыз)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-lo/strings.xml b/pdf/pdf-viewer/src/main/res/values-lo/strings.xml
index afbb196e..0d6dc62 100644
--- a/pdf/pdf-viewer/src/main/res/values-lo/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-lo/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"ໜ້າທີ <xliff:g id="PAGE">%1$d</xliff:g> ຈາກທັງໝົດ <xliff:g id="TOTAL">%2$d</xliff:g> ໜ້າ"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"ຊູມ <xliff:g id="FIRST">%1$d</xliff:g> ເປີເຊັນ"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"ໄປທີ່ໜ້າ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"ໜ້າ <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"ໜ້າຫວ່າງເປົ່າ"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"ໜ້າ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"ບໍ່ສາມາດສະແດງ PDF (<xliff:g id="TITLE">%1$s</xliff:g> ມີຮູບແບບທີ່ບໍ່ຖືກຕ້ອງ)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-lt/strings.xml b/pdf/pdf-viewer/src/main/res/values-lt/strings.xml
index d49f651..0737670 100644
--- a/pdf/pdf-viewer/src/main/res/values-lt/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-lt/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="PAGE">%1$d</xliff:g> psl. iš <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"keisti mastelį <xliff:g id="FIRST">%1$d</xliff:g> proc."</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Eiti į <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> puslapį"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g> puslapis"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Tuščias puslapis"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g> puslapis: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Negalima pateikti PDF („<xliff:g id="TITLE">%1$s</xliff:g>“ netinkamo formato)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-lv/strings.xml b/pdf/pdf-viewer/src/main/res/values-lv/strings.xml
index fecb537..21fa396f 100644
--- a/pdf/pdf-viewer/src/main/res/values-lv/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-lv/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="PAGE">%1$d</xliff:g>. lapa no <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"tālummaiņa procentos ir <xliff:g id="FIRST">%1$d</xliff:g>"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Doties uz <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>. lapu"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g>. lapa"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Tukša lapa"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>. lpp.: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Nevar parādīt PDF (faila “<xliff:g id="TITLE">%1$s</xliff:g>” formāts nav derīgs)."</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-mk/strings.xml b/pdf/pdf-viewer/src/main/res/values-mk/strings.xml
index 416eb02..d7ba10e 100644
--- a/pdf/pdf-viewer/src/main/res/values-mk/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-mk/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"страница <xliff:g id="PAGE">%1$d</xliff:g> од <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"зумирајте <xliff:g id="FIRST">%1$d</xliff:g> проценти"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Одете на страницата <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Страница <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Празна страница"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Страница <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Не може да се прикаже PDF (<xliff:g id="TITLE">%1$s</xliff:g> е со неважечки формат)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ml/strings.xml b/pdf/pdf-viewer/src/main/res/values-ml/strings.xml
index 4f8584a..7bce561 100644
--- a/pdf/pdf-viewer/src/main/res/values-ml/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ml/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g>-ൽ <xliff:g id="PAGE">%1$d</xliff:g>-ാമത്തെ പേജ്"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> ശതമാനം സൂം ചെയ്യുക"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g> പേജിലേക്ക് പോകുക"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"പേജ് <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"ശൂന്യമായ പേജ്"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"പേജ് <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF ദൃശ്യമാക്കാനാവില്ല (<xliff:g id="TITLE">%1$s</xliff:g>, അസാധുവായ ഫോർമാറ്റിലാണ്)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-mn/strings.xml b/pdf/pdf-viewer/src/main/res/values-mn/strings.xml
index f15a09e..71cf402 100644
--- a/pdf/pdf-viewer/src/main/res/values-mn/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-mn/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"Нийт <xliff:g id="TOTAL">%2$d</xliff:g> хуудасны <xliff:g id="PAGE">%1$d</xliff:g>-р хуудас"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> хувь томруулсан"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>-р хуудсанд очих"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g>-р хуудас"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Хоосон хуудас"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>-р хуудас: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF-г үзүүлэх боломжгүй (<xliff:g id="TITLE">%1$s</xliff:g>-н формат буруу байна)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-mr/strings.xml b/pdf/pdf-viewer/src/main/res/values-mr/strings.xml
index cfaa8ba..57f16e3 100644
--- a/pdf/pdf-viewer/src/main/res/values-mr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-mr/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g> पैकी पेज <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> टक्के झूम करा"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"पेज <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> वर जा"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"पेज <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"रिक्त पेज"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"पेज <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF दाखवू शकत नाही (<xliff:g id="TITLE">%1$s</xliff:g> चा फॉरमॅट चुकीचा आहे)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ms/strings.xml b/pdf/pdf-viewer/src/main/res/values-ms/strings.xml
index 12aa505..b76b58e 100644
--- a/pdf/pdf-viewer/src/main/res/values-ms/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ms/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"halaman <xliff:g id="PAGE">%1$d</xliff:g> daripada <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zum <xliff:g id="FIRST">%1$d</xliff:g> peratus"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Akses halaman <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Halaman <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Halaman kosong"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Halaman <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Tidak dapat memaparkan PDF (format untuk <xliff:g id="TITLE">%1$s</xliff:g> tidak sah)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-my/strings.xml b/pdf/pdf-viewer/src/main/res/values-my/strings.xml
index 721fb47..1225fad 100644
--- a/pdf/pdf-viewer/src/main/res/values-my/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-my/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"စာမျက်နှာ <xliff:g id="TOTAL">%2$d</xliff:g> အနက် <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"ဇူးမ် <xliff:g id="FIRST">%1$d</xliff:g> ရာခိုင်နှုန်း"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"စာမျက်နှာ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> သို့"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"စာမျက်နှာ <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"စာမျက်နှာအလွတ်"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"စာမျက်နှာ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>- <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF ကို ပြ၍မရပါ (<xliff:g id="TITLE">%1$s</xliff:g> သည် မမှန်ကန်သော ဖော်မက်ဖြစ်သည်)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-nb/strings.xml b/pdf/pdf-viewer/src/main/res/values-nb/strings.xml
index 1b00c6c..b21081b 100644
--- a/pdf/pdf-viewer/src/main/res/values-nb/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-nb/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"side <xliff:g id="PAGE">%1$d</xliff:g> av <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom <xliff:g id="FIRST">%1$d</xliff:g> prosent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Gå til side <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Side <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Blank side"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Side <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Kan ikke vise PDF-filen (<xliff:g id="TITLE">%1$s</xliff:g> har ugyldig format)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ne/strings.xml b/pdf/pdf-viewer/src/main/res/values-ne/strings.xml
index 3abed01..ac4b875 100644
--- a/pdf/pdf-viewer/src/main/res/values-ne/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ne/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g> मध्ये <xliff:g id="PAGE">%1$d</xliff:g> औँ पेज"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> प्रतिशत जुम गर्नुहोस्"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"पेज <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> मा जानुहोस्"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"पेज <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"यो पेज खाली छ"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"पेज <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF देखाउन मिल्दैन (<xliff:g id="TITLE">%1$s</xliff:g> को फर्म्याट अवैध छ)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-nl/strings.xml b/pdf/pdf-viewer/src/main/res/values-nl/strings.xml
index f808ff2..17a892b 100644
--- a/pdf/pdf-viewer/src/main/res/values-nl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-nl/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"pagina <xliff:g id="PAGE">%1$d</xliff:g> van <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom <xliff:g id="FIRST">%1$d</xliff:g> procent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Ga naar pagina <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Pagina <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Lege pagina"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Pagina <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Kan pdf niet weergeven (indeling van <xliff:g id="TITLE">%1$s</xliff:g> is ongeldig)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-or/strings.xml b/pdf/pdf-viewer/src/main/res/values-or/strings.xml
index a20b083..eb9dcee 100644
--- a/pdf/pdf-viewer/src/main/res/values-or/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-or/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g>ରୁ <xliff:g id="PAGE">%1$d</xliff:g> ପୃଷ୍ଠା"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"ଜୁମ <xliff:g id="FIRST">%1$d</xliff:g> ଶତକଡ଼ା"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g> ପୃଷ୍ଠାକୁ ଯାଆନ୍ତୁ"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"ପୃଷ୍ଠା <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"ଖାଲି ପୃଷ୍ଠା"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"ପୃଷ୍ଠା <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF ଡିସପ୍ଲେ ହୋଇପାରିବ ନାହିଁ (<xliff:g id="TITLE">%1$s</xliff:g>ର ଫର୍ମାଟ ଅବୈଧ ଅଟେ)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-pa/strings.xml b/pdf/pdf-viewer/src/main/res/values-pa/strings.xml
index 0cb6d48..b6cdd23 100644
--- a/pdf/pdf-viewer/src/main/res/values-pa/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-pa/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g> ਵਿੱਚੋਂ <xliff:g id="PAGE">%1$d</xliff:g> ਪੰਨਾ"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"ਜ਼ੂਮ <xliff:g id="FIRST">%1$d</xliff:g> ਫ਼ੀਸਦ"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g> ਪੰਨੇ \'ਤੇ ਜਾਓ"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"ਪੰਨਾ <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"ਖਾਲੀ ਪੰਨਾ"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"ਪੰਨਾ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF ਨੂੰ ਦਿਖਾਇਆ ਨਹੀਂ ਜਾ ਸਕਦਾ (<xliff:g id="TITLE">%1$s</xliff:g> ਅਵੈਧ ਫਾਰਮੈਟ ਦਾ ਹੈ)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-pl/strings.xml b/pdf/pdf-viewer/src/main/res/values-pl/strings.xml
index 23016e9..ec60ef7 100644
--- a/pdf/pdf-viewer/src/main/res/values-pl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-pl/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"strona <xliff:g id="PAGE">%1$d</xliff:g> z <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"powiększenie <xliff:g id="FIRST">%1$d</xliff:g> procent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Idź do strony <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Strona <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Pusta strona"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Strona <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Nie można wyświetlić PDF-a (<xliff:g id="TITLE">%1$s</xliff:g> ma zły format)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-pt-rBR/strings.xml b/pdf/pdf-viewer/src/main/res/values-pt-rBR/strings.xml
index 07d1389..901115c 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
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"página <xliff:g id="PAGE">%1$d</xliff:g> de <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom de <xliff:g id="FIRST">%1$d</xliff:g>%%"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Ir para a página <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Página <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Página vazia"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Página <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Não é possível mostrar o PDF (<xliff:g id="TITLE">%1$s</xliff:g>: formato inválido)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-pt-rPT/strings.xml b/pdf/pdf-viewer/src/main/res/values-pt-rPT/strings.xml
index 5bf69e7..61f9a19 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
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"página <xliff:g id="PAGE">%1$d</xliff:g> de <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom a <xliff:g id="FIRST">%1$d</xliff:g> por cento"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Ir para a página <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Página <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Página vazia"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Página <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Não é possível apresentar o PDF (<xliff:g id="TITLE">%1$s</xliff:g> tem um formato inválido)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-pt/strings.xml b/pdf/pdf-viewer/src/main/res/values-pt/strings.xml
index 07d1389..901115c 100644
--- a/pdf/pdf-viewer/src/main/res/values-pt/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-pt/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"página <xliff:g id="PAGE">%1$d</xliff:g> de <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom de <xliff:g id="FIRST">%1$d</xliff:g>%%"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Ir para a página <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Página <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Página vazia"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Página <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Não é possível mostrar o PDF (<xliff:g id="TITLE">%1$s</xliff:g>: formato inválido)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ro/strings.xml b/pdf/pdf-viewer/src/main/res/values-ro/strings.xml
index 2f144a0..06cb930 100644
--- a/pdf/pdf-viewer/src/main/res/values-ro/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ro/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"pagina <xliff:g id="PAGE">%1$d</xliff:g> din <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zoom de <xliff:g id="FIRST">%1$d</xliff:g> %%"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Accesează pagina <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Pagina <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Pagină goală"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Pagina <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Nu se poate afișa ca PDF (<xliff:g id="TITLE">%1$s</xliff:g> are un format nevalid)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ru/strings.xml b/pdf/pdf-viewer/src/main/res/values-ru/strings.xml
index 42c70e7..12794a4 100644
--- a/pdf/pdf-viewer/src/main/res/values-ru/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ru/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"страница <xliff:g id="PAGE">%1$d</xliff:g> из <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"масштаб: <xliff:g id="FIRST">%1$d</xliff:g> %%"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Перейти на страницу <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Страница <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Пустая страница"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Страница <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>. <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Недопустимый формат файла \"<xliff:g id="TITLE">%1$s</xliff:g>\"."</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-si/strings.xml b/pdf/pdf-viewer/src/main/res/values-si/strings.xml
index 0e660c5..2f98180 100644
--- a/pdf/pdf-viewer/src/main/res/values-si/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-si/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g> න් <xliff:g id="PAGE">%1$d</xliff:g> වෙනි පිටුව"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"විශාලනය සියයට <xliff:g id="FIRST">%1$d</xliff:g>"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g> වෙනි පිටුවට යන්න"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"පිටුව <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"හිස් පිටුව"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"පිටුව <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF සංදර්ශනය කළ නොහැක (<xliff:g id="TITLE">%1$s</xliff:g> අවලංගු ආකෘතියකි)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-sk/strings.xml b/pdf/pdf-viewer/src/main/res/values-sk/strings.xml
index 33ac624..d4d7d03 100644
--- a/pdf/pdf-viewer/src/main/res/values-sk/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sk/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"strana <xliff:g id="PAGE">%1$d</xliff:g> z <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"lupa na <xliff:g id="FIRST">%1$d</xliff:g> percent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Prejsť na stránku <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g>. strana"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Prázdna strana"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Strana <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Súbor PDF sa nedá zobraziť (<xliff:g id="TITLE">%1$s</xliff:g> má neplatný formát)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-sl/strings.xml b/pdf/pdf-viewer/src/main/res/values-sl/strings.xml
index 813e31f..585e83d 100644
--- a/pdf/pdf-viewer/src/main/res/values-sl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sl/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"stran <xliff:g id="PAGE">%1$d</xliff:g> od <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"povečava <xliff:g id="FIRST">%1$d</xliff:g> %%"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Pojdi na stran <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g>. stran"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Prazna stran"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>. stran: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF-ja ni mogoče prikazati (<xliff:g id="TITLE">%1$s</xliff:g> ni veljavna oblika)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-sq/strings.xml b/pdf/pdf-viewer/src/main/res/values-sq/strings.xml
index a11001e..218f09b 100644
--- a/pdf/pdf-viewer/src/main/res/values-sq/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sq/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"faqja <xliff:g id="PAGE">%1$d</xliff:g> nga <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zmadho me <xliff:g id="FIRST">%1$d</xliff:g> për qind"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Shko te faqja <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Faqja <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Faqe bosh"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Faqja <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Skedari PDF nuk mund të shfaqet (\"<xliff:g id="TITLE">%1$s</xliff:g>\" ka format të pavlefshëm)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-sr/strings.xml b/pdf/pdf-viewer/src/main/res/values-sr/strings.xml
index 8016e17..d88bae3 100644
--- a/pdf/pdf-viewer/src/main/res/values-sr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sr/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="PAGE">%1$d</xliff:g>. страница од <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"проценат зума: <xliff:g id="FIRST">%1$d</xliff:g>"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Иди на страницу <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Страница <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Празна страница"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Страница <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF не може да се прикаже (<xliff:g id="TITLE">%1$s</xliff:g> има неважећи формат)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-sv/strings.xml b/pdf/pdf-viewer/src/main/res/values-sv/strings.xml
index d99983b..7966f88a 100644
--- a/pdf/pdf-viewer/src/main/res/values-sv/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sv/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"sida <xliff:g id="PAGE">%1$d</xliff:g> av <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zooma <xliff:g id="FIRST">%1$d</xliff:g> procent"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Öppna sidan <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Sida <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Tom sida"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Sida <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Det går inte att visa PDF-filen (<xliff:g id="TITLE">%1$s</xliff:g> har ett ogiltigt format)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-sw/strings.xml b/pdf/pdf-viewer/src/main/res/values-sw/strings.xml
index 07499d7..d9c1f71 100644
--- a/pdf/pdf-viewer/src/main/res/values-sw/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-sw/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"ukurasa wa <xliff:g id="PAGE">%1$d</xliff:g> kati ya <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"kuza kwa asilimia <xliff:g id="FIRST">%1$d</xliff:g>"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Fungua ukurasa wa <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Ukurasa wa <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Ukurasa hauna chochote"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Ukurasa wa <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Imeshindwa kuonyesha PDF (muundo wa <xliff:g id="TITLE">%1$s</xliff:g> si sahihi)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ta/strings.xml b/pdf/pdf-viewer/src/main/res/values-ta/strings.xml
index 384ee2c..2dcdc17 100644
--- a/pdf/pdf-viewer/src/main/res/values-ta/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ta/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"பக்கம் <xliff:g id="PAGE">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"<xliff:g id="FIRST">%1$d</xliff:g> சதவீத அளவை மாற்று"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"பக்கம் <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>க்கு செல்லும்"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"பக்கம் <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"காலியான பக்கம்"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"பக்கம் <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDFஐக் காட்ட முடியவில்லை (<xliff:g id="TITLE">%1$s</xliff:g> தவறான வடிவத்தில் உள்ளது)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-te/strings.xml b/pdf/pdf-viewer/src/main/res/values-te/strings.xml
index aa15450..b8733ab 100644
--- a/pdf/pdf-viewer/src/main/res/values-te/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-te/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"<xliff:g id="TOTAL">%2$d</xliff:g>లో <xliff:g id="PAGE">%1$d</xliff:g>వ పేజీ"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"జూమ్ <xliff:g id="FIRST">%1$d</xliff:g> శాతం"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g> పేజీకి వెళ్లండి"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"పేజీ <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"ఖాళీ పేజీ"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"పేజీ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF డిస్‌ప్లే చేయడం సాధ్యం కాదు (<xliff:g id="TITLE">%1$s</xliff:g> చెల్లని ఫార్మాట్‌లో ఉంది)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-th/strings.xml b/pdf/pdf-viewer/src/main/res/values-th/strings.xml
index 2fb7d07..561d5b4 100644
--- a/pdf/pdf-viewer/src/main/res/values-th/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-th/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"หน้า <xliff:g id="PAGE">%1$d</xliff:g> จาก <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"ซูม <xliff:g id="FIRST">%1$d</xliff:g> เปอร์เซ็นต์"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"ไปที่หน้า <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"หน้าที่ <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"หน้าว่างเปล่า"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"หน้า <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"ไม่สามารถแสดง PDF (<xliff:g id="TITLE">%1$s</xliff:g> มีรูปแบบไม่ถูกต้อง)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-tl/strings.xml b/pdf/pdf-viewer/src/main/res/values-tl/strings.xml
index 6b5ece5..c350fb1 100644
--- a/pdf/pdf-viewer/src/main/res/values-tl/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-tl/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"page <xliff:g id="PAGE">%1$d</xliff:g> sa <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"i-zoom nang <xliff:g id="FIRST">%1$d</xliff:g> porsyento"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Pumunta sa page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Page <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Walang lamang page"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Page <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Hindi maipakita ang PDF (invalid ang format ng <xliff:g id="TITLE">%1$s</xliff:g>)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-tr/strings.xml b/pdf/pdf-viewer/src/main/res/values-tr/strings.xml
index dc74389..e942abd 100644
--- a/pdf/pdf-viewer/src/main/res/values-tr/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-tr/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"sayfa <xliff:g id="PAGE">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"yakınlaştırma yüzdesi <xliff:g id="FIRST">%1$d</xliff:g>"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Şu sayfaya git <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g>. sayfa"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Boş sayfa"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Sayfa <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF görüntülenemiyor (<xliff:g id="TITLE">%1$s</xliff:g> geçersiz biçimde)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-uk/strings.xml b/pdf/pdf-viewer/src/main/res/values-uk/strings.xml
index 6f503b4..dab20cf 100644
--- a/pdf/pdf-viewer/src/main/res/values-uk/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-uk/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"сторінка <xliff:g id="PAGE">%1$d</xliff:g> з <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"масштаб <xliff:g id="FIRST">%1$d</xliff:g>%%"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Перейти на сторінку <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Сторінка <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Пуста сторінка"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Сторінка <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Не вдається відобразити PDF (недійсний формат файлу \"<xliff:g id="TITLE">%1$s</xliff:g>\")"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-ur/strings.xml b/pdf/pdf-viewer/src/main/res/values-ur/strings.xml
index daafce7..cb3ff36 100644
--- a/pdf/pdf-viewer/src/main/res/values-ur/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-ur/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"صفحہ <xliff:g id="PAGE">%1$d</xliff:g> از <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"زوم <xliff:g id="FIRST">%1$d</xliff:g> فیصد"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g> صفحہ پر جائیں"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"صفحہ <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"خالی صفحہ"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"صفحہ <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"‏PDF ڈسپلے نہیں کر سکتا (<xliff:g id="TITLE">%1$s</xliff:g> کا فارمیٹ غلط ہے)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-uz/strings.xml b/pdf/pdf-viewer/src/main/res/values-uz/strings.xml
index 50176e0..b0e3a94 100644
--- a/pdf/pdf-viewer/src/main/res/values-uz/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-uz/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"sahifa: <xliff:g id="PAGE">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"zum: <xliff:g id="FIRST">%1$d</xliff:g> foiz"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"<xliff:g id="PAGE_NUMBER">%1$d</xliff:g>-sahifaga oʻtish"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"<xliff:g id="PAGE">%1$d</xliff:g>-sahifa"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Boʻsh sahifa"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Sahifa <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"PDF fayl koʻrsatilmaydi (<xliff:g id="TITLE">%1$s</xliff:g> yaroqsiz formatda)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-vi/strings.xml b/pdf/pdf-viewer/src/main/res/values-vi/strings.xml
index 9f55138..4eacb6e 100644
--- a/pdf/pdf-viewer/src/main/res/values-vi/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-vi/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"trang <xliff:g id="PAGE">%1$d</xliff:g> trong số <xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"thu phóng <xliff:g id="FIRST">%1$d</xliff:g> phần trăm"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Chuyển đến trang <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Trang <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Trang trống"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Trang <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Không hiển thị được tệp PDF (<xliff:g id="TITLE">%1$s</xliff:g> có định dạng không hợp lệ)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-w840dp/dimensions.xml b/pdf/pdf-viewer/src/main/res/values-w840dp/dimensions.xml
new file mode 100644
index 0000000..b292cd0
--- /dev/null
+++ b/pdf/pdf-viewer/src/main/res/values-w840dp/dimensions.xml
@@ -0,0 +1,19 @@
+<?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>
+    <dimen name="pdf_horizontal_padding">40dp</dimen>
+</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 3c4071a..4352a26 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
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"第 <xliff:g id="PAGE">%1$d</xliff:g> 页,共 <xliff:g id="TOTAL">%2$d</xliff:g> 页"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"缩放比例为百分之 <xliff:g id="FIRST">%1$d</xliff:g>"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"前往第 <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> 页"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"第 <xliff:g id="PAGE">%1$d</xliff:g> 页"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"空白页面"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"第 <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> 页:<xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"无法显示 PDF(“<xliff:g id="TITLE">%1$s</xliff:g>”的格式无效)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-zh-rHK/strings.xml b/pdf/pdf-viewer/src/main/res/values-zh-rHK/strings.xml
index 7874963..b157798 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
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"第 <xliff:g id="PAGE">%1$d</xliff:g> 頁,共 <xliff:g id="TOTAL">%2$d</xliff:g> 頁"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"縮放 <xliff:g id="FIRST">%1$d</xliff:g>%%"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"前往第 <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> 頁"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"第 <xliff:g id="PAGE">%1$d</xliff:g> 頁"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"空白頁"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"第 <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> 頁:<xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"無法顯示 PDF (<xliff:g id="TITLE">%1$s</xliff:g> 格式無效)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-zh-rTW/strings.xml b/pdf/pdf-viewer/src/main/res/values-zh-rTW/strings.xml
index fbef1d7..7f2ca64 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
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"第 <xliff:g id="PAGE">%1$d</xliff:g> 頁,共 <xliff:g id="TOTAL">%2$d</xliff:g> 頁"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"縮放 <xliff:g id="FIRST">%1$d</xliff:g>%%"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"前往第 <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> 頁"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"第 <xliff:g id="PAGE">%1$d</xliff:g> 頁"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"空白頁面"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"第 <xliff:g id="PAGE_NUMBER">%1$d</xliff:g> 頁:<xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"無法顯示 PDF (「<xliff:g id="TITLE">%1$s</xliff:g>」的格式無效)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values-zu/strings.xml b/pdf/pdf-viewer/src/main/res/values-zu/strings.xml
index 746c1a5..dda6441 100644
--- a/pdf/pdf-viewer/src/main/res/values-zu/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values-zu/strings.xml
@@ -29,8 +29,7 @@
     <string name="desc_page_single" msgid="8459583146661044094">"ikhasi <xliff:g id="PAGE">%1$d</xliff:g> kwangu-<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="desc_zoom" msgid="7318480946145947242">"sondeza iphesenti elingu-<xliff:g id="FIRST">%1$d</xliff:g>"</string>
     <string name="desc_goto_link" msgid="2461368384824849714">"Iya ekhasini <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>"</string>
-    <!-- no translation found for desc_page (6702471448987833953) -->
-    <skip />
+    <string name="desc_page" msgid="6702471448987833953">"Ikhasi <xliff:g id="PAGE">%1$d</xliff:g>"</string>
     <string name="desc_empty_page" msgid="5041794048330057239">"Ikhasi elingenalutho"</string>
     <string name="desc_page_with_text" msgid="2564017005407577604">"Ikhasi <xliff:g id="PAGE_NUMBER">%1$d</xliff:g>: <xliff:g id="PAGE_TEXT">%2$s</xliff:g>"</string>
     <string name="error_file_format_pdf" msgid="7567006188638831878">"Ayikwazi ukubonisa i-PDF (i-<xliff:g id="TITLE">%1$s</xliff:g> ingeyefomethi engavumelekile)"</string>
diff --git a/pdf/pdf-viewer/src/main/res/values/dimensions.xml b/pdf/pdf-viewer/src/main/res/values/dimensions.xml
index ab5c220..34b4179 100644
--- a/pdf/pdf-viewer/src/main/res/values/dimensions.xml
+++ b/pdf/pdf-viewer/src/main/res/values/dimensions.xml
@@ -26,4 +26,7 @@
     <!--Find in file button size -->
     <dimen name="find_in_file_button_size">48dp</dimen>
 
+    <dimen name="text_select_handle_touch_size">48dp</dimen>
+    <dimen name="pdf_horizontal_padding">0dp</dimen>
+
 </resources>
diff --git a/pdf/pdf-viewer/src/main/res/values/strings.xml b/pdf/pdf-viewer/src/main/res/values/strings.xml
index 06d82b9..24706b5 100644
--- a/pdf/pdf-viewer/src/main/res/values/strings.xml
+++ b/pdf/pdf-viewer/src/main/res/values/strings.xml
@@ -157,4 +157,8 @@
 
     <!-- Error Message on PDF File Load Error -->
     <string name="error_cannot_open_pdf">Can\'t open PDF file</string>
+
+    <!-- User visible label attached to text copied from a PDF when submitting it to the system
+         clipboard -->
+    <string name="clipboard_label">Content copied from PDF</string>
 </resources>
diff --git a/pdf/pdf-viewer/src/test/kotlin/androidx/pdf/view/SelectionStateManagerTest.kt b/pdf/pdf-viewer/src/test/kotlin/androidx/pdf/view/SelectionStateManagerTest.kt
index 63d5c25..b1f4dd3 100644
--- a/pdf/pdf-viewer/src/test/kotlin/androidx/pdf/view/SelectionStateManagerTest.kt
+++ b/pdf/pdf-viewer/src/test/kotlin/androidx/pdf/view/SelectionStateManagerTest.kt
@@ -19,6 +19,8 @@
 import android.graphics.Point
 import android.graphics.PointF
 import android.graphics.RectF
+import android.view.HapticFeedbackConstants
+import android.view.MotionEvent
 import androidx.pdf.PdfDocument
 import androidx.pdf.content.PageSelection
 import androidx.pdf.content.PdfPageTextContent
@@ -57,20 +59,41 @@
                 }
         }
 
+    /** It's simpler to set the selection manually for tests concerning the draggable handles */
+    private val initialSelectionForDragging =
+        SelectionModel(
+            TextSelection(
+                "This is the text that's selected",
+                listOf(
+                    PdfRect(pageNum = 0, RectF(150F, 150F, 190F, 160F)),
+                    PdfRect(pageNum = 0, RectF(10F, 170F, 50F, 180F)),
+                )
+            ),
+            startBoundary =
+                UiSelectionBoundary(PdfPoint(pageNum = 0, PointF(150F, 160F)), isRtl = true),
+            endBoundary =
+                UiSelectionBoundary(PdfPoint(pageNum = 0, PointF(50F, 180F)), isRtl = true),
+        )
+
     private lateinit var selectionStateManager: SelectionStateManager
 
     @Before
     fun setup() {
-        selectionStateManager = SelectionStateManager(pdfDocument, testScope)
+        selectionStateManager =
+            SelectionStateManager(
+                pdfDocument,
+                testScope,
+                handleTouchTargetSizePx = HANDLE_TOUCH_TARGET_PX
+            )
     }
 
     @OptIn(ExperimentalCoroutinesApi::class)
     @Test
     fun maybeSelectWordAtPoint() = runTest {
         val selectionPoint = PdfPoint(pageNum = 10, PointF(150F, 265F))
-        val invalidations = mutableListOf<Unit>()
+        val uiSignals = mutableListOf<SelectionUiSignal>()
         backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
-            selectionStateManager.invalidationSignalFlow.toList(invalidations)
+            selectionStateManager.selectionUiSignalBus.toList(uiSignals)
         }
 
         selectionStateManager.maybeSelectWordAtPoint(selectionPoint)
@@ -99,7 +122,19 @@
                 "This is all the text between ${selectionPoint.pagePoint} and ${selectionPoint.pagePoint}"
             )
 
-        assertThat(invalidations.size).isEqualTo(1)
+        assertThat(uiSignals.size).isEqualTo(4)
+        // hide action mode
+        assertThat(uiSignals[0]).isInstanceOf(SelectionUiSignal.ToggleActionMode::class.java)
+        assertThat((uiSignals[0] as SelectionUiSignal.ToggleActionMode).show).isFalse()
+        // play long press haptic feedback
+        assertThat(uiSignals[1]).isInstanceOf(SelectionUiSignal.PlayHapticFeedback::class.java)
+        assertThat((uiSignals[1] as SelectionUiSignal.PlayHapticFeedback).level)
+            .isEqualTo(HapticFeedbackConstants.LONG_PRESS)
+        // invalidate
+        assertThat(uiSignals[2]).isInstanceOf(SelectionUiSignal.Invalidate::class.java)
+        // show action mode
+        assertThat(uiSignals[3]).isInstanceOf(SelectionUiSignal.ToggleActionMode::class.java)
+        assertThat((uiSignals[3] as SelectionUiSignal.ToggleActionMode).show).isTrue()
     }
 
     @Test
@@ -139,9 +174,9 @@
     @Test
     fun clearSelection() = runTest {
         val selectionPoint = PdfPoint(pageNum = 10, PointF(150F, 265F))
-        val invalidations = mutableListOf<Unit>()
+        val uiSignals = mutableListOf<SelectionUiSignal>()
         backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
-            selectionStateManager.invalidationSignalFlow.toList(invalidations)
+            selectionStateManager.selectionUiSignalBus.toList(uiSignals)
         }
 
         selectionStateManager.maybeSelectWordAtPoint(selectionPoint)
@@ -150,8 +185,14 @@
         selectionStateManager.clearSelection()
 
         assertThat(selectionStateManager.selectionModel).isNull()
-        // One for the selection, one for clearing it
-        assertThat(invalidations.size).isEqualTo(2)
+        // We only care about the final 2 signals that should occur as a result of cancellation
+        // hide action mode
+        assertThat(uiSignals[uiSignals.size - 2])
+            .isInstanceOf(SelectionUiSignal.ToggleActionMode::class.java)
+        assertThat((uiSignals[uiSignals.size - 2] as SelectionUiSignal.ToggleActionMode).show)
+            .isFalse()
+        // invalidate
+        assertThat(uiSignals.last()).isInstanceOf(SelectionUiSignal.Invalidate::class.java)
     }
 
     @Test
@@ -169,6 +210,213 @@
         assertThat(selectionStateManager.selectionModel).isNull()
     }
 
+    @Test
+    fun maybeDragHandle_actionDownOutsideHandle_returnFalse() {
+        selectionStateManager.selectionModel = initialSelectionForDragging
+
+        assertThat(
+                selectionStateManager.maybeDragSelectionHandle(
+                    MotionEvent.ACTION_DOWN,
+                    PdfPoint(pageNum = 0, PointF(0F, 0F)),
+                    currentZoom = 2.0F
+                )
+            )
+            .isFalse()
+    }
+
+    @Test
+    fun maybeDragHandle_actionDownInsideStartHandle_returnTrue() {
+        selectionStateManager.selectionModel = initialSelectionForDragging
+        // Chose a point inside the start handle touch target (below and behind the start position)
+        val insideStartHandle =
+            PointF(initialSelectionForDragging.startBoundary.location.pagePoint).apply {
+                offset(-HANDLE_TOUCH_TARGET_PX / 4.0F, HANDLE_TOUCH_TARGET_PX / 4.0F)
+            }
+
+        // "Grab" the start handle and make sure we handle the event
+        assertThat(
+                selectionStateManager.maybeDragSelectionHandle(
+                    MotionEvent.ACTION_DOWN,
+                    PdfPoint(pageNum = 0, insideStartHandle),
+                    currentZoom = 2.0F
+                )
+            )
+            .isTrue()
+    }
+
+    @Test
+    fun maybeDragHandle_actionDownInsideEndHandle_returnTrue() {
+        selectionStateManager.selectionModel = initialSelectionForDragging
+        // Chose a point inside the end handle touch target (below and ahead the end position)
+        val insideEndHandle =
+            PointF(initialSelectionForDragging.endBoundary.location.pagePoint).apply {
+                offset(HANDLE_TOUCH_TARGET_PX / 4.0F, HANDLE_TOUCH_TARGET_PX / 4.0F)
+            }
+
+        // "Grab" the end handle and make sure we handle the event
+        assertThat(
+                selectionStateManager.maybeDragSelectionHandle(
+                    MotionEvent.ACTION_DOWN,
+                    PdfPoint(pageNum = 0, insideEndHandle),
+                    currentZoom = 2.0F
+                )
+            )
+            .isTrue()
+    }
+
+    @Test
+    fun maybeDragHandle_actionMove_updateSelection() {
+        selectionStateManager.selectionModel = initialSelectionForDragging
+        // "Grab" the start handle
+        val insideStartHandle =
+            PointF(initialSelectionForDragging.startBoundary.location.pagePoint).apply {
+                offset(-HANDLE_TOUCH_TARGET_PX / 4.0F, HANDLE_TOUCH_TARGET_PX / 4.0F)
+            }
+        assertThat(
+                selectionStateManager.maybeDragSelectionHandle(
+                    MotionEvent.ACTION_DOWN,
+                    PdfPoint(pageNum = 0, insideStartHandle),
+                    currentZoom = 2.0F
+                )
+            )
+            .isTrue()
+
+        // Drag the start handle by 5px in both x and y
+        val newStartPosition =
+            PointF(insideStartHandle).apply { offset(/* dx= */ 5F, /* dy= */ 5F) }
+        assertThat(
+                selectionStateManager.maybeDragSelectionHandle(
+                    MotionEvent.ACTION_MOVE,
+                    PdfPoint(pageNum = 0, newStartPosition),
+                    currentZoom = 2.0F
+                )
+            )
+            .isTrue()
+
+        // Make sure the selection is updated appropriately
+        testDispatcher.scheduler.runCurrent()
+        val selection = selectionStateManager.selectionModel?.selection
+        assertThat(selection).isInstanceOf(TextSelection::class.java)
+        val expectedStartLoc = initialSelectionForDragging.endBoundary.location.pagePoint
+        val expectedEndLoc =
+            PointF(initialSelectionForDragging.startBoundary.location.pagePoint).apply {
+                offset(/* dx= */ 5F, /* dy= */ 5F)
+            }
+        assertThat((selection as TextSelection).text)
+            .isEqualTo("This is all the text between $expectedStartLoc and $expectedEndLoc")
+    }
+
+    @Test
+    fun maybeDragHandle_actionMoveOutsidePage_returnTrue() {
+        selectionStateManager.selectionModel = initialSelectionForDragging
+        // "Grab" the start handle
+        val insideStartHandle =
+            PointF(initialSelectionForDragging.startBoundary.location.pagePoint).apply {
+                offset(-HANDLE_TOUCH_TARGET_PX / 4.0F, HANDLE_TOUCH_TARGET_PX / 4.0F)
+            }
+        assertThat(
+                selectionStateManager.maybeDragSelectionHandle(
+                    MotionEvent.ACTION_DOWN,
+                    PdfPoint(pageNum = 0, insideStartHandle),
+                    currentZoom = 2.0F
+                )
+            )
+            .isTrue()
+
+        // Drag the handle to a location outside any page (location = null), and make sure we still
+        // "capture" the event
+        assertThat(
+                selectionStateManager.maybeDragSelectionHandle(
+                    MotionEvent.ACTION_MOVE,
+                    location = null,
+                    currentZoom = 2.0F
+                )
+            )
+            .isTrue()
+    }
+
+    @Test
+    fun maybeDragHandle_actionMoveWithoutActionDown_returnFalse() {
+        selectionStateManager.selectionModel = initialSelectionForDragging
+        // Chose a point inside the start handle touch target (below and behind the start position)
+        val insideStartHandle =
+            PointF(initialSelectionForDragging.startBoundary.location.pagePoint).apply {
+                offset(-HANDLE_TOUCH_TARGET_PX / 4.0F, HANDLE_TOUCH_TARGET_PX / 4.0F)
+            }
+
+        // Make sure we don't handle an ACTION_MOVE without an initial ACTION_DOWN, even when the
+        // move event occurs within one of the drag handles
+        assertThat(
+                selectionStateManager.maybeDragSelectionHandle(
+                    MotionEvent.ACTION_MOVE,
+                    PdfPoint(pageNum = 0, insideStartHandle),
+                    currentZoom = 2.0F
+                )
+            )
+            .isFalse()
+    }
+
+    @Test
+    fun maybeDragHandle_actionUpWithoutActionDown_returnFalse() {
+        selectionStateManager.selectionModel = initialSelectionForDragging
+        // Chose a point inside the start handle touch target (below and behind the start position)
+        val insideStartHandle =
+            PointF(initialSelectionForDragging.startBoundary.location.pagePoint).apply {
+                offset(-HANDLE_TOUCH_TARGET_PX / 4.0F, HANDLE_TOUCH_TARGET_PX / 4.0F)
+            }
+
+        // Make sure we don't handle an ACTION_UP without an initial ACTION_DOWN, even when the
+        // up event occurs within one of the drag handles
+        assertThat(
+                selectionStateManager.maybeDragSelectionHandle(
+                    MotionEvent.ACTION_UP,
+                    PdfPoint(pageNum = 0, insideStartHandle),
+                    currentZoom = 2.0F
+                )
+            )
+            .isFalse()
+    }
+
+    @Test
+    fun maybeDragHandle_actionUp_returnTrueAndStopHandlingEvents() {
+        selectionStateManager.selectionModel = initialSelectionForDragging
+        // Chose a point inside the start handle touch target (below and behind the start position)
+        val insideStartHandle =
+            PointF(initialSelectionForDragging.startBoundary.location.pagePoint).apply {
+                offset(-HANDLE_TOUCH_TARGET_PX / 4.0F, HANDLE_TOUCH_TARGET_PX / 4.0F)
+            }
+
+        // "Grab" the start handle
+        assertThat(
+                selectionStateManager.maybeDragSelectionHandle(
+                    MotionEvent.ACTION_DOWN,
+                    PdfPoint(pageNum = 0, insideStartHandle),
+                    currentZoom = 2.0F
+                )
+            )
+            .isTrue()
+
+        // "Release" the start handle, and make sure we handle the event
+        assertThat(
+                selectionStateManager.maybeDragSelectionHandle(
+                    MotionEvent.ACTION_UP,
+                    PdfPoint(pageNum = 0, insideStartHandle),
+                    currentZoom = 2.0F
+                )
+            )
+            .isTrue()
+
+        // Make sure we don't handle an ACTION_MOVE after releasing the gesture
+        assertThat(
+                selectionStateManager.maybeDragSelectionHandle(
+                    MotionEvent.ACTION_MOVE,
+                    PdfPoint(pageNum = 0, insideStartHandle),
+                    currentZoom = 2.0F
+                )
+            )
+            .isFalse()
+    }
+
     private fun pageSelectionFor(page: Int, start: PointF, end: PointF): PageSelection {
         return PageSelection(
             page,
@@ -190,3 +438,5 @@
         )
     }
 }
+
+private const val HANDLE_TOUCH_TARGET_PX = 48
diff --git a/performance/performance-annotation/api/current.txt b/performance/performance-annotation/api/current.txt
new file mode 100644
index 0000000..06dbdba
--- /dev/null
+++ b/performance/performance-annotation/api/current.txt
@@ -0,0 +1,8 @@
+// Signature format: 4.0
+package dalvik.annotation.optimization {
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CONSTRUCTOR, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface NeverInline {
+  }
+
+}
+
diff --git a/appfunctions/appfunctions-agent-runtime/api/res-current.txt b/performance/performance-annotation/api/res-current.txt
similarity index 100%
copy from appfunctions/appfunctions-agent-runtime/api/res-current.txt
copy to performance/performance-annotation/api/res-current.txt
diff --git a/performance/performance-annotation/api/restricted_current.txt b/performance/performance-annotation/api/restricted_current.txt
new file mode 100644
index 0000000..06dbdba
--- /dev/null
+++ b/performance/performance-annotation/api/restricted_current.txt
@@ -0,0 +1,8 @@
+// Signature format: 4.0
+package dalvik.annotation.optimization {
+
+  @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CONSTRUCTOR, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface NeverInline {
+  }
+
+}
+
diff --git a/performance/performance-annotation/bcv/native/current.txt b/performance/performance-annotation/bcv/native/current.txt
new file mode 100644
index 0000000..8e4fa01
--- /dev/null
+++ b/performance/performance-annotation/bcv/native/current.txt
@@ -0,0 +1,11 @@
+// Klib ABI Dump
+// Targets: [iosArm64, iosSimulatorArm64, iosX64, linuxArm64, linuxX64, macosArm64, macosX64, mingwX64, tvosArm64, tvosSimulatorArm64, tvosX64, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64, watchosX64]
+// Rendering settings:
+// - Signature version: 2
+// - Show manifest properties: true
+// - Show declarations: true
+
+// Library unique name: <androidx.performance:performance-annotation>
+open annotation class dalvik.annotation.optimization/NeverInline : kotlin/Annotation { // dalvik.annotation.optimization/NeverInline|null[1]
+    constructor <init>() // dalvik.annotation.optimization/NeverInline.<init>|<init>(){}[1]
+}
diff --git a/performance/performance-annotation/build.gradle b/performance/performance-annotation/build.gradle
index 36a6772..e03e5bf 100644
--- a/performance/performance-annotation/build.gradle
+++ b/performance/performance-annotation/build.gradle
@@ -61,7 +61,7 @@
 
 androidx {
     name = "Performance - Annotation"
-    type = LibraryType.UNSET
+    type = LibraryType.PUBLISHED_LIBRARY
     inceptionYear = "2024"
     description = "Provides source annotations for performance optimizations."
     kotlinTarget = KotlinTarget.KOTLIN_1_9
diff --git a/performance/performance-unsafe/api/api_lint.ignore b/performance/performance-unsafe/api/api_lint.ignore
new file mode 100644
index 0000000..8d44e3d
--- /dev/null
+++ b/performance/performance-unsafe/api/api_lint.ignore
@@ -0,0 +1,127 @@
+// Baseline format: 1.0
+MissingNullability: sun.misc.Unsafe#allocateInstance(Class<?>):
+    Missing nullability on method `allocateInstance` return
+MissingNullability: sun.misc.Unsafe#allocateInstance(Class<?>) parameter #0:
+    Missing nullability on parameter `c` in method `allocateInstance`
+MissingNullability: sun.misc.Unsafe#arrayBaseOffset(Class<?>) parameter #0:
+    Missing nullability on parameter `clazz` in method `arrayBaseOffset`
+MissingNullability: sun.misc.Unsafe#arrayIndexScale(Class<?>) parameter #0:
+    Missing nullability on parameter `clazz` in method `arrayIndexScale`
+MissingNullability: sun.misc.Unsafe#compareAndSwapInt(Object, long, int, int) parameter #0:
+    Missing nullability on parameter `obj` in method `compareAndSwapInt`
+MissingNullability: sun.misc.Unsafe#compareAndSwapLong(Object, long, long, long) parameter #0:
+    Missing nullability on parameter `obj` in method `compareAndSwapLong`
+MissingNullability: sun.misc.Unsafe#compareAndSwapObject(Object, long, Object, Object) parameter #0:
+    Missing nullability on parameter `obj` in method `compareAndSwapObject`
+MissingNullability: sun.misc.Unsafe#compareAndSwapObject(Object, long, Object, Object) parameter #2:
+    Missing nullability on parameter `expectedValue` in method `compareAndSwapObject`
+MissingNullability: sun.misc.Unsafe#compareAndSwapObject(Object, long, Object, Object) parameter #3:
+    Missing nullability on parameter `newValue` in method `compareAndSwapObject`
+MissingNullability: sun.misc.Unsafe#copyMemoryFromPrimitiveArray(Object, long, long, long) parameter #0:
+    Missing nullability on parameter `src` in method `copyMemoryFromPrimitiveArray`
+MissingNullability: sun.misc.Unsafe#copyMemoryToPrimitiveArray(long, Object, long, long) parameter #1:
+    Missing nullability on parameter `dst` in method `copyMemoryToPrimitiveArray`
+MissingNullability: sun.misc.Unsafe#getAndAddInt(Object, long, int) parameter #0:
+    Missing nullability on parameter `o` in method `getAndAddInt`
+MissingNullability: sun.misc.Unsafe#getAndAddLong(Object, long, long) parameter #0:
+    Missing nullability on parameter `o` in method `getAndAddLong`
+MissingNullability: sun.misc.Unsafe#getAndSetInt(Object, long, int) parameter #0:
+    Missing nullability on parameter `o` in method `getAndSetInt`
+MissingNullability: sun.misc.Unsafe#getAndSetLong(Object, long, long) parameter #0:
+    Missing nullability on parameter `o` in method `getAndSetLong`
+MissingNullability: sun.misc.Unsafe#getAndSetObject(Object, long, Object):
+    Missing nullability on method `getAndSetObject` return
+MissingNullability: sun.misc.Unsafe#getAndSetObject(Object, long, Object) parameter #0:
+    Missing nullability on parameter `o` in method `getAndSetObject`
+MissingNullability: sun.misc.Unsafe#getAndSetObject(Object, long, Object) parameter #2:
+    Missing nullability on parameter `newValue` in method `getAndSetObject`
+MissingNullability: sun.misc.Unsafe#getBoolean(Object, long) parameter #0:
+    Missing nullability on parameter `obj` in method `getBoolean`
+MissingNullability: sun.misc.Unsafe#getByte(Object, long) parameter #0:
+    Missing nullability on parameter `obj` in method `getByte`
+MissingNullability: sun.misc.Unsafe#getChar(Object, long) parameter #0:
+    Missing nullability on parameter `obj` in method `getChar`
+MissingNullability: sun.misc.Unsafe#getDouble(Object, long) parameter #0:
+    Missing nullability on parameter `obj` in method `getDouble`
+MissingNullability: sun.misc.Unsafe#getFloat(Object, long) parameter #0:
+    Missing nullability on parameter `obj` in method `getFloat`
+MissingNullability: sun.misc.Unsafe#getInt(Object, long) parameter #0:
+    Missing nullability on parameter `obj` in method `getInt`
+MissingNullability: sun.misc.Unsafe#getIntVolatile(Object, long) parameter #0:
+    Missing nullability on parameter `obj` in method `getIntVolatile`
+MissingNullability: sun.misc.Unsafe#getLong(Object, long) parameter #0:
+    Missing nullability on parameter `obj` in method `getLong`
+MissingNullability: sun.misc.Unsafe#getLongVolatile(Object, long) parameter #0:
+    Missing nullability on parameter `obj` in method `getLongVolatile`
+MissingNullability: sun.misc.Unsafe#getObject(Object, long):
+    Missing nullability on method `getObject` return
+MissingNullability: sun.misc.Unsafe#getObject(Object, long) parameter #0:
+    Missing nullability on parameter `obj` in method `getObject`
+MissingNullability: sun.misc.Unsafe#getObjectVolatile(Object, long):
+    Missing nullability on method `getObjectVolatile` return
+MissingNullability: sun.misc.Unsafe#getObjectVolatile(Object, long) parameter #0:
+    Missing nullability on parameter `obj` in method `getObjectVolatile`
+MissingNullability: sun.misc.Unsafe#getShort(Object, long) parameter #0:
+    Missing nullability on parameter `obj` in method `getShort`
+MissingNullability: sun.misc.Unsafe#getUnsafe():
+    Missing nullability on method `getUnsafe` return
+MissingNullability: sun.misc.Unsafe#objectFieldOffset(java.lang.reflect.Field) parameter #0:
+    Missing nullability on parameter `field` in method `objectFieldOffset`
+MissingNullability: sun.misc.Unsafe#putBoolean(Object, long, boolean) parameter #0:
+    Missing nullability on parameter `obj` in method `putBoolean`
+MissingNullability: sun.misc.Unsafe#putByte(Object, long, byte) parameter #0:
+    Missing nullability on parameter `obj` in method `putByte`
+MissingNullability: sun.misc.Unsafe#putChar(Object, long, char) parameter #0:
+    Missing nullability on parameter `obj` in method `putChar`
+MissingNullability: sun.misc.Unsafe#putDouble(Object, long, double) parameter #0:
+    Missing nullability on parameter `obj` in method `putDouble`
+MissingNullability: sun.misc.Unsafe#putFloat(Object, long, float) parameter #0:
+    Missing nullability on parameter `obj` in method `putFloat`
+MissingNullability: sun.misc.Unsafe#putInt(Object, long, int) parameter #0:
+    Missing nullability on parameter `obj` in method `putInt`
+MissingNullability: sun.misc.Unsafe#putIntVolatile(Object, long, int) parameter #0:
+    Missing nullability on parameter `obj` in method `putIntVolatile`
+MissingNullability: sun.misc.Unsafe#putLong(Object, long, long) parameter #0:
+    Missing nullability on parameter `obj` in method `putLong`
+MissingNullability: sun.misc.Unsafe#putLongVolatile(Object, long, long) parameter #0:
+    Missing nullability on parameter `obj` in method `putLongVolatile`
+MissingNullability: sun.misc.Unsafe#putObject(Object, long, Object) parameter #0:
+    Missing nullability on parameter `obj` in method `putObject`
+MissingNullability: sun.misc.Unsafe#putObject(Object, long, Object) parameter #2:
+    Missing nullability on parameter `newValue` in method `putObject`
+MissingNullability: sun.misc.Unsafe#putObjectVolatile(Object, long, Object) parameter #0:
+    Missing nullability on parameter `obj` in method `putObjectVolatile`
+MissingNullability: sun.misc.Unsafe#putObjectVolatile(Object, long, Object) parameter #2:
+    Missing nullability on parameter `newValue` in method `putObjectVolatile`
+MissingNullability: sun.misc.Unsafe#putOrderedInt(Object, long, int) parameter #0:
+    Missing nullability on parameter `obj` in method `putOrderedInt`
+MissingNullability: sun.misc.Unsafe#putOrderedLong(Object, long, long) parameter #0:
+    Missing nullability on parameter `obj` in method `putOrderedLong`
+MissingNullability: sun.misc.Unsafe#putOrderedObject(Object, long, Object) parameter #0:
+    Missing nullability on parameter `obj` in method `putOrderedObject`
+MissingNullability: sun.misc.Unsafe#putOrderedObject(Object, long, Object) parameter #2:
+    Missing nullability on parameter `newValue` in method `putOrderedObject`
+MissingNullability: sun.misc.Unsafe#putShort(Object, long, short) parameter #0:
+    Missing nullability on parameter `obj` in method `putShort`
+MissingNullability: sun.misc.Unsafe#unpark(Object) parameter #0:
+    Missing nullability on parameter `obj` in method `unpark`
+
+
+NoByteOrShort: sun.misc.Unsafe#getByte(Object, long):
+    Should avoid odd sized primitives; use `int` instead of `byte` in method sun.misc.Unsafe.getByte(Object,long)
+NoByteOrShort: sun.misc.Unsafe#getByte(long):
+    Should avoid odd sized primitives; use `int` instead of `byte` in method sun.misc.Unsafe.getByte(long)
+NoByteOrShort: sun.misc.Unsafe#getShort(Object, long):
+    Should avoid odd sized primitives; use `int` instead of `short` in method sun.misc.Unsafe.getShort(Object,long)
+NoByteOrShort: sun.misc.Unsafe#getShort(long):
+    Should avoid odd sized primitives; use `int` instead of `short` in method sun.misc.Unsafe.getShort(long)
+NoByteOrShort: sun.misc.Unsafe#putByte(Object, long, byte) parameter #2:
+    Should avoid odd sized primitives; use `int` instead of `byte` in parameter newValue in sun.misc.Unsafe.putByte(Object obj, long offset, byte newValue)
+NoByteOrShort: sun.misc.Unsafe#putByte(long, byte) parameter #1:
+    Should avoid odd sized primitives; use `int` instead of `byte` in parameter x in sun.misc.Unsafe.putByte(long address, byte x)
+NoByteOrShort: sun.misc.Unsafe#putShort(Object, long, short) parameter #2:
+    Should avoid odd sized primitives; use `int` instead of `short` in parameter newValue in sun.misc.Unsafe.putShort(Object obj, long offset, short newValue)
+NoByteOrShort: sun.misc.Unsafe#putShort(long, short) parameter #1:
+    Should avoid odd sized primitives; use `int` instead of `short` in parameter x in sun.misc.Unsafe.putShort(long address, short x)
+NoByteOrShort: sun.misc.Unsafe#setMemory(long, long, byte) parameter #2:
+    Should avoid odd sized primitives; use `int` instead of `byte` in parameter value in sun.misc.Unsafe.setMemory(long address, long bytes, byte value)
diff --git a/performance/performance-unsafe/api/current.txt b/performance/performance-unsafe/api/current.txt
new file mode 100644
index 0000000..ecc05bb
--- /dev/null
+++ b/performance/performance-unsafe/api/current.txt
@@ -0,0 +1,76 @@
+// Signature format: 4.0
+package sun.misc {
+
+  public final class Unsafe {
+    method public int addressSize();
+    method public Object! allocateInstance(Class<? extends java.lang.Object!>!);
+    method public long allocateMemory(long);
+    method public int arrayBaseOffset(Class<? extends java.lang.Object!>!);
+    method public int arrayIndexScale(Class<? extends java.lang.Object!>!);
+    method public boolean compareAndSwapInt(Object!, long, int, int);
+    method public boolean compareAndSwapLong(Object!, long, long, long);
+    method public boolean compareAndSwapObject(Object!, long, Object!, Object!);
+    method public void copyMemory(long, long, long);
+    method public void copyMemoryFromPrimitiveArray(Object!, long, long, long);
+    method public void copyMemoryToPrimitiveArray(long, Object!, long, long);
+    method public void freeMemory(long);
+    method public void fullFence();
+    method public int getAndAddInt(Object!, long, int);
+    method public long getAndAddLong(Object!, long, long);
+    method public int getAndSetInt(Object!, long, int);
+    method public long getAndSetLong(Object!, long, long);
+    method public Object! getAndSetObject(Object!, long, Object!);
+    method public boolean getBoolean(Object!, long);
+    method public byte getByte(Object!, long);
+    method public byte getByte(long);
+    method public char getChar(Object!, long);
+    method public char getChar(long);
+    method public double getDouble(Object!, long);
+    method public double getDouble(long);
+    method public float getFloat(Object!, long);
+    method public float getFloat(long);
+    method public int getInt(Object!, long);
+    method public int getInt(long);
+    method public int getIntVolatile(Object!, long);
+    method public long getLong(Object!, long);
+    method public long getLong(long);
+    method public long getLongVolatile(Object!, long);
+    method public Object! getObject(Object!, long);
+    method public Object! getObjectVolatile(Object!, long);
+    method public short getShort(Object!, long);
+    method public short getShort(long);
+    method public static sun.misc.Unsafe! getUnsafe();
+    method public void loadFence();
+    method public long objectFieldOffset(java.lang.reflect.Field!);
+    method public int pageSize();
+    method public void park(boolean, long);
+    method public void putBoolean(Object!, long, boolean);
+    method public void putByte(Object!, long, byte);
+    method public void putByte(long, byte);
+    method public void putChar(Object!, long, char);
+    method public void putChar(long, char);
+    method public void putDouble(Object!, long, double);
+    method public void putDouble(long, double);
+    method public void putFloat(Object!, long, float);
+    method public void putFloat(long, float);
+    method public void putInt(Object!, long, int);
+    method public void putInt(long, int);
+    method public void putIntVolatile(Object!, long, int);
+    method public void putLong(Object!, long, long);
+    method public void putLong(long, long);
+    method public void putLongVolatile(Object!, long, long);
+    method public void putObject(Object!, long, Object!);
+    method public void putObjectVolatile(Object!, long, Object!);
+    method public void putOrderedInt(Object!, long, int);
+    method public void putOrderedLong(Object!, long, long);
+    method public void putOrderedObject(Object!, long, Object!);
+    method public void putShort(Object!, long, short);
+    method public void putShort(long, short);
+    method public void setMemory(long, long, byte);
+    method public void storeFence();
+    method public void unpark(Object!);
+    field public static final int INVALID_FIELD_OFFSET = -1; // 0xffffffff
+  }
+
+}
+
diff --git a/performance/performance-unsafe/api/restricted_current.txt b/performance/performance-unsafe/api/restricted_current.txt
new file mode 100644
index 0000000..ecc05bb
--- /dev/null
+++ b/performance/performance-unsafe/api/restricted_current.txt
@@ -0,0 +1,76 @@
+// Signature format: 4.0
+package sun.misc {
+
+  public final class Unsafe {
+    method public int addressSize();
+    method public Object! allocateInstance(Class<? extends java.lang.Object!>!);
+    method public long allocateMemory(long);
+    method public int arrayBaseOffset(Class<? extends java.lang.Object!>!);
+    method public int arrayIndexScale(Class<? extends java.lang.Object!>!);
+    method public boolean compareAndSwapInt(Object!, long, int, int);
+    method public boolean compareAndSwapLong(Object!, long, long, long);
+    method public boolean compareAndSwapObject(Object!, long, Object!, Object!);
+    method public void copyMemory(long, long, long);
+    method public void copyMemoryFromPrimitiveArray(Object!, long, long, long);
+    method public void copyMemoryToPrimitiveArray(long, Object!, long, long);
+    method public void freeMemory(long);
+    method public void fullFence();
+    method public int getAndAddInt(Object!, long, int);
+    method public long getAndAddLong(Object!, long, long);
+    method public int getAndSetInt(Object!, long, int);
+    method public long getAndSetLong(Object!, long, long);
+    method public Object! getAndSetObject(Object!, long, Object!);
+    method public boolean getBoolean(Object!, long);
+    method public byte getByte(Object!, long);
+    method public byte getByte(long);
+    method public char getChar(Object!, long);
+    method public char getChar(long);
+    method public double getDouble(Object!, long);
+    method public double getDouble(long);
+    method public float getFloat(Object!, long);
+    method public float getFloat(long);
+    method public int getInt(Object!, long);
+    method public int getInt(long);
+    method public int getIntVolatile(Object!, long);
+    method public long getLong(Object!, long);
+    method public long getLong(long);
+    method public long getLongVolatile(Object!, long);
+    method public Object! getObject(Object!, long);
+    method public Object! getObjectVolatile(Object!, long);
+    method public short getShort(Object!, long);
+    method public short getShort(long);
+    method public static sun.misc.Unsafe! getUnsafe();
+    method public void loadFence();
+    method public long objectFieldOffset(java.lang.reflect.Field!);
+    method public int pageSize();
+    method public void park(boolean, long);
+    method public void putBoolean(Object!, long, boolean);
+    method public void putByte(Object!, long, byte);
+    method public void putByte(long, byte);
+    method public void putChar(Object!, long, char);
+    method public void putChar(long, char);
+    method public void putDouble(Object!, long, double);
+    method public void putDouble(long, double);
+    method public void putFloat(Object!, long, float);
+    method public void putFloat(long, float);
+    method public void putInt(Object!, long, int);
+    method public void putInt(long, int);
+    method public void putIntVolatile(Object!, long, int);
+    method public void putLong(Object!, long, long);
+    method public void putLong(long, long);
+    method public void putLongVolatile(Object!, long, long);
+    method public void putObject(Object!, long, Object!);
+    method public void putObjectVolatile(Object!, long, Object!);
+    method public void putOrderedInt(Object!, long, int);
+    method public void putOrderedLong(Object!, long, long);
+    method public void putOrderedObject(Object!, long, Object!);
+    method public void putShort(Object!, long, short);
+    method public void putShort(long, short);
+    method public void setMemory(long, long, byte);
+    method public void storeFence();
+    method public void unpark(Object!);
+    field public static final int INVALID_FIELD_OFFSET = -1; // 0xffffffff
+  }
+
+}
+
diff --git a/performance/performance-unsafe/build.gradle b/performance/performance-unsafe/build.gradle
index 332949a..152abd0 100644
--- a/performance/performance-unsafe/build.gradle
+++ b/performance/performance-unsafe/build.gradle
@@ -28,7 +28,7 @@
 
 androidx {
     name = "Performance - Unsafe"
-    type = LibraryType.UNSET
+    type = LibraryType.PUBLISHED_LIBRARY
     inceptionYear = "2024"
     description = "Compile-time support for sun.misc.Unsafe."
 }
diff --git a/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundExtension.kt b/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundExtension.kt
index d9041e8..e84121de 100644
--- a/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundExtension.kt
+++ b/playground-common/playground-plugin/src/main/kotlin/androidx/playground/PlaygroundExtension.kt
@@ -251,6 +251,7 @@
         private val REQUIRED_PROJECTS = listOf(":lint-checks")
         private val UNSUPPORTED_PROJECTS = listOf(
             ":benchmark:benchmark-common", // requires prebuilts
+            ":benchmark:benchmark-traceprocessor", // requires prebuilts
             ":inspection:inspection", // native compilation
         )
     }
diff --git a/playground-common/playground.properties b/playground-common/playground.properties
index e5e5601..5794818 100644
--- a/playground-common/playground.properties
+++ b/playground-common/playground.properties
@@ -26,5 +26,5 @@
 # Disable docs
 androidx.enableDocumentation=false
 androidx.playground.snapshotBuildId=12482018
-androidx.playground.metalavaBuildId=12685367
-androidx.studio.type=playground
+androidx.playground.metalavaBuildId=12892968
+androidx.studio.type=playground
\ No newline at end of file
diff --git a/privacysandbox/tools/tools-apigenerator/src/main/java/androidx/privacysandbox/tools/apigenerator/PrivacySandboxApiGenerator.kt b/privacysandbox/tools/tools-apigenerator/src/main/java/androidx/privacysandbox/tools/apigenerator/PrivacySandboxApiGenerator.kt
index 0876d1f..e1d6c35 100644
--- a/privacysandbox/tools/tools-apigenerator/src/main/java/androidx/privacysandbox/tools/apigenerator/PrivacySandboxApiGenerator.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/main/java/androidx/privacysandbox/tools/apigenerator/PrivacySandboxApiGenerator.kt
@@ -38,8 +38,8 @@
 import androidx.privacysandbox.tools.core.model.containsSdkActivityLauncher
 import androidx.privacysandbox.tools.core.model.getOnlyService
 import androidx.privacysandbox.tools.core.model.hasSuspendFunctions
+import androidx.privacysandbox.tools.core.proto.InvalidProtocolBufferException
 import androidx.privacysandbox.tools.core.proto.PrivacySandboxToolsProtocol.ToolMetadata
-import com.google.protobuf.InvalidProtocolBufferException
 import java.io.File
 import java.nio.file.Path
 import java.util.zip.ZipInputStream
diff --git a/appfunctions/appfunctions-agent-runtime/api/current.txt b/privacysandbox/tools/tools-core-external-protobuf/api/current.txt
similarity index 100%
copy from appfunctions/appfunctions-agent-runtime/api/current.txt
copy to privacysandbox/tools/tools-core-external-protobuf/api/current.txt
diff --git a/appfunctions/appfunctions-agent-runtime/api/restricted_current.txt b/privacysandbox/tools/tools-core-external-protobuf/api/restricted_current.txt
similarity index 100%
rename from appfunctions/appfunctions-agent-runtime/api/restricted_current.txt
rename to privacysandbox/tools/tools-core-external-protobuf/api/restricted_current.txt
diff --git a/appfunctions/appfunctions-agent-runtime/build.gradle b/privacysandbox/tools/tools-core-external-protobuf/build.gradle
similarity index 62%
copy from appfunctions/appfunctions-agent-runtime/build.gradle
copy to privacysandbox/tools/tools-core-external-protobuf/build.gradle
index cce847f..e9ba66a 100644
--- a/appfunctions/appfunctions-agent-runtime/build.gradle
+++ b/privacysandbox/tools/tools-core-external-protobuf/build.gradle
@@ -25,22 +25,28 @@
 
 plugins {
     id("AndroidXPlugin")
-    id("com.android.library")
-    id("org.jetbrains.kotlin.android")
+    id("AndroidXRepackagePlugin")
+    id("kotlin")
+}
+
+repackage {
+    addRelocation {
+        sourcePackage = "com.google.protobuf"
+        targetPackage =  "androidx.privacysandbox.tools.core.proto"
+    }
+    artifactId = "privacysandbox-tools-core-external-protobuf"
 }
 
 dependencies {
-    api(libs.kotlinStdlib)
-    // Add dependencies here
-}
-
-android {
-    namespace = "androidx.appfunctions.agent.runtime"
+    repackage(libs.protobufLite)
 }
 
 androidx {
-    name = "androidx.appfunctions:appfunctions-agent-runtime"
+    name = "Privacysandbox Tools Core External Protobuf"
     type = LibraryType.PUBLISHED_LIBRARY
-    inceptionYear = "2024"
-    description = "Provides a set of helper classes for the agent to interact with AppFunctions."
+    inceptionYear = "2025"
+    description =  "Repackaged proto-lite dependency for use by privacysandbox-tools-core"
+    doNotDocumentReason = "Repackaging only"
+    license.name = "BSD-3-Clause"
+    license.url = "https://opensource.org/licenses/BSD-3-Clause"
 }
diff --git a/privacysandbox/tools/tools-core/build.gradle b/privacysandbox/tools/tools-core/build.gradle
index 2f69c1d..98b1bb6 100644
--- a/privacysandbox/tools/tools-core/build.gradle
+++ b/privacysandbox/tools/tools-core/build.gradle
@@ -28,6 +28,7 @@
 
 plugins {
     id("AndroidXPlugin")
+    id("AndroidXRepackagePlugin")
     id("kotlin")
     id("com.google.protobuf")
 }
@@ -35,10 +36,22 @@
 def buildToolsVersion = AndroidXConfig.getDefaultAndroidConfig(project).getBuildToolsVersion()
 def compileSdk = AndroidXConfig.getDefaultAndroidConfig(project).getCompileSdk()
 
+repackage {
+    // Must match what is in privacysandbox/tools/tools-core-external-protobuf/build.gradle
+    addRelocation {
+        sourcePackage = "com.google.protobuf"
+        targetPackage =  "androidx.privacysandbox.tools.core.proto"
+    }
+}
+
 dependencies {
     api(libs.kotlinStdlib)
-    api(libs.protobuf)
     api(libs.kotlinPoet)
+    api(project(":privacysandbox:tools:tools-core-external-protobuf"))
+    // Must be compileOnly to not bring in protobufLite in runtime
+    // Repackaged protobufLite brought in by
+    // project(":privacysandbox:tools:tools-core-external-protobuf") and used at runtime
+    compileOnly(libs.protobufLite)
     implementation(libs.guava)
     implementation(project(":privacysandbox:tools:tools"))
 
diff --git a/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/BaseHiddenFragment.kt b/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/BaseHiddenFragment.kt
new file mode 100644
index 0000000..b00e16f
--- /dev/null
+++ b/privacysandbox/ui/integration-tests/testapp/src/main/java/androidx/privacysandbox/ui/integration/testapp/BaseHiddenFragment.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2025 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.ui.integration.testapp
+
+/** Base hidden fragment to be used for testing different automation and benchmarking flows. */
+abstract class BaseHiddenFragment : BaseFragment() {
+    final override fun handleLoadAdFromDrawer(
+        adType: Int,
+        mediationOption: Int,
+        drawViewabilityLayer: Boolean
+    ) {}
+
+    final override fun handleDrawerStateChange(isDrawerOpen: Boolean) {}
+}
diff --git a/settings.gradle b/settings.gradle
index ec60c4a..3de9fb9 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -33,7 +33,7 @@
         if (agpOverride != null) {
             classpath("com.android.settings:com.android.settings.gradle.plugin:$agpOverride")
         } else {
-            classpath("com.android.settings:com.android.settings.gradle.plugin:8.9.0-alpha06")
+            classpath("com.android.settings:com.android.settings.gradle.plugin:8.9.0-alpha01")
         }
         // set guava version to be compatible with Depdendency analysis gradle plugin
         classpath("com.google.guava:guava:33.3.1-jre")
@@ -385,11 +385,12 @@
 includeProject(":appcompat:appcompat-lint:integration-tests", [BuildType.MAIN])
 includeProject(":appcompat:appcompat-resources", [BuildType.MAIN])
 includeProject(":appcompat:integration-tests:receive-content-testapp", [BuildType.MAIN])
-includeProject(":appfunctions:appfunctions-agent-compiler", [BuildType.MAIN])
-includeProject(":appfunctions:appfunctions-agent-runtime", [BuildType.MAIN])
 includeProject(":appfunctions:appfunctions-app-compiler", [BuildType.MAIN])
 includeProject(":appfunctions:appfunctions-app-runtime", [BuildType.MAIN])
 includeProject(":appfunctions:appfunctions-common", [BuildType.MAIN])
+includeProject(":appfunctions:appfunctions-compiler", [BuildType.MAIN])
+includeProject(":appfunctions:appfunctions-runtime", [BuildType.MAIN])
+includeProject(":appfunctions:appfunctions-stubs", [BuildType.MAIN])
 includeProject(":appsearch:appsearch", [BuildType.MAIN])
 includeProject(":appsearch:appsearch-builtin-types", [BuildType.MAIN])
 includeProject(":appsearch:appsearch-compiler", "appsearch/compiler", [BuildType.MAIN])
@@ -929,6 +930,7 @@
 includeProject(":privacysandbox:tools:tools-apigenerator", [BuildType.MAIN])
 includeProject(":privacysandbox:tools:tools-apipackager", [BuildType.MAIN])
 includeProject(":privacysandbox:tools:tools-core", [BuildType.MAIN])
+includeProject(":privacysandbox:tools:tools-core-external-protobuf", [BuildType.MAIN])
 includeProject(":privacysandbox:tools:tools-testing", [BuildType.MAIN])
 includeProject(":privacysandbox:ui:integration-tests:mediateesdkprovider", [BuildType.MAIN])
 includeProject(":privacysandbox:ui:integration-tests:mediateesdkproviderwrapper", [BuildType.MAIN])
@@ -1250,6 +1252,8 @@
 includeProject(":noto-emoji-compat-font", new File(externalRoot, "noto-fonts/emoji-compat"), [BuildType.MAIN])
 includeProject(":noto-emoji-compat-flatbuffers", new File(externalRoot, "noto-fonts/emoji-compat-flatbuffers"), [BuildType.MAIN, BuildType.COMPOSE])
 
+includeProject(":compose-hero-benchmarks", new File(externalRoot, "compose-hero-benchmarks"), [BuildType.COMPOSE])
+includeProject(":compose-hero-benchmarks:poxedex-compose", new File(externalRoot, "compose-hero-benchmarks/poxedex-compose"), [BuildType.COMPOSE])
 includeProject(":compose-hero-benchmarks:poxedex-compose:app", new File(externalRoot, "compose-hero-benchmarks/poxedex-compose/app"), [BuildType.COMPOSE])
 
 if (isAllProjects()) {
diff --git a/slidingpanelayout/slidingpanelayout/build.gradle b/slidingpanelayout/slidingpanelayout/build.gradle
index 50b605c..8dd129f 100644
--- a/slidingpanelayout/slidingpanelayout/build.gradle
+++ b/slidingpanelayout/slidingpanelayout/build.gradle
@@ -24,6 +24,7 @@
     androidTestImplementation(libs.testRunner)
     androidTestImplementation(libs.espressoCore)
     androidTestImplementation(libs.kotlinStdlib)
+    androidTestImplementation(libs.testUiautomator)
     androidTestImplementation(libs.truth)
     androidTestImplementation(project(":internal-testutils-runtime"))
     androidTestImplementation("androidx.window:window-testing:1.2.0")
diff --git a/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/SlidingPaneLayoutFindViewByAccessibilityIdTraversalTest.kt b/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/SlidingPaneLayoutFindViewByAccessibilityIdTraversalTest.kt
new file mode 100644
index 0000000..776048e
--- /dev/null
+++ b/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/SlidingPaneLayoutFindViewByAccessibilityIdTraversalTest.kt
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2025 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.slidingpanelayout.widget
+
+import android.graphics.Matrix
+import android.os.Bundle
+import android.os.LocaleList
+import android.view.View.AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
+import android.view.ViewGroup
+import android.view.ViewStructure
+import android.view.autofill.AutofillId
+import android.view.autofill.AutofillValue
+import android.widget.FrameLayout
+import androidx.annotation.RequiresApi
+import androidx.slidingpanelayout.test.R
+import androidx.slidingpanelayout.widget.helpers.TestActivity
+import androidx.test.core.app.ActivityScenario
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.UiDevice
+import androidx.testutils.withActivity
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@LargeTest
+class SlidingPaneLayoutFindViewByAccessibilityIdTraversalTest {
+
+    @After
+    fun tearDown() {
+        TestActivity.onActivityCreated = {}
+    }
+
+    @Test
+    fun testAccessibilityService_canFindChildren() {
+        // View#findViewByAccessibilityIdTraversal is a hidden method and we can't directly test it.
+        // In this test, we exploit that UiDevice is an Accessibility service and its findObject
+        // used the findViewByAccessibilityIdTraversal on API 28 and under.
+        // And if UiDevice can find the children, then other A11y services like Talkback will work
+        // as intended.
+        TestActivity.onActivityCreated = { activity ->
+            val container = FrameLayout(activity)
+            val layout =
+                activity.layoutInflater.inflate(
+                    R.layout.user_resizeable_slidingpanelayout,
+                    null,
+                    false
+                )
+            container.addView(layout, ViewGroup.LayoutParams(300, 500))
+
+            val spl = layout.findViewById<SlidingPaneLayout>(R.id.sliding_pane_layout)
+            spl.isUserResizingEnabled = true
+            spl.isOverlappingEnabled = false
+
+            activity.setContentView(container)
+        }
+
+        val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+
+        with(ActivityScenario.launch(TestActivity::class.java)) {
+            val layout = withActivity { findViewById<SlidingPaneLayout>(R.id.sliding_pane_layout) }
+
+            assertThat(layout.isUserResizable).isTrue()
+            assertThat(device.findObject(By.text("List"))).isNotNull()
+            assertThat(device.findObject(By.text("Detail"))).isNotNull()
+        }
+    }
+
+    // We have SdkSuppress because ViewGroup#dispatchProvideAutofillStructure is available only
+    // after API 26.
+    @Test
+    @SdkSuppress(minSdkVersion = 26)
+    fun testAutofill_canFindChildren() {
+        TestActivity.onActivityCreated = { activity ->
+            val container = FrameLayout(activity)
+            val layout =
+                activity.layoutInflater.inflate(
+                    R.layout.user_resizeable_slidingpanelayout,
+                    null,
+                    false
+                )
+            container.addView(
+                layout,
+                ViewGroup.LayoutParams(
+                    ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.WRAP_CONTENT
+                )
+            )
+
+            activity.setContentView(container)
+        }
+
+        with(ActivityScenario.launch(TestActivity::class.java)) {
+            val slidingPaneLayout = withActivity {
+                findViewById<SlidingPaneLayout>(R.id.sliding_pane_layout)
+            }
+            val viewStructure = TestViewStructure()
+            slidingPaneLayout.dispatchProvideAutofillStructure(
+                viewStructure,
+                AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
+            )
+            // Ensure that the children is visible to Autofill service.
+            assertThat(viewStructure.getChildCount()).isEqualTo(2)
+        }
+    }
+
+    @RequiresApi(26)
+    private class TestViewStructure : ViewStructure() {
+        private var childMap = mutableMapOf<Int, TestViewStructure>()
+
+        override fun setId(id: Int, packageName: String?, typeName: String?, entryName: String?) {}
+
+        override fun setDimens(
+            left: Int,
+            top: Int,
+            scrollX: Int,
+            scrollY: Int,
+            width: Int,
+            height: Int
+        ) {}
+
+        override fun setTransformation(matrix: Matrix?) {}
+
+        override fun setElevation(elevation: Float) {}
+
+        override fun setAlpha(alpha: Float) {}
+
+        override fun setVisibility(visibility: Int) {}
+
+        override fun setEnabled(state: Boolean) {}
+
+        override fun setClickable(state: Boolean) {}
+
+        override fun setLongClickable(state: Boolean) {}
+
+        override fun setContextClickable(state: Boolean) {}
+
+        override fun setFocusable(state: Boolean) {}
+
+        override fun setFocused(state: Boolean) {}
+
+        override fun setAccessibilityFocused(state: Boolean) {}
+
+        override fun setCheckable(state: Boolean) {}
+
+        override fun setChecked(state: Boolean) {}
+
+        override fun setSelected(state: Boolean) {}
+
+        override fun setActivated(state: Boolean) {}
+
+        override fun setOpaque(opaque: Boolean) {}
+
+        override fun setClassName(className: String?) {}
+
+        override fun setContentDescription(contentDescription: CharSequence?) {}
+
+        override fun setText(text: CharSequence?) {}
+
+        override fun setText(text: CharSequence?, selectionStart: Int, selectionEnd: Int) {}
+
+        override fun setTextStyle(size: Float, fgColor: Int, bgColor: Int, style: Int) {}
+
+        override fun setTextLines(charOffsets: IntArray?, baselines: IntArray?) {}
+
+        override fun setHint(hint: CharSequence?) {}
+
+        override fun getText(): CharSequence? = null
+
+        override fun getTextSelectionStart(): Int = 0
+
+        override fun getTextSelectionEnd(): Int = 0
+
+        override fun getHint(): CharSequence? = null
+
+        override fun getExtras(): Bundle? = null
+
+        override fun hasExtras(): Boolean = false
+
+        override fun setChildCount(num: Int) {}
+
+        override fun addChildCount(num: Int): Int = childMap.size
+
+        override fun getChildCount(): Int = childMap.size
+
+        override fun newChild(index: Int): ViewStructure? {
+            if (!childMap.contains(index)) {
+                childMap[index] = TestViewStructure()
+            }
+            return childMap[index]
+        }
+
+        override fun asyncNewChild(index: Int): ViewStructure? {
+            return newChild(index)
+        }
+
+        override fun getAutofillId(): AutofillId? {
+            return null
+        }
+
+        override fun setAutofillId(id: AutofillId) {}
+
+        override fun setAutofillId(parentId: AutofillId, virtualId: Int) {}
+
+        override fun setAutofillType(type: Int) {}
+
+        override fun setAutofillHints(hint: Array<out String?>?) {}
+
+        override fun setAutofillValue(value: AutofillValue?) {}
+
+        override fun setAutofillOptions(options: Array<out CharSequence?>?) {}
+
+        override fun setInputType(inputType: Int) {}
+
+        override fun setDataIsSensitive(sensitive: Boolean) {}
+
+        override fun asyncCommit() {}
+
+        override fun setWebDomain(domain: String?) {}
+
+        override fun setLocaleList(localeList: LocaleList?) {}
+
+        override fun newHtmlInfoBuilder(tagName: String): HtmlInfo.Builder? = null
+
+        override fun setHtmlInfo(htmlInfo: HtmlInfo) {}
+    }
+}
diff --git a/slidingpanelayout/slidingpanelayout/src/androidTest/res/layout/user_resizeable_slidingpanelayout.xml b/slidingpanelayout/slidingpanelayout/src/androidTest/res/layout/user_resizeable_slidingpanelayout.xml
new file mode 100644
index 0000000..8c6b6a8
--- /dev/null
+++ b/slidingpanelayout/slidingpanelayout/src/androidTest/res/layout/user_resizeable_slidingpanelayout.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+  Copyright 2021 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<androidx.slidingpanelayout.widget.SlidingPaneLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/sliding_pane_layout">
+
+    <TextView
+        android:id="@+id/list_pane"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:background="@android:color/darker_gray"
+        android:text="List" />
+
+    <TextView
+        android:id="@+id/detail_pane"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:background="@android:color/black"
+        android:text="Detail" />
+</androidx.slidingpanelayout.widget.SlidingPaneLayout>
\ No newline at end of file
diff --git a/slidingpanelayout/slidingpanelayout/src/main/java/androidx/slidingpanelayout/widget/SlidingPaneLayout.kt b/slidingpanelayout/slidingpanelayout/src/main/java/androidx/slidingpanelayout/widget/SlidingPaneLayout.kt
index 5ba2325..6649789 100644
--- a/slidingpanelayout/slidingpanelayout/src/main/java/androidx/slidingpanelayout/widget/SlidingPaneLayout.kt
+++ b/slidingpanelayout/slidingpanelayout/src/main/java/androidx/slidingpanelayout/widget/SlidingPaneLayout.kt
@@ -43,6 +43,7 @@
 import androidx.annotation.IntDef
 import androidx.annotation.Px
 import androidx.annotation.RequiresApi
+import androidx.annotation.RestrictTo
 import androidx.core.content.ContextCompat
 import androidx.core.content.withStyledAttributes
 import androidx.core.graphics.Insets
@@ -62,6 +63,7 @@
 import androidx.slidingpanelayout.R
 import androidx.window.layout.FoldingFeature
 import androidx.window.layout.WindowInfoTracker
+import java.lang.reflect.Method
 import java.util.concurrent.CopyOnWriteArrayList
 import kotlin.math.abs
 import kotlin.math.max
@@ -405,6 +407,9 @@
     private var accessibilityProvider: AccessibilityProvider? = null
     private var dividerHasA11yHover = false
 
+    // Cached reflected method used by findViewByAccessibilityIdTraversal
+    private var getAccessibilityViewIdMethod: Method? = null
+
     /**
      * Set a [Drawable] to display when [isUserResizingEnabled] is `true` and multiple panes are
      * visible without overlapping. This forms the visual touch target for dragging. This may also
@@ -2089,6 +2094,66 @@
         }
     }
 
+    /**
+     * This overrides an hidden method in ViewGroup. Because of the hide tag, the override keyword
+     * cannot be used, but the override works anyway because the ViewGroup method is not final. In
+     * Android P and earlier, the call path is
+     * AccessibilityInteractionController#findViewByAccessibilityId ->
+     * View#findViewByAccessibilityId -> ViewGroup#findViewByAccessibilityIdTraversal. In Android Q
+     * and later, AccessibilityInteractionController#findViewByAccessibilityId uses
+     * AccessibilityNodeIdManager and findViewByAccessibilityIdTraversal is only used by autofill.
+     */
+    @Suppress("BanHideTag")
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    fun findViewByAccessibilityIdTraversal(accessibilityId: Int): View? {
+        return try {
+
+            // AccessibilityInteractionController#findViewByAccessibilityId doesn't call this
+            // method in Android Q and later.
+            // Note that after Q, the original ViewGroup#findViewByAccessibilityIdTraversal returns
+            // null anyway when there is a AccessibilityNodeProvider.
+            // Autofill is using this method mainly for views that provides accessibility
+            // information but not autofill structure. It doesn't impact the autofill behavior of
+            // children views, since children views will directly talk to AutofillManager to update
+            // its status.
+            findViewByAccessibilityIdRootedAtCurrentView(accessibilityId, this)
+        } catch (e: NoSuchMethodException) {
+            null
+        }
+    }
+
+    private fun findViewByAccessibilityIdRootedAtCurrentView(
+        accessibilityId: Int,
+        currentView: View
+    ): View? {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
+            val getAccessibilityViewIdMethod =
+                this.getAccessibilityViewIdMethod
+                    ?: View::class.java.getDeclaredMethod("getAccessibilityViewId").also {
+                        this.getAccessibilityViewIdMethod = it
+                    }
+            getAccessibilityViewIdMethod.isAccessible = true
+            if (getAccessibilityViewIdMethod.invoke(currentView) == accessibilityId) {
+                return currentView
+            }
+            if (currentView is ViewGroup) {
+                for (i in 0 until currentView.childCount) {
+                    val foundView =
+                        findViewByAccessibilityIdRootedAtCurrentView(
+                            accessibilityId,
+                            currentView.getChildAt(i)
+                        )
+                    if (foundView != null) {
+                        return foundView
+                    }
+                }
+            }
+        }
+        // After Q, ViewGroup#findViewByAccessibilityIdTraversal returns null for ViewGroup with
+        // AccessibilityNodeProvider.
+        return null
+    }
+
     private fun sendAccessibilityEventForDivider(eventType: Int) {
         parent.requestSendAccessibilityEvent(
             this,
diff --git a/tv/tv-material/src/androidTest/java/androidx/tv/material3/NavigationDrawerItemTest.kt b/tv/tv-material/src/androidTest/java/androidx/tv/material3/NavigationDrawerItemTest.kt
index b6a3595..ccab5f2 100644
--- a/tv/tv-material/src/androidTest/java/androidx/tv/material3/NavigationDrawerItemTest.kt
+++ b/tv/tv-material/src/androidTest/java/androidx/tv/material3/NavigationDrawerItemTest.kt
@@ -237,7 +237,7 @@
                 .getUnclippedBoundsInRoot()
 
         (itemBounds.bottom - trailingContentBounds.bottom).assertIsEqualTo(
-            16.dp,
+            12.dp,
             "padding between the bottom of the trailing content and the bottom of the nav " +
                 "drawer item"
         )
@@ -360,7 +360,7 @@
 
     @Test
     fun navigationDrawerItem_oneLineHeight() {
-        val expectedHeightNoIcon = 56.dp
+        val expectedHeightNoIcon = 48.dp
 
         rule.setContent {
             DrawerScope {
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/NavigationDrawerItemDefaults.kt b/tv/tv-material/src/main/java/androidx/tv/material3/NavigationDrawerItemDefaults.kt
index 75380fe..07cbe42 100644
--- a/tv/tv-material/src/main/java/androidx/tv/material3/NavigationDrawerItemDefaults.kt
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/NavigationDrawerItemDefaults.kt
@@ -52,13 +52,13 @@
      * The default content padding [PaddingValues] used by [NavigationDrawerItem] with 1 line when
      * the drawer is expanded
      */
-    val ContainerHeightOneLine = 56.dp
+    val ContainerHeightOneLine = 48.dp
 
     /**
      * The default content padding [PaddingValues] used by [NavigationDrawerItem] with 2 lines when
      * the drawer is expanded
      */
-    val ContainerHeightTwoLine = 64.dp
+    val ContainerHeightTwoLine = 56.dp
 
     /** The default elevation used by [NavigationDrawerItem] */
     val NavigationDrawerItemElevation = Elevation.Level0
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/Surface.kt b/tv/tv-material/src/main/java/androidx/tv/material3/Surface.kt
index 82f353c..ec9feea 100644
--- a/tv/tv-material/src/main/java/androidx/tv/material3/Surface.kt
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/Surface.kt
@@ -16,9 +16,7 @@
 
 package androidx.tv.material3
 
-import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.foundation.background
-import androidx.compose.foundation.focusable
 import androidx.compose.foundation.interaction.Interaction
 import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.interaction.PressInteraction
@@ -29,34 +27,14 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.NonRestartableComposable
-import androidx.compose.runtime.compositionLocalOf
 import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.composed
 import androidx.compose.ui.draw.clip
-import androidx.compose.ui.draw.scale
-import androidx.compose.ui.focus.onFocusChanged
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.graphics.graphicsLayer
-import androidx.compose.ui.input.key.NativeKeyEvent
-import androidx.compose.ui.input.key.onKeyEvent
-import androidx.compose.ui.platform.debugInspectorInfo
-import androidx.compose.ui.semantics.disabled
-import androidx.compose.ui.semantics.onClick
-import androidx.compose.ui.semantics.onLongClick
-import androidx.compose.ui.semantics.selected
-import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
-import androidx.compose.ui.zIndex
 import androidx.tv.material3.tokens.Elevation
-import kotlinx.coroutines.launch
 
 /**
  * The [Surface] is a building block component that will be used for any element on TV such as
@@ -92,7 +70,7 @@
         LocalAbsoluteTonalElevation provides absoluteElevation
     ) {
         val backgroundColorByState =
-            surfaceColorAtElevation(
+            calculateSurfaceColorAtElevation(
                 color = colors.containerColor,
                 elevation = LocalAbsoluteTonalElevation.current
             )
@@ -171,46 +149,32 @@
         enabled = enabled,
         tonalElevation = tonalElevation,
         shape =
-            ClickableSurfaceDefaults.shape(
+            shape.currentShape(
                 enabled = enabled,
                 focused = focused,
                 pressed = pressed,
-                shape = shape
             ),
         color =
-            ClickableSurfaceDefaults.containerColor(
-                enabled = enabled,
-                focused = focused,
-                pressed = pressed,
-                colors = colors
-            ),
+            colors.currentContainerColor(enabled = enabled, focused = focused, pressed = pressed),
         contentColor =
-            ClickableSurfaceDefaults.contentColor(
-                enabled = enabled,
-                focused = focused,
-                pressed = pressed,
-                colors = colors
-            ),
+            colors.currentContentColor(enabled = enabled, focused = focused, pressed = pressed),
         scale =
-            ClickableSurfaceDefaults.scale(
+            scale.currentScale(
                 enabled = enabled,
                 focused = focused,
                 pressed = pressed,
-                scale = scale
             ),
         border =
-            ClickableSurfaceDefaults.border(
+            border.currentBorder(
                 enabled = enabled,
                 focused = focused,
                 pressed = pressed,
-                border = border
             ),
         glow =
-            ClickableSurfaceDefaults.glow(
+            glow.currentGlow(
                 enabled = enabled,
                 focused = focused,
                 pressed = pressed,
-                glow = glow
             ),
         interactionSource = interactionSource,
         content = content
@@ -287,346 +251,48 @@
         enabled = enabled,
         tonalElevation = tonalElevation,
         shape =
-            SelectableSurfaceDefaults.shape(
+            shape.currentShape(
                 enabled = enabled,
                 focused = focused,
                 pressed = pressed,
                 selected = selected,
-                shape = shape
             ),
         color =
-            SelectableSurfaceDefaults.containerColor(
+            colors.currentContainerColor(
                 enabled = enabled,
                 focused = focused,
                 pressed = pressed,
                 selected = selected,
-                colors = colors
             ),
         contentColor =
-            SelectableSurfaceDefaults.contentColor(
+            colors.currentContentColor(
                 enabled = enabled,
                 focused = focused,
                 pressed = pressed,
                 selected = selected,
-                colors = colors
             ),
         scale =
-            SelectableSurfaceDefaults.scale(
+            scale.currentScale(
                 enabled = enabled,
                 focused = focused,
                 pressed = pressed,
                 selected = selected,
-                scale = scale
             ),
         border =
-            SelectableSurfaceDefaults.border(
+            border.currentBorder(
                 enabled = enabled,
                 focused = focused,
                 pressed = pressed,
                 selected = selected,
-                border = border
             ),
         glow =
-            SelectableSurfaceDefaults.glow(
+            glow.currentGlow(
                 enabled = enabled,
                 focused = focused,
                 pressed = pressed,
                 selected = selected,
-                glow = glow
             ),
         interactionSource = interactionSource,
         content = content
     )
 }
-
-@Composable
-private fun SurfaceImpl(
-    modifier: Modifier,
-    selected: Boolean,
-    enabled: Boolean,
-    shape: Shape,
-    color: Color,
-    contentColor: Color,
-    scale: Float,
-    border: Border,
-    glow: Glow,
-    tonalElevation: Dp,
-    interactionSource: MutableInteractionSource? = null,
-    content: @Composable (BoxScope.() -> Unit)
-) {
-    @Suppress("NAME_SHADOWING")
-    val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
-    val focused by interactionSource.collectIsFocusedAsState()
-    val pressed by interactionSource.collectIsPressedAsState()
-
-    val surfaceAlpha =
-        stateAlpha(enabled = enabled, focused = focused, pressed = pressed, selected = selected)
-
-    val absoluteElevation = LocalAbsoluteTonalElevation.current + tonalElevation
-
-    CompositionLocalProvider(
-        LocalContentColor provides contentColor,
-        LocalAbsoluteTonalElevation provides absoluteElevation
-    ) {
-        val zIndex by
-            animateFloatAsState(
-                targetValue = if (focused) FocusedZIndex else NonFocusedZIndex,
-                label = "zIndex"
-            )
-
-        val backgroundColorByState =
-            surfaceColorAtElevation(color = color, elevation = LocalAbsoluteTonalElevation.current)
-
-        Box(
-            modifier =
-                modifier
-                    .tvSurfaceScale(
-                        scale = scale,
-                        interactionSource = interactionSource,
-                    )
-                    .ifElse(API_28_OR_ABOVE, Modifier.tvSurfaceGlow(shape, glow))
-                    // Increasing the zIndex of this Surface when it is in the focused state to
-                    // avoid the glowIndication from being overlapped by subsequent items if
-                    // this Surface is inside a list composable (like a Row/Column).
-                    .zIndex(zIndex)
-                    .ifElse(border != Border.None, Modifier.tvSurfaceBorder(shape, border))
-                    .background(backgroundColorByState, shape)
-                    .graphicsLayer {
-                        this.alpha = surfaceAlpha
-                        this.shape = shape
-                        this.clip = true
-                    },
-            propagateMinConstraints = true
-        ) {
-            Box(
-                modifier =
-                    Modifier.graphicsLayer {
-                        this.alpha = if (!enabled) DisabledContentAlpha else EnabledContentAlpha
-                    },
-                content = content
-            )
-        }
-    }
-}
-
-/**
- * This modifier handles click, press, and focus events for a TV composable.
- *
- * @param enabled decides whether [onClick] is executed
- * @param onClick executes the provided lambda on click.
- * @param onLongClick executes the provided lambda on long press.
- * @param interactionSource used to emit [PressInteraction] events
- */
-private fun Modifier.tvClickable(
-    enabled: Boolean,
-    onClick: (() -> Unit)?,
-    onLongClick: (() -> Unit)?,
-    interactionSource: MutableInteractionSource
-) =
-    handleDPadEnter(
-            enabled = enabled,
-            interactionSource = interactionSource,
-            onClick = onClick,
-            onLongClick = onLongClick
-        )
-        // We are not using "clickable" modifier here because if we set "enabled" to false
-        // then the Surface won't be focusable as well. But, in TV use case, a disabled surface
-        // should be focusable
-        .focusable(interactionSource = interactionSource)
-        .semantics(mergeDescendants = true) {
-            onClick {
-                onClick?.let { nnOnClick ->
-                    nnOnClick()
-                    return@onClick true
-                }
-                false
-            }
-            onLongClick {
-                onLongClick?.let { nnOnLongClick ->
-                    nnOnLongClick()
-                    return@onLongClick true
-                }
-                false
-            }
-            if (!enabled) {
-                disabled()
-            }
-        }
-
-/**
- * This modifier handles click, press, and focus events for a TV composable.
- *
- * @param enabled decides whether [onClick] is executed
- * @param selected differentiates whether the current item is selected or unselected
- * @param onClick executes the provided lambda on click, while returning the inverse state of
- *   [selected].
- * @param onLongClick executes the provided lambda on long press.
- * @param interactionSource used to emit [PressInteraction] events
- */
-private fun Modifier.tvSelectable(
-    enabled: Boolean,
-    selected: Boolean,
-    onClick: () -> Unit,
-    onLongClick: (() -> Unit)?,
-    interactionSource: MutableInteractionSource,
-) =
-    handleDPadEnter(
-            enabled = enabled,
-            interactionSource = interactionSource,
-            selected = selected,
-            onClick = onClick,
-            onLongClick = onLongClick
-        )
-        // We are not using "selectable" modifier here because if we set "enabled" to false
-        // then the Surface won't be focusable as well. But, in TV use case, a disabled surface
-        // should be focusable
-        .focusable(interactionSource = interactionSource)
-        .semantics(mergeDescendants = true) {
-            this.selected = selected
-            onClick {
-                onClick()
-                true
-            }
-            onLongClick {
-                onLongClick?.let { nnOnLongClick ->
-                    nnOnLongClick()
-                    return@onLongClick true
-                }
-                false
-            }
-            if (!enabled) {
-                disabled()
-            }
-        }
-
-/**
- * This modifier is used to perform some actions when the user clicks the D-PAD enter button
- *
- * @param enabled if this is false, the D-PAD enter event is ignored
- * @param interactionSource used to emit [PressInteraction] events
- * @param onClick this lambda will be triggered on D-PAD enter event
- * @param onLongClick this lambda will be triggered when D-PAD enter is long pressed.
- * @param selected differentiates whether the current item is selected or unselected
- */
-private fun Modifier.handleDPadEnter(
-    enabled: Boolean,
-    interactionSource: MutableInteractionSource,
-    onClick: (() -> Unit)? = null,
-    onLongClick: (() -> Unit)? = null,
-    selected: Boolean = false,
-) =
-    composed(
-        inspectorInfo =
-            debugInspectorInfo {
-                name = "handleDPadEnter"
-                properties["enabled"] = enabled
-                properties["interactionSource"] = interactionSource
-                properties["onClick"] = onClick
-                properties["onLongClick"] = onLongClick
-                properties["selected"] = selected
-            }
-    ) {
-        if (!enabled) return@composed this
-
-        val coroutineScope = rememberCoroutineScope()
-        val pressInteraction = remember { PressInteraction.Press(Offset.Zero) }
-        var isLongClick by remember { mutableStateOf(false) }
-        val isPressed by interactionSource.collectIsPressedAsState()
-
-        this.onFocusChanged {
-                if (!it.isFocused && isPressed) {
-                    coroutineScope.launch {
-                        interactionSource.emit(PressInteraction.Release(pressInteraction))
-                    }
-                }
-            }
-            .onKeyEvent { keyEvent ->
-                if (AcceptableKeys.contains(keyEvent.nativeKeyEvent.keyCode)) {
-                    when (keyEvent.nativeKeyEvent.action) {
-                        NativeKeyEvent.ACTION_DOWN -> {
-                            when (keyEvent.nativeKeyEvent.repeatCount) {
-                                0 ->
-                                    coroutineScope.launch {
-                                        interactionSource.emit(pressInteraction)
-                                    }
-                                1 ->
-                                    onLongClick?.let {
-                                        isLongClick = true
-                                        coroutineScope.launch {
-                                            interactionSource.emit(
-                                                PressInteraction.Release(pressInteraction)
-                                            )
-                                        }
-                                        it.invoke()
-                                    }
-                            }
-                        }
-                        NativeKeyEvent.ACTION_UP -> {
-                            if (!isLongClick) {
-                                coroutineScope.launch {
-                                    interactionSource.emit(
-                                        PressInteraction.Release(pressInteraction)
-                                    )
-                                }
-                                onClick?.invoke()
-                            } else isLongClick = false
-                        }
-                    }
-                    return@onKeyEvent KeyEventPropagation.StopPropagation
-                }
-                KeyEventPropagation.ContinuePropagation
-            }
-    }
-
-@Composable
-internal fun surfaceColorAtElevation(color: Color, elevation: Dp): Color {
-    return if (color == MaterialTheme.colorScheme.surface) {
-        MaterialTheme.colorScheme.surfaceColorAtElevation(elevation)
-    } else {
-        color
-    }
-}
-
-/**
- * Returns the alpha value for Surface's background based on its current indication state. The value
- * ranges between 0f and 1f.
- */
-private fun stateAlpha(
-    enabled: Boolean,
-    focused: Boolean,
-    pressed: Boolean,
-    selected: Boolean
-): Float {
-    return when {
-        !enabled && pressed -> DisabledPressedStateAlpha
-        !enabled && focused -> DisabledFocusedStateAlpha
-        !enabled && selected -> DisabledSelectedStateAlpha
-        enabled -> EnabledContentAlpha
-        else -> DisabledDefaultStateAlpha
-    }
-}
-
-private const val DisabledPressedStateAlpha = 0.8f
-private const val DisabledFocusedStateAlpha = 0.8f
-private const val DisabledSelectedStateAlpha = 0.8f
-private const val DisabledDefaultStateAlpha = 0.6f
-
-private const val FocusedZIndex = 0.5f
-private const val NonFocusedZIndex = 0f
-
-private const val DisabledContentAlpha = 0.8f
-internal const val EnabledContentAlpha = 1f
-
-/**
- * CompositionLocal containing the current absolute elevation provided by Surface components. This
- * absolute elevation is a sum of all the previous elevations. Absolute elevation is only used for
- * calculating surface tonal colors, and is *not* used for drawing the shadow in a [SurfaceImpl].
- */
-internal val LocalAbsoluteTonalElevation = compositionLocalOf { 0.dp }
-
-private val AcceptableKeys =
-    intArrayOf(
-        NativeKeyEvent.KEYCODE_DPAD_CENTER,
-        NativeKeyEvent.KEYCODE_ENTER,
-        NativeKeyEvent.KEYCODE_NUMPAD_ENTER
-    )
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceClickableUtils.kt b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceClickableUtils.kt
new file mode 100644
index 0000000..db793fa
--- /dev/null
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceClickableUtils.kt
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.tv.material3
+
+import androidx.compose.foundation.focusable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.semantics.disabled
+import androidx.compose.ui.semantics.onClick
+import androidx.compose.ui.semantics.onLongClick
+import androidx.compose.ui.semantics.semantics
+
+internal fun Modifier.tvClickable(
+    enabled: Boolean,
+    onClick: (() -> Unit)?,
+    onLongClick: (() -> Unit)?,
+    interactionSource: MutableInteractionSource
+) =
+    handleDPadEnter(
+            enabled = enabled,
+            interactionSource = interactionSource,
+            onClick = onClick,
+            onLongClick = onLongClick
+        )
+        // We are not using "clickable" modifier here because if we set "enabled" to false
+        // then the Surface won't be focusable as well. But, in TV use case, a disabled surface
+        // should be focusable
+        .focusable(interactionSource = interactionSource)
+        .semantics(mergeDescendants = true) {
+            onClick {
+                onClick?.let { nnOnClick ->
+                    nnOnClick()
+                    return@onClick true
+                }
+                false
+            }
+            onLongClick {
+                onLongClick?.let { nnOnLongClick ->
+                    nnOnLongClick()
+                    return@onLongClick true
+                }
+                false
+            }
+            if (!enabled) {
+                disabled()
+            }
+        }
+
+internal fun ClickableSurfaceShape.currentShape(
+    enabled: Boolean,
+    focused: Boolean,
+    pressed: Boolean
+): Shape {
+    return when {
+        pressed && enabled -> pressedShape
+        focused && enabled -> focusedShape
+        focused && !enabled -> focusedDisabledShape
+        enabled -> shape
+        else -> disabledShape
+    }
+}
+
+internal fun ClickableSurfaceColors.currentContainerColor(
+    enabled: Boolean,
+    focused: Boolean,
+    pressed: Boolean
+): Color {
+    return when {
+        pressed && enabled -> pressedContainerColor
+        focused && enabled -> focusedContainerColor
+        enabled -> containerColor
+        else -> disabledContainerColor
+    }
+}
+
+internal fun ClickableSurfaceColors.currentContentColor(
+    enabled: Boolean,
+    focused: Boolean,
+    pressed: Boolean
+): Color {
+    return when {
+        pressed && enabled -> pressedContentColor
+        focused && enabled -> focusedContentColor
+        enabled -> contentColor
+        else -> disabledContentColor
+    }
+}
+
+internal fun ClickableSurfaceScale.currentScale(
+    enabled: Boolean,
+    focused: Boolean,
+    pressed: Boolean
+): Float {
+    return when {
+        pressed && enabled -> pressedScale
+        focused && enabled -> focusedScale
+        focused && !enabled -> focusedDisabledScale
+        enabled -> scale
+        else -> disabledScale
+    }
+}
+
+internal fun ClickableSurfaceBorder.currentBorder(
+    enabled: Boolean,
+    focused: Boolean,
+    pressed: Boolean
+): Border {
+    return when {
+        pressed && enabled -> pressedBorder
+        focused && enabled -> focusedBorder
+        focused && !enabled -> focusedDisabledBorder
+        enabled -> border
+        else -> disabledBorder
+    }
+}
+
+internal fun ClickableSurfaceGlow.currentGlow(
+    enabled: Boolean,
+    focused: Boolean,
+    pressed: Boolean
+): Glow {
+    return if (enabled) {
+        when {
+            pressed -> pressedGlow
+            focused -> focusedGlow
+            else -> glow
+        }
+    } else {
+        Glow.None
+    }
+}
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceDefaults.kt b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceDefaults.kt
index 53dd292..da15f56 100644
--- a/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceDefaults.kt
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceDefaults.kt
@@ -55,21 +55,6 @@
 
 /** Contains the default values used by clickable Surface. */
 object ClickableSurfaceDefaults {
-    internal fun shape(
-        enabled: Boolean,
-        focused: Boolean,
-        pressed: Boolean,
-        shape: ClickableSurfaceShape
-    ): Shape {
-        return when {
-            pressed && enabled -> shape.pressedShape
-            focused && enabled -> shape.focusedShape
-            focused && !enabled -> shape.focusedDisabledShape
-            enabled -> shape.shape
-            else -> shape.disabledShape
-        }
-    }
-
     /**
      * Creates a [ClickableSurfaceShape] that represents the default container shapes used in a
      * Surface.
@@ -97,34 +82,6 @@
             focusedDisabledShape = focusedDisabledShape
         )
 
-    internal fun containerColor(
-        enabled: Boolean,
-        focused: Boolean,
-        pressed: Boolean,
-        colors: ClickableSurfaceColors
-    ): Color {
-        return when {
-            pressed && enabled -> colors.pressedContainerColor
-            focused && enabled -> colors.focusedContainerColor
-            enabled -> colors.containerColor
-            else -> colors.disabledContainerColor
-        }
-    }
-
-    internal fun contentColor(
-        enabled: Boolean,
-        focused: Boolean,
-        pressed: Boolean,
-        colors: ClickableSurfaceColors
-    ): Color {
-        return when {
-            pressed && enabled -> colors.pressedContentColor
-            focused && enabled -> colors.focusedContentColor
-            enabled -> colors.contentColor
-            else -> colors.disabledContentColor
-        }
-    }
-
     /**
      * Creates a [ClickableSurfaceColors] that represents the default container & content colors
      * used in a Surface.
@@ -162,21 +119,6 @@
             disabledContentColor = disabledContentColor
         )
 
-    internal fun scale(
-        enabled: Boolean,
-        focused: Boolean,
-        pressed: Boolean,
-        scale: ClickableSurfaceScale
-    ): Float {
-        return when {
-            pressed && enabled -> scale.pressedScale
-            focused && enabled -> scale.focusedScale
-            focused && !enabled -> scale.focusedDisabledScale
-            enabled -> scale.scale
-            else -> scale.disabledScale
-        }
-    }
-
     /**
      * Creates a [ClickableSurfaceScale] that represents the default scales used in a Surface.
      * scales are used to modify the size of a composable in different [Interaction] states e.g. 1f
@@ -204,21 +146,6 @@
             focusedDisabledScale = focusedDisabledScale
         )
 
-    internal fun border(
-        enabled: Boolean,
-        focused: Boolean,
-        pressed: Boolean,
-        border: ClickableSurfaceBorder
-    ): Border {
-        return when {
-            pressed && enabled -> border.pressedBorder
-            focused && enabled -> border.focusedBorder
-            focused && !enabled -> border.focusedDisabledBorder
-            enabled -> border.border
-            else -> border.disabledBorder
-        }
-    }
-
     /**
      * Creates a [ClickableSurfaceBorder] that represents the default [Border]s applied on a Surface
      * in different [Interaction] states.
@@ -252,23 +179,6 @@
             focusedDisabledBorder = focusedDisabledBorder
         )
 
-    internal fun glow(
-        enabled: Boolean,
-        focused: Boolean,
-        pressed: Boolean,
-        glow: ClickableSurfaceGlow
-    ): Glow {
-        return if (enabled) {
-            when {
-                pressed -> glow.pressedGlow
-                focused -> glow.focusedGlow
-                else -> glow.glow
-            }
-        } else {
-            Glow.None
-        }
-    }
-
     /**
      * Creates a [ClickableSurfaceGlow] that represents the default [Glow]s used in a Surface.
      *
@@ -504,123 +414,6 @@
             focusedSelectedGlow = focusedSelectedGlow,
             pressedSelectedGlow = pressedSelectedGlow
         )
-
-    internal fun shape(
-        enabled: Boolean,
-        focused: Boolean,
-        pressed: Boolean,
-        selected: Boolean,
-        shape: SelectableSurfaceShape
-    ): Shape {
-        return when {
-            enabled && selected && pressed -> shape.pressedSelectedShape
-            enabled && selected && focused -> shape.focusedSelectedShape
-            enabled && selected -> shape.selectedShape
-            enabled && pressed -> shape.pressedShape
-            enabled && focused -> shape.focusedShape
-            enabled -> shape.shape
-            !enabled && selected && focused -> shape.focusedSelectedDisabledShape
-            !enabled && selected -> shape.selectedDisabledShape
-            !enabled && focused -> shape.focusedDisabledShape
-            else -> shape.disabledShape
-        }
-    }
-
-    internal fun containerColor(
-        enabled: Boolean,
-        focused: Boolean,
-        pressed: Boolean,
-        selected: Boolean,
-        colors: SelectableSurfaceColors
-    ): Color {
-        return when {
-            enabled && selected && pressed -> colors.pressedSelectedContainerColor
-            enabled && selected && focused -> colors.focusedSelectedContainerColor
-            enabled && selected -> colors.selectedContainerColor
-            enabled && pressed -> colors.pressedContainerColor
-            enabled && focused -> colors.focusedContainerColor
-            enabled -> colors.containerColor
-            else -> colors.disabledContainerColor
-        }
-    }
-
-    internal fun contentColor(
-        enabled: Boolean,
-        focused: Boolean,
-        pressed: Boolean,
-        selected: Boolean,
-        colors: SelectableSurfaceColors
-    ): Color {
-        return when {
-            enabled && selected && pressed -> colors.pressedSelectedContentColor
-            enabled && selected && focused -> colors.focusedSelectedContentColor
-            enabled && selected -> colors.selectedContentColor
-            enabled && pressed -> colors.pressedContentColor
-            enabled && focused -> colors.focusedContentColor
-            enabled -> colors.contentColor
-            else -> colors.disabledContentColor
-        }
-    }
-
-    internal fun scale(
-        enabled: Boolean,
-        focused: Boolean,
-        pressed: Boolean,
-        selected: Boolean,
-        scale: SelectableSurfaceScale
-    ): Float {
-        return when {
-            enabled && selected && pressed -> scale.pressedSelectedScale
-            enabled && selected && focused -> scale.focusedSelectedScale
-            enabled && selected -> scale.selectedScale
-            enabled && pressed -> scale.pressedScale
-            enabled && focused -> scale.focusedScale
-            enabled -> scale.scale
-            !enabled && selected && focused -> scale.focusedSelectedDisabledScale
-            !enabled && selected -> scale.selectedDisabledScale
-            !enabled && focused -> scale.focusedDisabledScale
-            else -> scale.disabledScale
-        }
-    }
-
-    internal fun border(
-        enabled: Boolean,
-        focused: Boolean,
-        pressed: Boolean,
-        selected: Boolean,
-        border: SelectableSurfaceBorder
-    ): Border {
-        return when {
-            enabled && selected && pressed -> border.pressedSelectedBorder
-            enabled && selected && focused -> border.focusedSelectedBorder
-            enabled && selected -> border.selectedBorder
-            enabled && pressed -> border.pressedBorder
-            enabled && focused -> border.focusedBorder
-            enabled -> border.border
-            !enabled && selected && focused -> border.focusedSelectedDisabledBorder
-            !enabled && selected -> border.selectedDisabledBorder
-            !enabled && focused -> border.focusedDisabledBorder
-            else -> border.disabledBorder
-        }
-    }
-
-    internal fun glow(
-        enabled: Boolean,
-        focused: Boolean,
-        pressed: Boolean,
-        selected: Boolean,
-        glow: SelectableSurfaceGlow
-    ): Glow {
-        return when {
-            enabled && selected && pressed -> glow.pressedSelectedGlow
-            enabled && selected && focused -> glow.focusedSelectedGlow
-            enabled && selected -> glow.selectedGlow
-            enabled && pressed -> glow.pressedGlow
-            enabled && focused -> glow.focusedGlow
-            enabled -> glow.glow
-            else -> Glow.None
-        }
-    }
 }
 
 private const val DisabledContainerAlpha = 0.4f
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceGlow.kt b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceGlow.kt
index 115461d..112b6bb 100644
--- a/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceGlow.kt
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceGlow.kt
@@ -37,7 +37,8 @@
     shape: Shape,
     glow: Glow,
 ): Modifier {
-    val color = surfaceColorAtElevation(color = glow.elevationColor, elevation = glow.elevation)
+    val color =
+        calculateSurfaceColorAtElevation(color = glow.elevationColor, elevation = glow.elevation)
     val glowBlurRadiusPx = with(LocalDensity.current) { glow.elevation.toPx() }
 
     return then(
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceImpl.kt b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceImpl.kt
new file mode 100644
index 0000000..1806d50
--- /dev/null
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceImpl.kt
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.tv.material3
+
+import androidx.compose.animation.core.animateFloatAsState
+import androidx.compose.foundation.background
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.interaction.PressInteraction
+import androidx.compose.foundation.interaction.collectIsFocusedAsState
+import androidx.compose.foundation.interaction.collectIsPressedAsState
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.compositionLocalOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.composed
+import androidx.compose.ui.focus.onFocusChanged
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.input.key.NativeKeyEvent
+import androidx.compose.ui.input.key.onKeyEvent
+import androidx.compose.ui.platform.debugInspectorInfo
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.zIndex
+import kotlinx.coroutines.launch
+
+@Composable
+internal fun SurfaceImpl(
+    modifier: Modifier,
+    selected: Boolean,
+    enabled: Boolean,
+    shape: Shape,
+    color: Color,
+    contentColor: Color,
+    scale: Float,
+    border: Border,
+    glow: Glow,
+    tonalElevation: Dp,
+    interactionSource: MutableInteractionSource? = null,
+    content: @Composable (BoxScope.() -> Unit)
+) {
+    @Suppress("NAME_SHADOWING")
+    val interactionSource = interactionSource ?: remember { MutableInteractionSource() }
+    val focused by interactionSource.collectIsFocusedAsState()
+    val pressed by interactionSource.collectIsPressedAsState()
+
+    val surfaceAlpha =
+        calculateAlphaBasedOnState(
+            enabled = enabled,
+            focused = focused,
+            pressed = pressed,
+            selected = selected
+        )
+
+    val absoluteElevation = LocalAbsoluteTonalElevation.current + tonalElevation
+
+    CompositionLocalProvider(
+        LocalContentColor provides contentColor,
+        LocalAbsoluteTonalElevation provides absoluteElevation
+    ) {
+        val zIndex by
+            animateFloatAsState(
+                targetValue = if (focused) FocusedZIndex else NonFocusedZIndex,
+                label = "zIndex"
+            )
+
+        val backgroundColorByState =
+            calculateSurfaceColorAtElevation(
+                color = color,
+                elevation = LocalAbsoluteTonalElevation.current
+            )
+
+        Box(
+            modifier =
+                modifier
+                    .tvSurfaceScale(
+                        scale = scale,
+                        interactionSource = interactionSource,
+                    )
+                    .ifElse(API_28_OR_ABOVE, Modifier.tvSurfaceGlow(shape, glow))
+                    // Increasing the zIndex of this Surface when it is in the focused state to
+                    // avoid the glowIndication from being overlapped by subsequent items if
+                    // this Surface is inside a list composable (like a Row/Column).
+                    .zIndex(zIndex)
+                    .ifElse(border != Border.None, Modifier.tvSurfaceBorder(shape, border))
+                    .background(backgroundColorByState, shape)
+                    .graphicsLayer {
+                        this.alpha = surfaceAlpha
+                        this.shape = shape
+                        this.clip = true
+                    },
+            propagateMinConstraints = true
+        ) {
+            Box(
+                modifier =
+                    Modifier.graphicsLayer {
+                        this.alpha = if (!enabled) DisabledContentAlpha else EnabledContentAlpha
+                    },
+                content = content
+            )
+        }
+    }
+}
+
+internal fun Modifier.handleDPadEnter(
+    enabled: Boolean,
+    interactionSource: MutableInteractionSource,
+    onClick: (() -> Unit)? = null,
+    onLongClick: (() -> Unit)? = null,
+    selected: Boolean = false,
+) =
+    composed(
+        inspectorInfo =
+            debugInspectorInfo {
+                name = "handleDPadEnter"
+                properties["enabled"] = enabled
+                properties["interactionSource"] = interactionSource
+                properties["onClick"] = onClick
+                properties["onLongClick"] = onLongClick
+                properties["selected"] = selected
+            }
+    ) {
+        if (!enabled) return@composed this
+
+        val coroutineScope = rememberCoroutineScope()
+        val pressInteraction = remember { PressInteraction.Press(Offset.Zero) }
+        var isLongClick by remember { mutableStateOf(false) }
+        val isPressed by interactionSource.collectIsPressedAsState()
+
+        this.onFocusChanged {
+                if (!it.isFocused && isPressed) {
+                    coroutineScope.launch {
+                        interactionSource.emit(PressInteraction.Release(pressInteraction))
+                    }
+                }
+            }
+            .onKeyEvent { keyEvent ->
+                if (AcceptableEnterClickKeys.contains(keyEvent.nativeKeyEvent.keyCode)) {
+                    when (keyEvent.nativeKeyEvent.action) {
+                        NativeKeyEvent.ACTION_DOWN -> {
+                            when (keyEvent.nativeKeyEvent.repeatCount) {
+                                0 ->
+                                    coroutineScope.launch {
+                                        interactionSource.emit(pressInteraction)
+                                    }
+                                1 ->
+                                    onLongClick?.let {
+                                        isLongClick = true
+                                        coroutineScope.launch {
+                                            interactionSource.emit(
+                                                PressInteraction.Release(pressInteraction)
+                                            )
+                                        }
+                                        it.invoke()
+                                    }
+                            }
+                        }
+                        NativeKeyEvent.ACTION_UP -> {
+                            if (!isLongClick) {
+                                coroutineScope.launch {
+                                    interactionSource.emit(
+                                        PressInteraction.Release(pressInteraction)
+                                    )
+                                }
+                                onClick?.invoke()
+                            } else isLongClick = false
+                        }
+                    }
+                    return@onKeyEvent KeyEventPropagation.StopPropagation
+                }
+                KeyEventPropagation.ContinuePropagation
+            }
+    }
+
+private fun calculateAlphaBasedOnState(
+    enabled: Boolean,
+    focused: Boolean,
+    pressed: Boolean,
+    selected: Boolean
+): Float {
+    return when {
+        !enabled && pressed -> DisabledPressedStateAlpha
+        !enabled && focused -> DisabledFocusedStateAlpha
+        !enabled && selected -> DisabledSelectedStateAlpha
+        enabled -> EnabledContentAlpha
+        else -> DisabledDefaultStateAlpha
+    }
+}
+
+@Composable
+internal fun calculateSurfaceColorAtElevation(color: Color, elevation: Dp): Color {
+    return if (color == MaterialTheme.colorScheme.surface) {
+        MaterialTheme.colorScheme.surfaceColorAtElevation(elevation)
+    } else {
+        color
+    }
+}
+
+private const val DisabledPressedStateAlpha = 0.8f
+private const val DisabledFocusedStateAlpha = 0.8f
+private const val DisabledSelectedStateAlpha = 0.8f
+private const val DisabledDefaultStateAlpha = 0.6f
+
+private const val FocusedZIndex = 0.5f
+private const val NonFocusedZIndex = 0f
+
+private const val DisabledContentAlpha = 0.8f
+private const val EnabledContentAlpha = 1f
+
+private val AcceptableEnterClickKeys =
+    intArrayOf(
+        NativeKeyEvent.KEYCODE_DPAD_CENTER,
+        NativeKeyEvent.KEYCODE_ENTER,
+        NativeKeyEvent.KEYCODE_NUMPAD_ENTER
+    )
+
+/**
+ * CompositionLocal containing the current absolute elevation provided by Surface components. This
+ * absolute elevation is a sum of all the previous elevations. Absolute elevation is only used for
+ * calculating surface tonal colors, and is *not* used for drawing the shadow in a [SurfaceImpl].
+ */
+internal val LocalAbsoluteTonalElevation = compositionLocalOf { 0.dp }
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceSelectableUtils.kt b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceSelectableUtils.kt
new file mode 100644
index 0000000..444e80b
--- /dev/null
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/SurfaceSelectableUtils.kt
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.tv.material3
+
+import androidx.compose.foundation.focusable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.semantics.disabled
+import androidx.compose.ui.semantics.onClick
+import androidx.compose.ui.semantics.onLongClick
+import androidx.compose.ui.semantics.selected
+import androidx.compose.ui.semantics.semantics
+
+internal fun Modifier.tvSelectable(
+    enabled: Boolean,
+    selected: Boolean,
+    onClick: () -> Unit,
+    onLongClick: (() -> Unit)?,
+    interactionSource: MutableInteractionSource,
+) =
+    handleDPadEnter(
+            enabled = enabled,
+            interactionSource = interactionSource,
+            selected = selected,
+            onClick = onClick,
+            onLongClick = onLongClick
+        )
+        // We are not using "selectable" modifier here because if we set "enabled" to false
+        // then the Surface won't be focusable as well. But, in TV use case, a disabled surface
+        // should be focusable
+        .focusable(interactionSource = interactionSource)
+        .semantics(mergeDescendants = true) {
+            this.selected = selected
+            onClick {
+                onClick()
+                true
+            }
+            onLongClick {
+                onLongClick?.let { nnOnLongClick ->
+                    nnOnLongClick()
+                    return@onLongClick true
+                }
+                false
+            }
+            if (!enabled) {
+                disabled()
+            }
+        }
+
+internal fun SelectableSurfaceShape.currentShape(
+    enabled: Boolean,
+    focused: Boolean,
+    pressed: Boolean,
+    selected: Boolean,
+): Shape {
+    return when {
+        enabled && selected && pressed -> pressedSelectedShape
+        enabled && selected && focused -> focusedSelectedShape
+        enabled && selected -> selectedShape
+        enabled && pressed -> pressedShape
+        enabled && focused -> focusedShape
+        enabled -> shape
+        !enabled && selected && focused -> focusedSelectedDisabledShape
+        !enabled && selected -> selectedDisabledShape
+        !enabled && focused -> focusedDisabledShape
+        else -> disabledShape
+    }
+}
+
+internal fun SelectableSurfaceColors.currentContainerColor(
+    enabled: Boolean,
+    focused: Boolean,
+    pressed: Boolean,
+    selected: Boolean,
+): Color {
+    return when {
+        enabled && selected && pressed -> pressedSelectedContainerColor
+        enabled && selected && focused -> focusedSelectedContainerColor
+        enabled && selected -> selectedContainerColor
+        enabled && pressed -> pressedContainerColor
+        enabled && focused -> focusedContainerColor
+        enabled -> containerColor
+        else -> disabledContainerColor
+    }
+}
+
+internal fun SelectableSurfaceColors.currentContentColor(
+    enabled: Boolean,
+    focused: Boolean,
+    pressed: Boolean,
+    selected: Boolean,
+): Color {
+    return when {
+        enabled && selected && pressed -> pressedSelectedContentColor
+        enabled && selected && focused -> focusedSelectedContentColor
+        enabled && selected -> selectedContentColor
+        enabled && pressed -> pressedContentColor
+        enabled && focused -> focusedContentColor
+        enabled -> contentColor
+        else -> disabledContentColor
+    }
+}
+
+internal fun SelectableSurfaceScale.currentScale(
+    enabled: Boolean,
+    focused: Boolean,
+    pressed: Boolean,
+    selected: Boolean,
+): Float {
+    return when {
+        enabled && selected && pressed -> pressedSelectedScale
+        enabled && selected && focused -> focusedSelectedScale
+        enabled && selected -> selectedScale
+        enabled && pressed -> pressedScale
+        enabled && focused -> focusedScale
+        enabled -> scale
+        !enabled && selected && focused -> focusedSelectedDisabledScale
+        !enabled && selected -> selectedDisabledScale
+        !enabled && focused -> focusedDisabledScale
+        else -> disabledScale
+    }
+}
+
+internal fun SelectableSurfaceBorder.currentBorder(
+    enabled: Boolean,
+    focused: Boolean,
+    pressed: Boolean,
+    selected: Boolean,
+): Border {
+    return when {
+        enabled && selected && pressed -> pressedSelectedBorder
+        enabled && selected && focused -> focusedSelectedBorder
+        enabled && selected -> selectedBorder
+        enabled && pressed -> pressedBorder
+        enabled && focused -> focusedBorder
+        enabled -> border
+        !enabled && selected && focused -> focusedSelectedDisabledBorder
+        !enabled && selected -> selectedDisabledBorder
+        !enabled && focused -> focusedDisabledBorder
+        else -> disabledBorder
+    }
+}
+
+internal fun SelectableSurfaceGlow.currentGlow(
+    enabled: Boolean,
+    focused: Boolean,
+    pressed: Boolean,
+    selected: Boolean,
+): Glow {
+    return when {
+        enabled && selected && pressed -> pressedSelectedGlow
+        enabled && selected && focused -> focusedSelectedGlow
+        enabled && selected -> selectedGlow
+        enabled && pressed -> pressedGlow
+        enabled && focused -> focusedGlow
+        enabled -> glow
+        else -> Glow.None
+    }
+}
diff --git a/wear/compose/compose-foundation/api/current.txt b/wear/compose/compose-foundation/api/current.txt
index 1811b65..323abf7 100644
--- a/wear/compose/compose-foundation/api/current.txt
+++ b/wear/compose/compose-foundation/api/current.txt
@@ -621,8 +621,8 @@
     method public float getSwipeToDismissEdgeZoneFraction();
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.gestures.TargetedFlingBehavior snapFlingBehavior(androidx.wear.compose.foundation.pager.PagerState state, optional androidx.compose.foundation.pager.PagerSnapDistance pagerSnapDistance, optional androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float> decayAnimationSpec, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> snapAnimationSpec, optional @FloatRange(from=0.0, to=1.0) float snapPositionalThreshold);
     property public final int BeyondViewportPageCount;
+    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> SnapAnimationSpec;
     property public final float SwipeToDismissEdgeZoneFraction;
-    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> snapAnimationSpec;
     field public static final androidx.wear.compose.foundation.pager.PagerDefaults INSTANCE;
   }
 
diff --git a/wear/compose/compose-foundation/api/restricted_current.txt b/wear/compose/compose-foundation/api/restricted_current.txt
index 1811b65..323abf7 100644
--- a/wear/compose/compose-foundation/api/restricted_current.txt
+++ b/wear/compose/compose-foundation/api/restricted_current.txt
@@ -621,8 +621,8 @@
     method public float getSwipeToDismissEdgeZoneFraction();
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.gestures.TargetedFlingBehavior snapFlingBehavior(androidx.wear.compose.foundation.pager.PagerState state, optional androidx.compose.foundation.pager.PagerSnapDistance pagerSnapDistance, optional androidx.compose.animation.core.DecayAnimationSpec<java.lang.Float> decayAnimationSpec, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> snapAnimationSpec, optional @FloatRange(from=0.0, to=1.0) float snapPositionalThreshold);
     property public final int BeyondViewportPageCount;
+    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> SnapAnimationSpec;
     property public final float SwipeToDismissEdgeZoneFraction;
-    property public final androidx.compose.animation.core.AnimationSpec<java.lang.Float> snapAnimationSpec;
     field public static final androidx.wear.compose.foundation.pager.PagerDefaults INSTANCE;
   }
 
diff --git a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/pager/Pager.kt b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/pager/Pager.kt
index 5fbb2b7..0a6bd47 100644
--- a/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/pager/Pager.kt
+++ b/wear/compose/compose-foundation/src/main/java/androidx/wear/compose/foundation/pager/Pager.kt
@@ -301,7 +301,7 @@
         state: PagerState,
         pagerSnapDistance: PagerSnapDistance = PagerSnapDistance.atMost(1),
         decayAnimationSpec: DecayAnimationSpec<Float> = rememberSplineBasedDecay(),
-        snapAnimationSpec: AnimationSpec<Float> = PagerDefaults.snapAnimationSpec,
+        snapAnimationSpec: AnimationSpec<Float> = PagerDefaults.SnapAnimationSpec,
         @FloatRange(from = 0.0, to = 1.0) snapPositionalThreshold: Float = 0.5f
     ): TargetedFlingBehavior {
         return ComposePagerDefaults.flingBehavior(
@@ -323,7 +323,7 @@
      * The default spring animation used for the Pager's snap animation spec - a spring based
      * animation with medium-high stiffness and no bounce.
      */
-    public val snapAnimationSpec: AnimationSpec<Float> =
+    public val SnapAnimationSpec: AnimationSpec<Float> =
         spring(Spring.DampingRatioNoBouncy, MediumHighStiffness)
 
     /**
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 441f0c2..4c7576f 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
@@ -78,6 +78,11 @@
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 @Composable
 public fun isSmallScreen(): Boolean =
-    LocalConfiguration.current.screenWidthDp <= SMALL_SCREEN_WIDTH_DP
+    LocalConfiguration.current.screenWidthDp < LARGE_SCREEN_WIDTH_DP
 
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public const val SMALL_SCREEN_WIDTH_DP: Int = 225
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@Composable
+public fun isLargeScreen(): Boolean =
+    LocalConfiguration.current.screenWidthDp >= LARGE_SCREEN_WIDTH_DP
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public const val LARGE_SCREEN_WIDTH_DP: Int = 225
diff --git a/wear/compose/compose-material3/api/current.txt b/wear/compose/compose-material3/api/current.txt
index 23e0195..5cca753 100644
--- a/wear/compose/compose-material3/api/current.txt
+++ b/wear/compose/compose-material3/api/current.txt
@@ -477,7 +477,7 @@
   }
 
   public final class DatePickerKt {
-    method @RequiresApi(android.os.Build.VERSION_CODES.O) @androidx.compose.runtime.Composable public static void DatePicker(java.time.LocalDate initialDate, kotlin.jvm.functions.Function1<? super java.time.LocalDate,kotlin.Unit> onDatePicked, optional androidx.compose.ui.Modifier modifier, optional java.time.LocalDate? minValidDate, optional java.time.LocalDate? maxValidDate, optional int datePickerType, optional androidx.wear.compose.material3.DatePickerColors colors);
+    method @androidx.compose.runtime.Composable public static void DatePicker(java.time.LocalDate initialDate, kotlin.jvm.functions.Function1<? super java.time.LocalDate,kotlin.Unit> onDatePicked, optional androidx.compose.ui.Modifier modifier, optional java.time.LocalDate? minValidDate, optional java.time.LocalDate? maxValidDate, optional int datePickerType, optional androidx.wear.compose.material3.DatePickerColors colors);
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class DatePickerType {
@@ -575,12 +575,12 @@
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonShapes shapes(optional androidx.compose.ui.graphics.Shape shape);
     property public final float DefaultButtonSize;
     property public final float DefaultIconSize;
+    property public final float DisabledImageOpacity;
     property public final float ExtraSmallButtonSize;
     property public final float LargeButtonSize;
     property public final float LargeIconSize;
     property public final float SmallButtonSize;
     property public final float SmallIconSize;
-    property public final float disabledImageOpacity;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.shape.CornerBasedShape pressedShape;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.shape.RoundedCornerShape shape;
     field public static final androidx.wear.compose.material3.IconButtonDefaults INSTANCE;
@@ -844,11 +844,11 @@
 
   public final class PickerGroupScope {
     ctor public PickerGroupScope();
-    method public boolean pickerGroupItem(androidx.wear.compose.material3.PickerState pickerState, optional androidx.compose.ui.Modifier modifier, optional String? contentDescription, optional androidx.compose.ui.focus.FocusRequester? focusRequester, optional kotlin.jvm.functions.Function0<kotlin.Unit> onSelected, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? readOnlyLabel, optional float spacing, kotlin.jvm.functions.Function3<? super androidx.wear.compose.material3.PickerScope,? super java.lang.Integer,? super java.lang.Boolean,kotlin.Unit> option);
+    method public boolean pickerGroupItem(androidx.wear.compose.material3.PickerState pickerState, optional androidx.compose.ui.Modifier modifier, optional String? contentDescription, optional androidx.compose.ui.focus.FocusRequester? focusRequester, optional kotlin.jvm.functions.Function0<kotlin.Unit> onSelected, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? readOnlyLabel, optional float verticalSpacing, kotlin.jvm.functions.Function3<? super androidx.wear.compose.material3.PickerScope,? super java.lang.Integer,? super java.lang.Boolean,kotlin.Unit> option);
   }
 
   public final class PickerKt {
-    method @androidx.compose.runtime.Composable public static void Picker(androidx.wear.compose.material3.PickerState state, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional boolean readOnly, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? readOnlyLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit> onSelected, optional float spacing, optional @FloatRange(from=0.0, to=0.5) float gradientRatio, optional long gradientColor, optional boolean userScrollEnabled, optional androidx.wear.compose.foundation.rotary.RotaryScrollableBehavior? rotaryScrollableBehavior, kotlin.jvm.functions.Function2<? super androidx.wear.compose.material3.PickerScope,? super java.lang.Integer,kotlin.Unit> option);
+    method @androidx.compose.runtime.Composable public static void Picker(androidx.wear.compose.material3.PickerState state, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional boolean readOnly, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? readOnlyLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit> onSelected, optional float verticalSpacing, optional @FloatRange(from=0.0, to=0.5) float gradientRatio, optional long gradientColor, optional boolean userScrollEnabled, optional androidx.wear.compose.foundation.rotary.RotaryScrollableBehavior? rotaryScrollableBehavior, kotlin.jvm.functions.Function2<? super androidx.wear.compose.material3.PickerScope,? super java.lang.Integer,kotlin.Unit> option);
     method @androidx.compose.runtime.Composable public static androidx.wear.compose.material3.PickerState rememberPickerState(@IntRange(from=1L) int initialNumberOfOptions, optional @IntRange(from=0L) int initiallySelectedIndex, optional boolean shouldRepeatOptions);
   }
 
@@ -1622,7 +1622,7 @@
   }
 
   public final class TimePickerKt {
-    method @RequiresApi(android.os.Build.VERSION_CODES.O) @androidx.compose.runtime.Composable public static void TimePicker(java.time.LocalTime initialTime, kotlin.jvm.functions.Function1<? super java.time.LocalTime,kotlin.Unit> onTimePicked, optional androidx.compose.ui.Modifier modifier, optional int timePickerType, optional androidx.wear.compose.material3.TimePickerColors colors);
+    method @androidx.compose.runtime.Composable public static void TimePicker(java.time.LocalTime initialTime, kotlin.jvm.functions.Function1<? super java.time.LocalTime,kotlin.Unit> onTimePicked, optional androidx.compose.ui.Modifier modifier, optional int timePickerType, optional androidx.wear.compose.material3.TimePickerColors colors);
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class TimePickerType {
diff --git a/wear/compose/compose-material3/api/restricted_current.txt b/wear/compose/compose-material3/api/restricted_current.txt
index 23e0195..5cca753 100644
--- a/wear/compose/compose-material3/api/restricted_current.txt
+++ b/wear/compose/compose-material3/api/restricted_current.txt
@@ -477,7 +477,7 @@
   }
 
   public final class DatePickerKt {
-    method @RequiresApi(android.os.Build.VERSION_CODES.O) @androidx.compose.runtime.Composable public static void DatePicker(java.time.LocalDate initialDate, kotlin.jvm.functions.Function1<? super java.time.LocalDate,kotlin.Unit> onDatePicked, optional androidx.compose.ui.Modifier modifier, optional java.time.LocalDate? minValidDate, optional java.time.LocalDate? maxValidDate, optional int datePickerType, optional androidx.wear.compose.material3.DatePickerColors colors);
+    method @androidx.compose.runtime.Composable public static void DatePicker(java.time.LocalDate initialDate, kotlin.jvm.functions.Function1<? super java.time.LocalDate,kotlin.Unit> onDatePicked, optional androidx.compose.ui.Modifier modifier, optional java.time.LocalDate? minValidDate, optional java.time.LocalDate? maxValidDate, optional int datePickerType, optional androidx.wear.compose.material3.DatePickerColors colors);
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class DatePickerType {
@@ -575,12 +575,12 @@
     method @androidx.compose.runtime.Composable public androidx.wear.compose.material3.IconButtonShapes shapes(optional androidx.compose.ui.graphics.Shape shape);
     property public final float DefaultButtonSize;
     property public final float DefaultIconSize;
+    property public final float DisabledImageOpacity;
     property public final float ExtraSmallButtonSize;
     property public final float LargeButtonSize;
     property public final float LargeIconSize;
     property public final float SmallButtonSize;
     property public final float SmallIconSize;
-    property public final float disabledImageOpacity;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.shape.CornerBasedShape pressedShape;
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.shape.RoundedCornerShape shape;
     field public static final androidx.wear.compose.material3.IconButtonDefaults INSTANCE;
@@ -844,11 +844,11 @@
 
   public final class PickerGroupScope {
     ctor public PickerGroupScope();
-    method public boolean pickerGroupItem(androidx.wear.compose.material3.PickerState pickerState, optional androidx.compose.ui.Modifier modifier, optional String? contentDescription, optional androidx.compose.ui.focus.FocusRequester? focusRequester, optional kotlin.jvm.functions.Function0<kotlin.Unit> onSelected, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? readOnlyLabel, optional float spacing, kotlin.jvm.functions.Function3<? super androidx.wear.compose.material3.PickerScope,? super java.lang.Integer,? super java.lang.Boolean,kotlin.Unit> option);
+    method public boolean pickerGroupItem(androidx.wear.compose.material3.PickerState pickerState, optional androidx.compose.ui.Modifier modifier, optional String? contentDescription, optional androidx.compose.ui.focus.FocusRequester? focusRequester, optional kotlin.jvm.functions.Function0<kotlin.Unit> onSelected, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? readOnlyLabel, optional float verticalSpacing, kotlin.jvm.functions.Function3<? super androidx.wear.compose.material3.PickerScope,? super java.lang.Integer,? super java.lang.Boolean,kotlin.Unit> option);
   }
 
   public final class PickerKt {
-    method @androidx.compose.runtime.Composable public static void Picker(androidx.wear.compose.material3.PickerState state, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional boolean readOnly, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? readOnlyLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit> onSelected, optional float spacing, optional @FloatRange(from=0.0, to=0.5) float gradientRatio, optional long gradientColor, optional boolean userScrollEnabled, optional androidx.wear.compose.foundation.rotary.RotaryScrollableBehavior? rotaryScrollableBehavior, kotlin.jvm.functions.Function2<? super androidx.wear.compose.material3.PickerScope,? super java.lang.Integer,kotlin.Unit> option);
+    method @androidx.compose.runtime.Composable public static void Picker(androidx.wear.compose.material3.PickerState state, String? contentDescription, optional androidx.compose.ui.Modifier modifier, optional boolean readOnly, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit>? readOnlyLabel, optional kotlin.jvm.functions.Function0<kotlin.Unit> onSelected, optional float verticalSpacing, optional @FloatRange(from=0.0, to=0.5) float gradientRatio, optional long gradientColor, optional boolean userScrollEnabled, optional androidx.wear.compose.foundation.rotary.RotaryScrollableBehavior? rotaryScrollableBehavior, kotlin.jvm.functions.Function2<? super androidx.wear.compose.material3.PickerScope,? super java.lang.Integer,kotlin.Unit> option);
     method @androidx.compose.runtime.Composable public static androidx.wear.compose.material3.PickerState rememberPickerState(@IntRange(from=1L) int initialNumberOfOptions, optional @IntRange(from=0L) int initiallySelectedIndex, optional boolean shouldRepeatOptions);
   }
 
@@ -1622,7 +1622,7 @@
   }
 
   public final class TimePickerKt {
-    method @RequiresApi(android.os.Build.VERSION_CODES.O) @androidx.compose.runtime.Composable public static void TimePicker(java.time.LocalTime initialTime, kotlin.jvm.functions.Function1<? super java.time.LocalTime,kotlin.Unit> onTimePicked, optional androidx.compose.ui.Modifier modifier, optional int timePickerType, optional androidx.wear.compose.material3.TimePickerColors colors);
+    method @androidx.compose.runtime.Composable public static void TimePicker(java.time.LocalTime initialTime, kotlin.jvm.functions.Function1<? super java.time.LocalTime,kotlin.Unit> onTimePicked, optional androidx.compose.ui.Modifier modifier, optional int timePickerType, optional androidx.wear.compose.material3.TimePickerColors colors);
   }
 
   @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class TimePickerType {
diff --git a/wear/compose/compose-material3/benchmark/build.gradle b/wear/compose/compose-material3/benchmark/build.gradle
index 836aa4e..9a1b2f5 100644
--- a/wear/compose/compose-material3/benchmark/build.gradle
+++ b/wear/compose/compose-material3/benchmark/build.gradle
@@ -35,7 +35,7 @@
     compileSdk = 35
 
     defaultConfig {
-        minSdk = 25
+        minSdk = 30
     }
     buildTypes.configureEach {
         consumerProguardFiles "benchmark-proguard-rules.pro"
diff --git a/wear/compose/compose-material3/build.gradle b/wear/compose/compose-material3/build.gradle
index f0c49b7..df4dcfa 100644
--- a/wear/compose/compose-material3/build.gradle
+++ b/wear/compose/compose-material3/build.gradle
@@ -72,7 +72,7 @@
     compileSdk = 35
 
     defaultConfig {
-        minSdk = 25
+        minSdk = 30
     }
     // Use Robolectric 4.+
     testOptions.unitTests.includeAndroidResources = true
diff --git a/wear/compose/compose-material3/integration-tests/build.gradle b/wear/compose/compose-material3/integration-tests/build.gradle
index 956afb7..85e2742 100644
--- a/wear/compose/compose-material3/integration-tests/build.gradle
+++ b/wear/compose/compose-material3/integration-tests/build.gradle
@@ -55,7 +55,7 @@
 android {
     compileSdk = 35
     defaultConfig {
-        minSdk = 25
+        minSdk = 30
     }
     namespace = "androidx.wear.compose.material3.demos"
 }
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/AlertDialogDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/AlertDialogDemo.kt
index 1392baa..e6afaee 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/AlertDialogDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/AlertDialogDemo.kt
@@ -193,7 +193,7 @@
         item {
             Button(
                 modifier = Modifier.fillMaxWidth(),
-                onClick = {},
+                onClick = { showDialog = false },
                 label = { Text("While using app") },
                 icon = { Icon(Icons.Filled.Check, "Check") }
             )
@@ -201,7 +201,7 @@
         item {
             FilledTonalButton(
                 modifier = Modifier.fillMaxWidth(),
-                onClick = {},
+                onClick = { showDialog = false },
                 label = { Text("Ask every time") },
                 icon = { Icon(Icons.Filled.Check, "Check") }
             )
@@ -209,7 +209,7 @@
         item {
             FilledTonalButton(
                 modifier = Modifier.fillMaxWidth(),
-                onClick = {},
+                onClick = { showDialog = false },
                 label = { Text("Don't allow") },
                 icon = { Icon(Icons.Filled.Check, "Check") }
             )
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ButtonDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ButtonDemo.kt
index 67de2c9..41f1a43 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ButtonDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/ButtonDemo.kt
@@ -409,7 +409,7 @@
                 modifier = Modifier.fillMaxWidth()
             )
         }
-        item { ListHeader { Text("3 Slot Button)") } }
+        item { ListHeader { Text("3 Slot Button") } }
         item { OutlinedButtonSample() }
         item {
             OutlinedButton(
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemos.kt
similarity index 97%
rename from wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemo.kt
rename to wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemos.kt
index 3f132df..5f9c200 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/CardDemos.kt
@@ -74,12 +74,24 @@
         item { CardWithMultipleImagesDemo() }
         item { OutlinedCardSample() }
         item { VerticallyCenteredBaseCard() }
+    }
+}
+
+@Composable
+fun AppCardDemo() {
+    ScalingLazyDemo {
         item { ListHeader { Text("App card") } }
         item { AppCardSample() }
         item { AppCardWithIconSample() }
         item { AppCardWithImageSample() }
         item { AppCardWithMultipleImagesDemo() }
         item { OutlinedAppCardSample() }
+    }
+}
+
+@Composable
+fun TitleCardDemo() {
+    ScalingLazyDemo {
         item { ListHeader { Text("Title card") } }
         item { TitleCardSample() }
         item { TitleCardWithSubtitleDemo() }
@@ -90,6 +102,12 @@
         item { OutlinedTitleCardSample() }
         item { OutlinedTitleCardWithSubtitleDemo() }
         item { OutlinedTitleCardWithSubtitleAndTimeDemo() }
+    }
+}
+
+@Composable
+fun ImageCardDemo() {
+    ScalingLazyDemo {
         item { ListHeader { Text("Image card") } }
         item { TitleCardWithImageBackgroundSample() }
     }
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/DatePickerDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/DatePickerDemo.kt
index 548b1eb..0c304d1 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/DatePickerDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/DatePickerDemo.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3.demos
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.material.icons.Icons
@@ -43,7 +41,6 @@
 import java.time.format.DateTimeFormatter
 import java.time.format.FormatStyle
 
-@RequiresApi(Build.VERSION_CODES.O)
 val DatePickerDemos =
     listOf(
         ComposableDemo("Date Year-Month-Day") { DatePickerYearMonthDaySample() },
@@ -54,7 +51,6 @@
         ComposableDemo("Past only") { DatePickerPastOnlyDemo() },
     )
 
-@RequiresApi(Build.VERSION_CODES.O)
 @Composable
 fun DatePickerDemo(datePickerType: DatePickerType) {
     var showDatePicker by remember { mutableStateOf(true) }
@@ -89,7 +85,6 @@
     }
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 @Composable
 fun DatePickerPastOnlyDemo() {
     val currentDate = LocalDate.now()
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TimePickerDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TimePickerDemo.kt
index 20d4ca7..7a1f55b 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TimePickerDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/TimePickerDemo.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3.demos
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.material.icons.Icons
@@ -41,7 +39,6 @@
 import java.time.LocalTime
 import java.time.format.DateTimeFormatter
 
-@RequiresApi(Build.VERSION_CODES.O)
 val TimePickerDemos =
     listOf(
         ComposableDemo("Time HH:MM:SS") { TimePickerWithSecondsSample() },
@@ -50,7 +47,6 @@
         ComposableDemo("Time System time format") { TimePickerSample() },
     )
 
-@RequiresApi(Build.VERSION_CODES.O)
 @Composable
 private fun TimePicker24hWithoutSecondsDemo() {
     var showTimePicker by remember { mutableStateOf(true) }
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 a30a8f5..b4828a7 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
@@ -115,7 +115,15 @@
                 ),
                 ComposableDemo("List Header") { Centralize { ListHeaderSample() } },
                 Material3DemoCategory("Time Text", TimeTextDemos),
-                ComposableDemo("Card") { CardDemo() },
+                Material3DemoCategory(
+                    "Card",
+                    listOf(
+                        ComposableDemo("Card") { CardDemo() },
+                        ComposableDemo("App Card") { AppCardDemo() },
+                        ComposableDemo("Title Card") { TitleCardDemo() },
+                        ComposableDemo("Image Card") { ImageCardDemo() },
+                    )
+                ),
                 ComposableDemo("Text Toggle Button") { TextToggleButtonDemo() },
                 ComposableDemo("Icon Toggle Button") { IconToggleButtonDemo() },
                 ComposableDemo("Checkbox Button") { CheckboxButtonDemo() },
@@ -127,13 +135,8 @@
                 Material3DemoCategory("Stepper", StepperDemos),
                 Material3DemoCategory("Slider", SliderDemos),
                 Material3DemoCategory("Picker", PickerDemos),
-                // Requires API level 26 or higher due to java.time dependency.
-                *(if (Build.VERSION.SDK_INT >= 26)
-                    arrayOf(
-                        Material3DemoCategory("TimePicker", TimePickerDemos),
-                        Material3DemoCategory("DatePicker", DatePickerDemos)
-                    )
-                else emptyArray<Material3DemoCategory>()),
+                Material3DemoCategory("TimePicker", TimePickerDemos),
+                Material3DemoCategory("DatePicker", DatePickerDemos),
                 Material3DemoCategory("Progress Indicator", ProgressIndicatorDemos),
                 Material3DemoCategory("Scroll Indicator", ScrollIndicatorDemos),
                 Material3DemoCategory("Placeholder", PlaceholderDemos),
diff --git a/wear/compose/compose-material3/macrobenchmark-common/build.gradle b/wear/compose/compose-material3/macrobenchmark-common/build.gradle
index 92093e3..51008d8 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/build.gradle
+++ b/wear/compose/compose-material3/macrobenchmark-common/build.gradle
@@ -10,7 +10,7 @@
     compileSdk = 35
 
     defaultConfig {
-        minSdk = 25
+        minSdk = 30
     }
 
     buildTypes.configureEach {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/DatePickerBenchmark.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/DatePickerBenchmark.kt
index 51431d0..3177504 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/DatePickerBenchmark.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/DatePickerBenchmark.kt
@@ -16,9 +16,7 @@
 
 package androidx.wear.compose.material3.macrobenchmark.common
 
-import android.os.Build
 import android.os.SystemClock
-import androidx.annotation.RequiresApi
 import androidx.benchmark.macro.MacrobenchmarkScope
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.material.icons.Icons
@@ -43,7 +41,6 @@
 import java.time.format.DateTimeFormatter
 import java.time.format.FormatStyle
 
-@RequiresApi(Build.VERSION_CODES.O)
 object DatePickerBenchmark : MacrobenchmarkScreen {
     override val content: @Composable (BoxScope.() -> Unit)
         get() = {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/TimePickerBenchmark.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/TimePickerBenchmark.kt
index 7d15ce7..1c9103b 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/TimePickerBenchmark.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/TimePickerBenchmark.kt
@@ -16,9 +16,7 @@
 
 package androidx.wear.compose.material3.macrobenchmark.common
 
-import android.os.Build
 import android.os.SystemClock
-import androidx.annotation.RequiresApi
 import androidx.benchmark.macro.MacrobenchmarkScope
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
@@ -26,7 +24,6 @@
 import androidx.wear.compose.material3.TimePickerType
 import java.time.LocalTime
 
-@RequiresApi(Build.VERSION_CODES.O)
 object TimePickerBenchmark : MacrobenchmarkScreen {
     override val content: @Composable (BoxScope.() -> Unit)
         get() = {
diff --git a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/DatePickerScreen.kt b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/DatePickerScreen.kt
index 04e9ca75..8e3685d1 100644
--- a/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/DatePickerScreen.kt
+++ b/wear/compose/compose-material3/macrobenchmark-common/src/main/java/androidx/wear/compose/material3/macrobenchmark/common/baselineprofile/DatePickerScreen.kt
@@ -16,7 +16,6 @@
 
 package androidx.wear.compose.material3.macrobenchmark.common.baselineprofile
 
-import android.os.Build
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
 import androidx.wear.compose.material3.DatePicker
@@ -28,16 +27,14 @@
     object : MacrobenchmarkScreen {
         override val content: @Composable BoxScope.() -> Unit
             get() = {
-                if (Build.VERSION.SDK_INT >= 26) {
-                    val minDate = LocalDate.of(2022, 10, 15)
-                    val maxDate = LocalDate.of(2025, 2, 4)
-                    DatePicker(
-                        initialDate = LocalDate.of(2024, 9, 2),
-                        onDatePicked = {},
-                        minValidDate = minDate,
-                        maxValidDate = maxDate,
-                        datePickerType = DatePickerType.YearMonthDay
-                    )
-                }
+                val minDate = LocalDate.of(2022, 10, 15)
+                val maxDate = LocalDate.of(2025, 2, 4)
+                DatePicker(
+                    initialDate = LocalDate.of(2024, 9, 2),
+                    onDatePicked = {},
+                    minValidDate = minDate,
+                    maxValidDate = maxDate,
+                    datePickerType = DatePickerType.YearMonthDay
+                )
             }
     }
diff --git a/wear/compose/compose-material3/macrobenchmark-target/build.gradle b/wear/compose/compose-material3/macrobenchmark-target/build.gradle
index 82913ef..eaba1e7 100644
--- a/wear/compose/compose-material3/macrobenchmark-target/build.gradle
+++ b/wear/compose/compose-material3/macrobenchmark-target/build.gradle
@@ -46,4 +46,4 @@
     implementation(project(":wear:compose:compose-material3-macrobenchmark-common"))
 }
 
-android.defaultConfig.minSdk = 25
+android.defaultConfig.minSdk = 30
diff --git a/wear/compose/compose-material3/macrobenchmark-target/src/main/AndroidManifest.xml b/wear/compose/compose-material3/macrobenchmark-target/src/main/AndroidManifest.xml
index 6ec1884..a68fd42 100644
--- a/wear/compose/compose-material3/macrobenchmark-target/src/main/AndroidManifest.xml
+++ b/wear/compose/compose-material3/macrobenchmark-target/src/main/AndroidManifest.xml
@@ -130,8 +130,7 @@
         <activity
             android:name=".DatePickerActivity"
             android:theme="@style/AppTheme"
-            android:exported="true"
-            tools:targetApi="o">
+            android:exported="true">
             <intent-filter>
                 <action android:name=
                     "androidx.wear.compose.material3.macrobenchmark.target.DATE_PICKER_ACTIVITY" />
@@ -270,8 +269,7 @@
         <activity
             android:name=".TimePickerActivity"
             android:theme="@style/AppTheme"
-            android:exported="true"
-            tools:targetApi="o">
+            android:exported="true">
             <intent-filter>
                 <action android:name=
                     "androidx.wear.compose.material3.macrobenchmark.target.TIME_PICKER_ACTIVITY" />
diff --git a/wear/compose/compose-material3/macrobenchmark-target/src/main/java/androidx/wear/compose/material3/macrobenchmark/target/DatePickerActivity.kt b/wear/compose/compose-material3/macrobenchmark-target/src/main/java/androidx/wear/compose/material3/macrobenchmark/target/DatePickerActivity.kt
index d18d12d..4256fdc 100644
--- a/wear/compose/compose-material3/macrobenchmark-target/src/main/java/androidx/wear/compose/material3/macrobenchmark/target/DatePickerActivity.kt
+++ b/wear/compose/compose-material3/macrobenchmark-target/src/main/java/androidx/wear/compose/material3/macrobenchmark/target/DatePickerActivity.kt
@@ -16,9 +16,6 @@
 
 package androidx.wear.compose.material3.macrobenchmark.target
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.wear.compose.material3.macrobenchmark.common.DatePickerBenchmark
 
-@RequiresApi(Build.VERSION_CODES.O)
 class DatePickerActivity : BenchmarkBaseActivity(DatePickerBenchmark)
diff --git a/wear/compose/compose-material3/macrobenchmark-target/src/main/java/androidx/wear/compose/material3/macrobenchmark/target/TimePickerActivity.kt b/wear/compose/compose-material3/macrobenchmark-target/src/main/java/androidx/wear/compose/material3/macrobenchmark/target/TimePickerActivity.kt
index e134065..6188ab7 100644
--- a/wear/compose/compose-material3/macrobenchmark-target/src/main/java/androidx/wear/compose/material3/macrobenchmark/target/TimePickerActivity.kt
+++ b/wear/compose/compose-material3/macrobenchmark-target/src/main/java/androidx/wear/compose/material3/macrobenchmark/target/TimePickerActivity.kt
@@ -16,9 +16,6 @@
 
 package androidx.wear.compose.material3.macrobenchmark.target
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.wear.compose.material3.macrobenchmark.common.TimePickerBenchmark
 
-@RequiresApi(Build.VERSION_CODES.O)
 class TimePickerActivity : BenchmarkBaseActivity(TimePickerBenchmark)
diff --git a/wear/compose/compose-material3/macrobenchmark/build.gradle b/wear/compose/compose-material3/macrobenchmark/build.gradle
index 1940fef..bcab91e 100644
--- a/wear/compose/compose-material3/macrobenchmark/build.gradle
+++ b/wear/compose/compose-material3/macrobenchmark/build.gradle
@@ -23,7 +23,7 @@
 android {
     compileSdk = 35
     defaultConfig {
-        minSdk = 29
+        minSdk = 30
     }
     namespace = "androidx.wear.compose.material3.macrobenchmark"
     targetProjectPath = ":wear:compose:compose-material3-macrobenchmark-target"
diff --git a/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/DatePickerBenchmarkTest.kt b/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/DatePickerBenchmarkTest.kt
index 3316732..b9abc42 100644
--- a/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/DatePickerBenchmarkTest.kt
+++ b/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/DatePickerBenchmarkTest.kt
@@ -16,15 +16,12 @@
 
 package androidx.wear.compose.material3.macrobenchmark
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.benchmark.macro.CompilationMode
 import androidx.test.filters.LargeTest
 import androidx.wear.compose.material3.macrobenchmark.common.DatePickerBenchmark
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
-@RequiresApi(Build.VERSION_CODES.O)
 @LargeTest
 @RunWith(Parameterized::class)
 class DatePickerBenchmarkTest(compilationMode: CompilationMode) :
diff --git a/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/TimePickerBenchmarkTest.kt b/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/TimePickerBenchmarkTest.kt
index 52a5a38..1533377 100644
--- a/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/TimePickerBenchmarkTest.kt
+++ b/wear/compose/compose-material3/macrobenchmark/src/main/java/androidx/wear/compose/material3/macrobenchmark/TimePickerBenchmarkTest.kt
@@ -16,15 +16,12 @@
 
 package androidx.wear.compose.material3.macrobenchmark
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.benchmark.macro.CompilationMode
 import androidx.test.filters.LargeTest
 import androidx.wear.compose.material3.macrobenchmark.common.TimePickerBenchmark
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
-@RequiresApi(Build.VERSION_CODES.O)
 @LargeTest
 @RunWith(Parameterized::class)
 class TimePickerBenchmarkTest(compilationMode: CompilationMode) :
diff --git a/wear/compose/compose-material3/samples/build.gradle b/wear/compose/compose-material3/samples/build.gradle
index 02e43d8..814f3e9 100644
--- a/wear/compose/compose-material3/samples/build.gradle
+++ b/wear/compose/compose-material3/samples/build.gradle
@@ -50,7 +50,7 @@
 android {
     compileSdk = 35
     defaultConfig {
-        minSdk = 25
+        minSdk = 30
     }
     namespace = "androidx.wear.compose.material3.samples"
 }
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/IconButtonSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/IconButtonSample.kt
index ac422ad..2cbf874 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/IconButtonSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/IconButtonSample.kt
@@ -119,7 +119,7 @@
             contentDescription = null,
             contentScale = ContentScale.Crop,
             modifier =
-                if (enabled) Modifier else Modifier.alpha(IconButtonDefaults.disabledImageOpacity)
+                if (enabled) Modifier else Modifier.alpha(IconButtonDefaults.DisabledImageOpacity)
         )
     }
 }
diff --git a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/PickerSample.kt b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/PickerSample.kt
index 6fa0d34c..3705257 100644
--- a/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/PickerSample.kt
+++ b/wear/compose/compose-material3/samples/src/main/java/androidx/wear/compose/material3/samples/PickerSample.kt
@@ -64,7 +64,7 @@
     val contentDescription by remember { derivedStateOf { "${state.selectedOptionIndex + 1}" } }
     Picker(
         state = state,
-        spacing = 4.dp,
+        verticalSpacing = 4.dp,
         contentDescription = contentDescription,
     ) {
         Button(
@@ -84,7 +84,7 @@
     Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
         Picker(
             state = state,
-            spacing = 4.dp,
+            verticalSpacing = 4.dp,
             contentDescription = contentDescription,
         ) {
             Button(
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt
index a6c2594..722675e 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ButtonTest.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
@@ -279,7 +277,6 @@
         assertEquals(expectedSecondaryTextStyle, actualSecondaryLabelTextStyle)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun default_shape_is_stadium() {
         rule.isShape(
@@ -292,7 +289,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_shape_override() {
         val shape = CutCornerShape(4.dp)
@@ -380,7 +376,6 @@
             .assertTopPositionInRootIsEqualTo((itemBounds.height - iconBounds.height) / 2)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_base_button_correct_colors() {
         rule.verifyButtonColors(
@@ -390,7 +385,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_base_button_correct_colors() {
         rule.verifyButtonColors(
@@ -404,7 +398,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_filled_tonal_base_button_correct_colors() {
         rule.verifyButtonColors(
@@ -415,7 +408,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_filled_tonal_base_button_correct_colors() {
         rule.verifyButtonColors(
@@ -430,7 +422,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_button_correct_filled_variant_colors() {
         rule.verifyButtonColors(
@@ -441,7 +432,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_button_correct_filled_variant_colors() {
         rule.verifyButtonColors(
@@ -456,7 +446,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_outlined_base_button_correct_colors() {
         rule.verifyButtonColors(
@@ -467,7 +456,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_outlined_base_button_correct_colors() {
         rule.verifyButtonColors(
@@ -480,7 +468,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_child_base_button_correct_colors() {
         rule.verifyButtonColors(
@@ -491,7 +478,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_child_base_button_correct_colors() {
         rule.verifyButtonColors(
@@ -504,7 +490,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_three_slot_button_correct_colors() {
         rule.verifyThreeSlotButtonColors(
@@ -514,7 +499,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_three_slot_button_correct_colors() {
         rule.verifyThreeSlotButtonColors(
@@ -524,7 +508,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_filled_tonal_three_slot_button_correct_colors() {
         rule.verifyThreeSlotButtonColors(
@@ -534,7 +517,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_filled_tonal_three_slot_button_correct_colors() {
         rule.verifyThreeSlotButtonColors(
@@ -544,7 +526,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_outlined_three_slot_button_correct_colors() {
         rule.verifyThreeSlotButtonColors(
@@ -554,7 +535,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_outlined_three_slot_button_correct_colors() {
         rule.verifyThreeSlotButtonColors(
@@ -564,7 +544,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_child_three_slot_button_correct_colors() {
         rule.verifyThreeSlotButtonColors(
@@ -574,7 +553,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_child_three_slot_button_correct_colors() {
         rule.verifyThreeSlotButtonColors(
@@ -584,7 +562,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_outlined_button_correct_border_colors() {
         val status = Status.Enabled
@@ -596,7 +573,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_outlined_button_correct_border_colors() {
         val status = Status.Disabled
@@ -618,7 +594,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun overrides_enabled_outlined_button_border_color() {
         val status = Status.Enabled
@@ -640,7 +615,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun overrides_disabled_outlined_button_border_color() {
         val status = Status.Disabled
@@ -778,7 +752,6 @@
             )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_compact_button_correct_colors() {
         rule.verifyCompactButtonColors(
@@ -787,7 +760,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_compact_button_correct_colors() {
         rule.verifyCompactButtonColors(
@@ -796,7 +768,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_filled_tonal_compact_button_correct_colors() {
         rule.verifyCompactButtonColors(
@@ -805,7 +776,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_filled_tonal_compact_button_correct_colors() {
         rule.verifyCompactButtonColors(
@@ -814,7 +784,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_outlined_compact_button_correct_colors() {
         rule.verifyCompactButtonColors(
@@ -823,7 +792,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_outlined_compact_button_correct_colors() {
         rule.verifyCompactButtonColors(
@@ -832,7 +800,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_child_compact_button_correct_colors() {
         rule.verifyCompactButtonColors(
@@ -841,7 +808,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_child_compact_button_correct_colors() {
         rule.verifyCompactButtonColors(
@@ -1262,7 +1228,6 @@
     }
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 private fun ComposeContentTestRule.verifyButtonColors(
     status: Status,
     expectedContainerColor: @Composable () -> Color,
@@ -1352,7 +1317,6 @@
     return actualContentColor
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 private fun ComposeContentTestRule.verifyThreeSlotButtonColors(
     status: Status,
     expectedColor: @Composable () -> ButtonColors,
@@ -1455,7 +1419,6 @@
     return ThreeSlotButtonColors(actualLabelColor, actualSecondaryLabelColor, actualIconColor)
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 internal fun ComposeContentTestRule.verifyButtonBorderColor(
     expectedBorderColor: @Composable () -> Color,
     content: @Composable (Modifier) -> Unit
@@ -1473,7 +1436,6 @@
     onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(finalExpectedBorderColor)
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 private fun ComposeContentTestRule.isShape(
     expectedShape: Shape,
     colors: @Composable () -> ButtonColors,
@@ -1507,7 +1469,6 @@
         )
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 private fun ComposeContentTestRule.verifyCompactButtonColors(
     status: Status,
     colors: @Composable () -> ButtonColors
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardTest.kt
index 98b8213..62c88b3 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardTest.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
@@ -542,7 +540,6 @@
         assertEquals(expectedTitleColor, actualTitleColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun outlined_card_has_outlined_border_and_transparent() {
         val outlineColor = Color.Red
@@ -566,7 +563,6 @@
             .assertColorInPercentageRange(testBackground, 93f..97f)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun outlined_titlecard_has_outlined_border_and_transparent() {
         val outlineColor = Color.Red
@@ -592,7 +588,6 @@
             .assertColorInPercentageRange(testBackground, 93f..97f)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun outlined_appcard_has_outlined_border_and_transparent() {
         val outlineColor = Color.Red
@@ -696,7 +691,6 @@
         assertEquals(expectedContentTextStyle, actuaContentTextStyle)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun outlined_app_card_gives_correct_text_style_base() {
         var actualAppTextStyle = TextStyle.Default
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CheckboxButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CheckboxButtonTest.kt
index 3b4f228..0c34439 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CheckboxButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CheckboxButtonTest.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.BoxScope
@@ -551,7 +549,6 @@
         Assert.assertEquals(2, secondaryLabelMaxLines)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun checkbox_button_allows_checked_background_color_override() =
         verifyToggleButtonBackgroundColor(
@@ -560,7 +557,6 @@
             expectedColor = CHECKED_COLOR
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun checkbox_button_allows_unchecked_background_color_override() =
         verifyToggleButtonBackgroundColor(
@@ -569,7 +565,6 @@
             expectedColor = UNCHECKED_COLOR
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun split_checkbox_button_allows_checked_background_color_override() =
         verifySplitToggleButtonBackgroundColor(
@@ -578,7 +573,6 @@
             expectedColor = CHECKED_COLOR
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun split_checkbox_button_allows_unchecked_background_color_override() =
         verifySplitToggleButtonBackgroundColor(
@@ -587,55 +581,46 @@
             expectedColor = UNCHECKED_COLOR
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_checkbox_button_colors_enabled_and_checked() {
         rule.verifyCheckboxButtonColors(checked = true, enabled = true)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_checkbox_button_colors_enabled_and_unchecked() {
         rule.verifyCheckboxButtonColors(checked = false, enabled = true)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_checkbox_button_colors_disabled_and_checked() {
         rule.verifyCheckboxButtonColors(checked = true, enabled = false)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_checkbox_button_colors_disabled_and_unchecked() {
         rule.verifyCheckboxButtonColors(checked = false, enabled = false)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_split_checkbox_button_colors_enabled_and_checked() {
         rule.verifySplitCheckboxButtonColors(checked = true, enabled = true)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_split_checkbox_button_colors_enabled_and_unchecked() {
         rule.verifySplitCheckboxButtonColors(checked = false, enabled = true)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_split_checkbox_button_colors_disabled_and_checked() {
         rule.verifySplitCheckboxButtonColors(checked = true, enabled = false)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_split_checkbox_button_colors_disabled_and_unchecked() {
         rule.verifySplitCheckboxButtonColors(checked = false, enabled = false)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun checkbox_checked_colors_are_customisable() {
         val boxColor = Color.Green
@@ -658,7 +643,6 @@
         checkboxImage.assertContainsColor(checkmarkColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun checkbox_unchecked_colors_are_customisable() {
         // NB checkmark is erased during animation, so we don't test uncheckedCheckmarkColor
@@ -680,7 +664,6 @@
         checkboxImage.assertContainsColor(boxColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun disabled_checkbox_checked_colors_are_customisable() {
         val boxColor = Color.Green
@@ -703,7 +686,6 @@
         checkboxImage.assertContainsColor(checkmarkColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun disabled_checkbox_unchecked_colors_are_customisable() {
         // NB checkmark is erased during animation, so we don't test uncheckedCheckmarkColor
@@ -725,7 +707,6 @@
         checkboxImage.assertContainsColor(boxColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun verifyToggleButtonBackgroundColor(
         checked: Boolean,
         enabled: Boolean,
@@ -748,7 +729,6 @@
         rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun verifySplitToggleButtonBackgroundColor(
         checked: Boolean,
         enabled: Boolean,
@@ -817,7 +797,6 @@
         toggleContentDescription = "description",
     )
 
-@RequiresApi(Build.VERSION_CODES.O)
 private fun ComposeContentTestRule.verifyCheckboxButtonColors(enabled: Boolean, checked: Boolean) {
     val testBackgroundColor = Color.White
     var expectedContainerColor = Color.Transparent
@@ -857,7 +836,6 @@
         )
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 private fun ComposeContentTestRule.verifySplitCheckboxButtonColors(
     enabled: Boolean,
     checked: Boolean
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CurvedTextTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CurvedTextTest.kt
index f42a497..2d16628 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CurvedTextTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CurvedTextTest.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.testutils.assertContainsColor
 import androidx.compose.testutils.assertDoesNotContainColor
@@ -37,7 +35,6 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
-@RequiresApi(Build.VERSION_CODES.O)
 class CurvedTextTest {
     @get:Rule val rule = createComposeRule()
 
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/DatePickerScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/DatePickerScreenshotTest.kt
index 057cf19..fba9409 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/DatePickerScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/DatePickerScreenshotTest.kt
@@ -17,7 +17,6 @@
 package androidx.wear.compose.material3
 
 import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.testutils.assertAgainstGolden
@@ -308,7 +307,6 @@
             )
             .onFirst()
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun ComposeContentTestRule.verifyDatePickerScreenshot(
         testName: TestName,
         screenshotRule: AndroidXScreenshotTestRule,
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
index ae3a245..bfc2adb 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/IconButtonTest.kt
@@ -21,6 +21,7 @@
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.shape.CircleShape
 import androidx.compose.foundation.shape.CutCornerShape
 import androidx.compose.foundation.shape.RoundedCornerShape
@@ -30,6 +31,7 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.asAndroidBitmap
 import androidx.compose.ui.hapticfeedback.HapticFeedbackType
 import androidx.compose.ui.platform.LocalHapticFeedback
 import androidx.compose.ui.platform.testTag
@@ -49,7 +51,9 @@
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.performClick
 import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.dp
+import androidx.core.graphics.get
 import androidx.wear.compose.material3.IconButtonDefaults.DefaultButtonSize
 import androidx.wear.compose.material3.IconButtonDefaults.ExtraSmallButtonSize
 import androidx.wear.compose.material3.IconButtonDefaults.LargeButtonSize
@@ -560,6 +564,41 @@
     }
 
     @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun button_positioned_correctly() {
+        rule.setContentWithTheme {
+            Box(Modifier.testTag(TEST_TAG).background(Color.Black).padding(1.dp)) {
+                IconButton(
+                    onClick = {},
+                    colors =
+                        IconButtonDefaults.filledIconButtonColors(containerColor = Color.Green),
+                    modifier = Modifier.size(27.dp, 20.dp)
+                ) {}
+            }
+        }
+
+        val bitmap = rule.onNodeWithTag(TEST_TAG).captureToImage().asAndroidBitmap()
+        val spaces =
+            listOf(IntOffset(0, 1), IntOffset(0, -1), IntOffset(1, 0), IntOffset(-1, 0)).map {
+                direction ->
+                var position =
+                    IntOffset(
+                        (bitmap.width - 1) * (1 - direction.x) / 2,
+                        (bitmap.height - 1) * (1 - direction.y) / 2,
+                    )
+                var distance = 0
+                while (bitmap[position.x, position.y] == android.graphics.Color.BLACK) {
+                    position += direction
+                    distance++
+                }
+                distance
+            }
+        assert(spaces.all { it == spaces[0] }) {
+            "All spaces around the button should be equal, where: ${spaces.joinToString()}"
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.O)
     private fun ComposeContentTestRule.verifyIconButtonColors(
         status: Status,
         colors: @Composable () -> IconButtonColors,
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 374863e..0d321cd 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
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
@@ -241,7 +239,6 @@
         rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOff()
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun is_circular_under_ltr() =
         rule.isShape(
@@ -258,7 +255,6 @@
             )
         }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun is_circular_under_rtl() =
         rule.isShape(
@@ -275,7 +271,6 @@
             )
         }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_shape_overrides() =
         rule.isShape(
@@ -389,7 +384,6 @@
             )
         }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_checked_primary_colors() =
         rule.verifyIconToggleButtonColors(
@@ -400,7 +394,6 @@
             contentColor = { MaterialTheme.colorScheme.onPrimary }
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_unchecked_surface_colors() =
         rule.verifyIconToggleButtonColors(
@@ -411,7 +404,6 @@
             contentColor = { MaterialTheme.colorScheme.onSurfaceVariant }
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_unchecked_surface_colors_with_alpha() =
         rule.verifyIconToggleButtonColors(
@@ -424,7 +416,6 @@
             contentColor = { MaterialTheme.colorScheme.onSurface.toDisabledColor() }
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_primary_checked_contrasting_content_color() =
         rule.verifyIconToggleButtonColors(
@@ -437,7 +428,6 @@
             contentColor = { MaterialTheme.colorScheme.onSurface.toDisabledColor() },
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_checked_background_override() {
         val overrideColor = Color.Yellow
@@ -455,7 +445,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_checked_content_override() {
         val overrideColor = Color.Green
@@ -471,7 +460,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_unchecked_background_override() {
         val overrideColor = Color.Red
@@ -489,7 +477,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_unchecked_content_override() {
         val overrideColor = Color.Green
@@ -507,7 +494,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_checked_disabled_background_override() {
         val overrideColor = Color.Yellow
@@ -526,7 +512,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_checked_disabled_content_override() {
         val overrideColor = Color.Green
@@ -547,7 +532,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_unchecked_disabled_background_override() {
         val overrideColor = Color.Red
@@ -566,7 +550,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_unchecked_disabled_content_override() {
         val overrideColor = Color.Green
@@ -623,7 +606,6 @@
             .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, overrideRole))
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun animates_corners_to_75_percent_on_click() {
         val uncheckedShape = RoundedCornerShape(20.dp)
@@ -659,7 +641,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun changes_unchecked_to_checked_shape_on_click() {
         val uncheckedShape = RoundedCornerShape(20.dp)
@@ -683,7 +664,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun changes_checked_to_unchecked_shape_on_click() {
         val uncheckedShape = RoundedCornerShape(10.dp)
@@ -708,7 +688,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun changes_to_unchecked_pressed_shape_when_pressed_on_unchecked() {
         val uncheckedShape = RoundedCornerShape(20.dp)
@@ -741,7 +720,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun changes_to_checked_pressed_shape_when_pressed_on_checked() {
         val uncheckedShape = RoundedCornerShape(10.dp)
@@ -774,7 +752,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun ComposeContentTestRule.verifyIconToggleButtonColors(
         status: Status,
         checked: Boolean,
@@ -801,7 +778,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun changes_unchecked_to_checked_shape_when_checked_changed() {
         val uncheckedShape = RoundedCornerShape(20.dp)
@@ -826,7 +802,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun changes_checked_to_unchecked_shape_when_checked_changed() {
         val uncheckedShape = RoundedCornerShape(20.dp)
@@ -858,7 +833,6 @@
             .value
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun ComposeContentTestRule.isShape(
         shape: Shape = CircleShape,
         layoutDirection: LayoutDirection,
@@ -889,7 +863,6 @@
             )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun ComposeContentTestRule.verifyColors(
         expectedContainerColor: @Composable () -> Color,
         expectedContentColor: @Composable () -> Color,
@@ -911,7 +884,6 @@
         onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(finalExpectedContainerColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun ComposeContentTestRule.verifyCheckedStateChange(
         updateState: () -> Unit,
         startShape: Shape,
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/LevelIndicatorTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/LevelIndicatorTest.kt
index 4645acf..bda423d 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/LevelIndicatorTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/LevelIndicatorTest.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
@@ -48,7 +46,6 @@
         rule.onNodeWithTag(TEST_TAG).assertExists()
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_indicator_correct_color() {
         var expectedColor: Color = Color.Unspecified
@@ -61,7 +58,6 @@
         rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_track_correct_color() {
         var expectedColor: Color = Color.Unspecified
@@ -74,7 +70,6 @@
         rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_indicator_custom_color() {
         val customColor = Color.Red
@@ -89,7 +84,6 @@
         rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(customColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_track_custom_color() {
         val customColor = Color.Red
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
index d0333da..d990dc1a 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/Material3Test.kt
@@ -17,8 +17,6 @@
 package androidx.wear.compose.material3
 
 import android.content.res.Configuration
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Arrangement
@@ -244,7 +242,6 @@
     onNodeWithTag(TEST_TAG).assertHeightIsEqualTo(expectedSize).assertWidthIsEqualTo(expectedSize)
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 internal fun ComposeContentTestRule.verifyColors(
     status: Status,
     expectedContainerColor: @Composable () -> Color,
@@ -379,7 +376,6 @@
     }
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 internal fun ComposeContentTestRule.verifyScreenshot(
     methodName: String,
     screenshotRule: AndroidXScreenshotTestRule,
@@ -400,7 +396,6 @@
     onNodeWithTag(testTag).captureToImage().assertAgainstGolden(screenshotRule, methodName)
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 fun ComposeContentTestRule.verifyRoundedButtonTapAnimationEnd(
     baseShape: RoundedCornerShape,
     pressedShape: RoundedCornerShape,
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PageIndicatorTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PageIndicatorTest.kt
index 203c279..84d54f5 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PageIndicatorTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PageIndicatorTest.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.testutils.assertContainsColor
 import androidx.compose.testutils.assertDoesNotContainColor
 import androidx.compose.ui.Modifier
@@ -35,7 +33,6 @@
 import org.junit.Rule
 import org.junit.Test
 
-@RequiresApi(Build.VERSION_CODES.O)
 class PageIndicatorTest {
     @get:Rule val rule = createComposeRule()
 
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PickerTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PickerTest.kt
index 3ec10a6..b2de4c0 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PickerTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PickerTest.kt
@@ -212,7 +212,7 @@
                     modifier =
                         Modifier.testTag(TEST_TAG)
                             .requiredSize(itemSizeDp * 11 + separationDp * 10 * separationSign),
-                    spacing = separationDp * separationSign
+                    verticalSpacing = separationDp * separationSign
                 ) {
                     Box(Modifier.requiredSize(itemSizeDp))
                 }
@@ -760,7 +760,7 @@
                         Modifier.testTag(TEST_TAG)
                             .requiredSize(pickerHeightDp)
                             .onGloballyPositioned { pickerLayoutCoordinates = it },
-                    spacing = separationDp * separationSign,
+                    verticalSpacing = separationDp * separationSign,
                     readOnly = readOnly.value,
                     contentDescription = CONTENT_DESCRIPTION,
                 ) { optionIndex ->
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PlaceholderTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PlaceholderTest.kt
index 3234616..e98e268 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PlaceholderTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/PlaceholderTest.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
@@ -43,7 +41,6 @@
 import org.junit.Rule
 import org.junit.Test
 
-@RequiresApi(Build.VERSION_CODES.O)
 class PlaceholderTest {
     @get:Rule val rule = createComposeRule()
 
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/RadioButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/RadioButtonTest.kt
index 4b6a973..44d9c68 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/RadioButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/RadioButtonTest.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.RowScope
@@ -585,7 +583,6 @@
         Assert.assertEquals(2, secondaryLabelMaxLines)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun radio_button_allows_checked_background_color_override() =
         verifyRadioButtonBackgroundColor(
@@ -594,7 +591,6 @@
             expectedColor = SELECTED_COLOR
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun radio_button_allows_unchecked_background_color_override() =
         verifyRadioButtonBackgroundColor(
@@ -603,7 +599,6 @@
             expectedColor = UNSELECTED_COLOR
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun split_radio_button_allows_checked_background_color_override() =
         verifySplitRadioButtonBackgroundColor(
@@ -612,7 +607,6 @@
             expectedColor = SELECTED_COLOR
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun split_radio_button_allows_unchecked_background_color_override() =
         verifySplitRadioButtonBackgroundColor(
@@ -621,7 +615,6 @@
             expectedColor = UNSELECTED_COLOR
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun verifyRadioButtonBackgroundColor(
         selected: Boolean,
         enabled: Boolean,
@@ -644,7 +637,6 @@
         rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun verifySplitRadioButtonBackgroundColor(
         selected: Boolean,
         enabled: Boolean,
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ScrollAwayTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ScrollAwayTest.kt
index 90674cb..9bcedf1 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ScrollAwayTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/ScrollAwayTest.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.ScrollState
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
@@ -61,7 +59,6 @@
 class ScrollAwayTest {
     @get:Rule val rule = createComposeRule()
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun showsTimeTextWithScalingLazyColumnInitially() {
         val timeTextColor = Color.Red
@@ -92,7 +89,6 @@
         rule.onNodeWithTag(TIME_TEXT_TAG).assertIsDisplayed()
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun showsTimeTextWithLazyColumnInitially() {
         val timeTextColor = Color.Red
@@ -105,7 +101,6 @@
         rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(timeTextColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun showsTimeTextWithColumnInitially() {
         val timeTextColor = Color.Red
@@ -118,7 +113,6 @@
         rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(timeTextColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun hidesTimeTextAfterScrollingScalingLazyColumn() {
         val timeTextColor = Color.Red
@@ -136,7 +130,6 @@
         rule.onNodeWithTag(TEST_TAG).captureToImage().assertDoesNotContainColor(timeTextColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun hidesTimeTextWithLazyColumn() {
         val timeTextColor = Color.Red
@@ -159,7 +152,6 @@
         rule.onNodeWithTag(TEST_TAG).captureToImage().assertDoesNotContainColor(timeTextColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun hidesTimeTextWithColumn() {
         val timeTextColor = Color.Red
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SwitchButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SwitchButtonTest.kt
index ec60445..f9dd312 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SwitchButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/SwitchButtonTest.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.BoxScope
@@ -547,7 +545,6 @@
         Assert.assertEquals(2, secondaryLabelMaxLines)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun switch_button_allows_checked_background_color_override() =
         verifySwitchButtonBackgroundColor(
@@ -556,7 +553,6 @@
             expectedColor = CHECKED_COLOR
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun switch_button_allows_unchecked_background_color_override() =
         verifySwitchButtonBackgroundColor(
@@ -565,7 +561,6 @@
             expectedColor = UNCHECKED_COLOR
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun split_switch_button_allows_checked_background_color_override() =
         verifySplitSwitchButtonBackgroundColor(
@@ -574,7 +569,6 @@
             expectedColor = CHECKED_COLOR
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun split_switch_button_allows_unchecked_background_color_override() =
         verifySplitSwitchButtonBackgroundColor(
@@ -583,55 +577,46 @@
             expectedColor = UNCHECKED_COLOR
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_switch_button_colors_enabled_and_checked() {
         rule.verifySwitchButtonColors(checked = true, enabled = true)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_switch_button_colors_enabled_and_unchecked() {
         rule.verifySwitchButtonColors(checked = false, enabled = true)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_switch_button_colors_disabled_and_checked() {
         rule.verifySwitchButtonColors(checked = true, enabled = false)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_switch_button_colors_disabled_and_unchecked() {
         rule.verifySwitchButtonColors(checked = false, enabled = false)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_split_switch_button_colors_enabled_and_checked() {
         rule.verifySplitToggleButtonColors(checked = true, enabled = true)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_split_switch_button_colors_enabled_and_unchecked() {
         rule.verifySplitToggleButtonColors(checked = false, enabled = true)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_split_switch_button_colors_disabled_and_checked() {
         rule.verifySplitToggleButtonColors(checked = true, enabled = false)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun verify_split_toggle_button_colors_disabled_and_unchecked() {
         rule.verifySplitToggleButtonColors(checked = false, enabled = false)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun switch_checked_colors_are_customisable() {
         val thumbColor = Color.Green
@@ -660,7 +645,6 @@
         image.assertContainsColor(trackBorderColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun switch_unchecked_colors_are_customisable() {
         val thumbColor = Color.Green
@@ -688,7 +672,6 @@
         image.assertContainsColor(trackBorderColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun disabled_switch_checked_colors_are_customisable() {
         val thumbColor = Color.Green
@@ -717,7 +700,6 @@
         image.assertContainsColor(trackBorderColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun disabled_switch_unchecked_colors_are_customisable() {
         val thumbColor = Color.Green
@@ -742,7 +724,6 @@
         image.assertContainsColor(trackBorderColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun verifySwitchButtonBackgroundColor(
         checked: Boolean,
         enabled: Boolean,
@@ -765,7 +746,6 @@
         rule.onNodeWithTag(TEST_TAG).captureToImage().assertContainsColor(expectedColor)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun verifySplitSwitchButtonBackgroundColor(
         checked: Boolean,
         enabled: Boolean,
@@ -834,7 +814,6 @@
         toggleContentDescription = "description",
     )
 
-@RequiresApi(Build.VERSION_CODES.O)
 private fun ComposeContentTestRule.verifySwitchButtonColors(enabled: Boolean, checked: Boolean) {
     val testBackgroundColor = Color.White
     var expectedContainerColor = Color.Transparent
@@ -874,7 +853,6 @@
         )
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 private fun ComposeContentTestRule.verifySplitToggleButtonColors(
     enabled: Boolean,
     checked: Boolean
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt
index 884643a..ddfc1b0 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TextButtonTest.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.padding
@@ -337,7 +335,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun default_shape_is_circular() {
         rule.isShape(
@@ -350,7 +347,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_shape_override() {
         val shape = CutCornerShape(4.dp)
@@ -367,7 +363,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_text_button_colors() {
         rule.verifyTextButtonColors(
@@ -378,7 +373,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_text_button_colors() {
         rule.verifyTextButtonColors(
@@ -391,7 +385,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_filled_text_button_colors() {
         rule.verifyTextButtonColors(
@@ -402,7 +395,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_filled_text_button_colors() {
         rule.verifyTextButtonColors(
@@ -417,7 +409,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_filled_variant_text_button_colors() {
         rule.verifyTextButtonColors(
@@ -428,7 +419,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_filled_variant_text_button_colors() {
         rule.verifyTextButtonColors(
@@ -443,7 +433,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_filled_tonal_text_button_colors() {
         rule.verifyTextButtonColors(
@@ -454,7 +443,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_filled_tonal_text_button_colors() {
         rule.verifyTextButtonColors(
@@ -469,7 +457,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_outlined_text_button_colors() {
         rule.verifyTextButtonColors(
@@ -480,7 +467,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_outlined_text_button_colors() {
         rule.verifyTextButtonColors(
@@ -493,7 +479,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_enabled_outlined_text_button_correct_border_colors() {
         val status = Status.Enabled
@@ -511,7 +496,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_outlined_text_button_correct_border_colors() {
         val status = Status.Disabled
@@ -531,7 +515,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun overrides_outlined_text_button_border_color() {
         val status = Status.Enabled
@@ -553,7 +536,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun animates_corners_to_75_percent_on_click() {
         val baseShape = RoundedCornerShape(20.dp)
@@ -575,7 +557,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun ComposeContentTestRule.verifyTextButtonColors(
         status: Status,
         colors: @Composable () -> TextButtonColors,
@@ -603,7 +584,6 @@
     }
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 private fun ComposeContentTestRule.isShape(
     expectedShape: Shape,
     colors: @Composable () -> TextButtonColors,
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 fae1c050..0d1b67e 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
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
@@ -243,7 +241,6 @@
         rule.onNodeWithTag(TEST_TAG).assertIsOff().performClick().assertIsOff()
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun is_circular_under_ltr() =
         rule.isShape(
@@ -260,7 +257,6 @@
             )
         }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun is_circular_under_rtl() =
         rule.isShape(
@@ -277,7 +273,6 @@
             )
         }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_shape_overrides() =
         rule.isShape(
@@ -379,7 +374,6 @@
             )
         }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_checked_primary_colors() =
         rule.verifyTextToggleButtonColors(
@@ -390,7 +384,6 @@
             contentColor = { MaterialTheme.colorScheme.onPrimary }
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_unchecked_surface_colors() =
         rule.verifyTextToggleButtonColors(
@@ -401,7 +394,6 @@
             contentColor = { MaterialTheme.colorScheme.onSurfaceVariant }
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_unchecked_surface_colors_with_alpha() =
         rule.verifyTextToggleButtonColors(
@@ -414,7 +406,6 @@
             contentColor = { MaterialTheme.colorScheme.onSurface.toDisabledColor() }
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun gives_disabled_primary_checked_contrasting_content_color() =
         rule.verifyTextToggleButtonColors(
@@ -427,7 +418,6 @@
             contentColor = { MaterialTheme.colorScheme.onSurface.toDisabledColor() },
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_checked_background_override() {
         val override = Color.Yellow
@@ -443,7 +433,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_checked_content_override() {
         val override = Color.Green
@@ -459,7 +448,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_unchecked_background_override() {
         val override = Color.Red
@@ -475,7 +463,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_unchecked_content_override() {
         val override = Color.Green
@@ -491,7 +478,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_checked_disabled_background_override() {
         val override = Color.Yellow
@@ -509,7 +495,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_checked_disabled_content_override() {
         val override = Color.Green
@@ -530,7 +515,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_unchecked_disabled_background_override() {
         val override = Color.Red
@@ -549,7 +533,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun allows_custom_unchecked_disabled_content_override() {
         val override = Color.Green
@@ -607,7 +590,6 @@
             .assert(SemanticsMatcher.expectValue(SemanticsProperties.Role, overrideRole))
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun animates_corners_to_75_percent_on_click() {
         val uncheckedShape = RoundedCornerShape(20.dp)
@@ -643,7 +625,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun changes_unchecked_to_checked_shape_on_click() {
         val uncheckedShape = RoundedCornerShape(20.dp)
@@ -667,7 +648,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun changes_checked_to_unchecked_shape_on_click() {
         val uncheckedShape = RoundedCornerShape(10.dp)
@@ -691,7 +671,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun changes_to_unchecked_pressed_shape_when_pressed_on_unchecked() {
         val uncheckedShape = RoundedCornerShape(20.dp)
@@ -724,7 +703,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun changes_to_checked_pressed_shape_when_pressed_on_checked() {
         val uncheckedShape = RoundedCornerShape(10.dp)
@@ -757,7 +735,6 @@
         }
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun changes_unchecked_to_checked_shape_when_checked_changed() {
         val uncheckedShape = RoundedCornerShape(20.dp)
@@ -782,7 +759,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     @Test
     fun changes_checked_to_unchecked_shape_when_checked_changed() {
         val uncheckedShape = RoundedCornerShape(20.dp)
@@ -814,7 +790,6 @@
             .value
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun ComposeContentTestRule.verifyTextToggleButtonColors(
         status: Status,
         checked: Boolean,
@@ -841,7 +816,6 @@
         )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun ComposeContentTestRule.isShape(
         shape: Shape = CircleShape,
         layoutDirection: LayoutDirection,
@@ -872,7 +846,6 @@
             )
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun ComposeContentTestRule.verifyColors(
         expectedContainerColor: @Composable () -> Color,
         expectedContentColor: @Composable () -> Color,
@@ -906,7 +879,6 @@
             .assertWidthIsEqualTo(expectedSize)
     }
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun ComposeContentTestRule.verifyCheckedStateChange(
         updateState: () -> Unit,
         startShape: Shape,
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimePickerScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimePickerScreenshotTest.kt
index 3511aa3..1e80a24 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimePickerScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/TimePickerScreenshotTest.kt
@@ -17,7 +17,6 @@
 package androidx.wear.compose.material3
 
 import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.runtime.Composable
 import androidx.compose.testutils.assertAgainstGolden
 import androidx.compose.ui.Modifier
@@ -139,7 +138,6 @@
             }
         )
 
-    @RequiresApi(Build.VERSION_CODES.O)
     private fun ComposeContentTestRule.verifyTimePickerScreenshot(
         methodName: String,
         screenshotRule: AndroidXScreenshotTestRule,
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/DatePicker.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/DatePicker.kt
index 140437a..af2130d 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/DatePicker.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/DatePicker.kt
@@ -16,9 +16,7 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
 import android.text.format.DateFormat
-import androidx.annotation.RequiresApi
 import androidx.compose.animation.core.Animatable
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Arrangement
@@ -69,6 +67,7 @@
 import androidx.wear.compose.material3.internal.Strings.Companion.PickerNextButtonContentDescription
 import androidx.wear.compose.material3.internal.getString
 import androidx.wear.compose.material3.tokens.DatePickerTokens
+import androidx.wear.compose.materialcore.isLargeScreen
 import java.time.LocalDate
 import java.time.format.DateTimeFormatter
 
@@ -97,7 +96,6 @@
  * @param datePickerType The different [DatePickerType] supported by this [DatePicker].
  * @param colors [DatePickerColors] to be applied to the DatePicker.
  */
-@RequiresApi(Build.VERSION_CODES.O)
 @Composable
 public fun DatePicker(
     initialDate: LocalDate,
@@ -137,7 +135,7 @@
             mutableStateOf(initiallySelectedIndex)
         }
 
-    val isLargeScreen = LocalConfiguration.current.screenWidthDp > 225
+    val isLargeScreen = isLargeScreen()
     val labelTextStyle =
         if (isLargeScreen) {
             DatePickerTokens.LabelLargeTypography.value
@@ -356,7 +354,7 @@
                                                     )
                                                 }
                                             ),
-                                        spacing = spacing,
+                                        verticalSpacing = spacing,
                                     )
                                 DatePickerOption.Month ->
                                     pickerGroupItem(
@@ -384,7 +382,7 @@
                                                     )
                                                 }
                                             ),
-                                        spacing = spacing,
+                                        verticalSpacing = spacing,
                                     )
                                 DatePickerOption.Year ->
                                     pickerGroupItem(
@@ -411,7 +409,7 @@
                                                     )
                                                 }
                                             ),
-                                        spacing = spacing,
+                                        verticalSpacing = spacing,
                                     )
                             }
                         }
@@ -698,7 +696,6 @@
         else -> arrayOf(DatePickerOption.Day, DatePickerOption.Month, DatePickerOption.Year)
     }
 
-@RequiresApi(Build.VERSION_CODES.O)
 private fun verifyDates(
     date: LocalDate,
     minDate: LocalDate,
@@ -708,7 +705,6 @@
     require(date in minDate..maxDate) { "date should lie between minDate and maxDate" }
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 private fun getMonthNames(pattern: String): List<String> {
     val monthFormatter = DateTimeFormatter.ofPattern(pattern)
     val months = 1..12
@@ -734,7 +730,6 @@
     }
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 private class DatePickerState(
     initialDate: LocalDate,
     initialDateMinYear: LocalDate?,
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 1570ab7..031c926 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
@@ -383,7 +383,7 @@
         @Composable get() = MaterialTheme.shapes.small
 
     /** Recommended alpha to apply to an IconButton with Image content with disabled */
-    public val disabledImageOpacity: Float = DisabledContentAlpha
+    public val DisabledImageOpacity: Float = DisabledContentAlpha
 
     /**
      * Creates a [IconButtonShapes] with a static [shape].
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/InteractiveComponentSize.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/InteractiveComponentSize.kt
index 0109ce9..4d8f874 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/InteractiveComponentSize.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/InteractiveComponentSize.kt
@@ -92,8 +92,8 @@
             }
 
         return layout(width, height) {
-            val centerX = ((width - placeable.width) / 2f).roundToInt()
-            val centerY = ((height - placeable.height) / 2f).roundToInt()
+            val centerX = ((width - placeable.width - 1) / 2f).roundToInt()
+            val centerY = ((height - placeable.height - 1) / 2f).roundToInt()
             placeable.place(centerX, centerY)
         }
     }
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Picker.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Picker.kt
index c584d90..c7cf091 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Picker.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Picker.kt
@@ -109,8 +109,8 @@
  *   so it is recommended that the label is given [Alignment.TopCenter].
  * @param onSelected Action triggered when the Picker is selected by clicking. Used by accessibility
  *   semantics, which facilitates implementation of multi-picker screens.
- * @param spacing The amount of spacing in [Dp] between items. Can be negative, which can be useful
- *   for Text if it has plenty of whitespace.
+ * @param verticalSpacing The amount of vertical spacing in [Dp] between items. Can be negative,
+ *   which can be useful for Text if it has plenty of whitespace.
  * @param gradientRatio The size relative to the Picker height that the top and bottom gradients
  *   take. These gradients blur the picker content on the top and bottom. The default is 0.33, so
  *   the top 1/3 and the bottom 1/3 of the picker are taken by gradients. Should be between 0.0 and
@@ -135,7 +135,7 @@
     readOnly: Boolean = false,
     readOnlyLabel: @Composable (BoxScope.() -> Unit)? = null,
     onSelected: () -> Unit = {},
-    spacing: Dp = 0.dp,
+    verticalSpacing: Dp = 0.dp,
     @FloatRange(from = 0.0, to = 0.5) gradientRatio: Float = PickerDefaults.GradientRatio,
     gradientColor: Color = MaterialTheme.colorScheme.background,
     userScrollEnabled: Boolean = true,
@@ -190,7 +190,7 @@
                                         val shimHeight =
                                             (size.height -
                                                 centerItem.unadjustedSize.toFloat() -
-                                                spacing.toPx()) / 2.0f
+                                                verticalSpacing.toPx()) / 2.0f
                                         drawShim(gradientColor, shimHeight)
                                     }
                                 }
@@ -220,7 +220,7 @@
             contentPadding = PaddingValues(0.dp),
             scalingParams = pickerScalingParams(),
             horizontalAlignment = Alignment.CenterHorizontally,
-            verticalArrangement = Arrangement.spacedBy(space = spacing),
+            verticalArrangement = Arrangement.spacedBy(space = verticalSpacing),
             flingBehavior = pickerFlingBehavior(state),
             autoCentering = AutoCenteringParams(itemIndex = 0),
             userScrollEnabled = userScrollEnabled
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/PickerGroup.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/PickerGroup.kt
index 6d22bd5..ece1094 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/PickerGroup.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/PickerGroup.kt
@@ -24,7 +24,6 @@
 import androidx.compose.foundation.layout.BoxScope
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
-import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.focusRequester
@@ -137,7 +136,7 @@
                             .focusRequester(focusRequester),
                     readOnlyLabel = pickerData.readOnlyLabel,
                     onSelected = pickerData.onSelected,
-                    spacing = pickerData.spacing,
+                    verticalSpacing = pickerData.verticalSpacing,
                     userScrollEnabled = !touchExplorationServicesEnabled || pickerSelected,
                     option = { optionIndex ->
                         with(pickerData) {
@@ -187,8 +186,8 @@
      * @param focusRequester Optional [FocusRequester] for the [Picker]. If not provided, a local
      *   instance of [FocusRequester] will be created to handle the focus between different pickers.
      * @param onSelected Action triggered when the [Picker] is selected by clicking.
-     * @param spacing The amount of spacing in [Dp] between items. Can be negative, which can be
-     *   useful for Text if it has plenty of whitespace.
+     * @param verticalSpacing The amount of vertical spacing in [Dp] between items. Can be negative,
+     *   which can be useful for Text if it has plenty of whitespace.
      * @param readOnlyLabel A slot for providing a label, displayed above the selected option when
      *   the [Picker] is read-only. The label is overlaid with the currently selected option within
      *   a Box, so it is recommended that the label is given [Alignment.TopCenter].
@@ -202,7 +201,7 @@
         focusRequester: FocusRequester? = null,
         onSelected: () -> Unit = {},
         readOnlyLabel: @Composable (BoxScope.() -> Unit)? = null,
-        spacing: Dp = 0.dp,
+        verticalSpacing: Dp = 0.dp,
         option: @Composable PickerScope.(optionIndex: Int, pickerSelected: Boolean) -> Unit
     ): Boolean =
         items.add(
@@ -213,7 +212,7 @@
                 focusRequester,
                 onSelected,
                 readOnlyLabel,
-                spacing,
+                verticalSpacing,
                 option
             )
         )
@@ -226,7 +225,7 @@
     val focusRequester: FocusRequester? = null,
     val onSelected: () -> Unit = {},
     val readOnlyLabel: @Composable (BoxScope.() -> Unit)? = null,
-    val spacing: Dp = 0.dp,
+    val verticalSpacing: Dp = 0.dp,
     val option: @Composable PickerScope.(optionIndex: Int, pickerSelected: Boolean) -> Unit
 )
 
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScrollIndicator.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScrollIndicator.kt
index 9d805fe..816d82c 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScrollIndicator.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/ScrollIndicator.kt
@@ -68,6 +68,7 @@
 import androidx.wear.compose.foundation.lazy.inverseLerp
 import androidx.wear.compose.material3.ScrollIndicatorDefaults.maxSizeFraction
 import androidx.wear.compose.material3.ScrollIndicatorDefaults.minSizeFraction
+import androidx.wear.compose.materialcore.isLargeScreen
 import androidx.wear.compose.materialcore.isRoundDevice
 import androidx.wear.compose.materialcore.toRadians
 import kotlin.math.asin
@@ -248,8 +249,7 @@
     internal val indicatorWidth
         @Composable
         get(): Dp {
-            val screenHeight = LocalConfiguration.current.screenHeightDp
-            return if (screenHeight >= 225) 6.dp else 5.dp
+            return if (isLargeScreen()) 6.dp else 5.dp
         }
 
     internal val gapHeight = 3.dp
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TimePicker.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TimePicker.kt
index 54dc22e..01b7923 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TimePicker.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/TimePicker.kt
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.material3
 
-import android.os.Build
-import androidx.annotation.RequiresApi
 import androidx.compose.animation.core.Animatable
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Arrangement
@@ -68,6 +66,7 @@
 import androidx.wear.compose.material3.internal.getString
 import androidx.wear.compose.material3.tokens.TimePickerTokens
 import androidx.wear.compose.materialcore.is24HourFormat
+import androidx.wear.compose.materialcore.isLargeScreen
 import java.time.LocalTime
 import java.time.format.DateTimeFormatter
 import java.time.temporal.ChronoField
@@ -96,7 +95,6 @@
  *   whether to show seconds or AM/PM selector as well as hours and minutes.
  * @param colors [TimePickerColors] be applied to the TimePicker.
  */
-@RequiresApi(Build.VERSION_CODES.O)
 @Composable
 public fun TimePicker(
     initialTime: LocalTime,
@@ -246,7 +244,7 @@
                                     indexToText = { "%02d".format(if (is12hour) it + 1 else it) },
                                     optionHeight = styles.optionHeight,
                                 ),
-                            spacing = styles.optionSpacing
+                            verticalSpacing = styles.optionSpacing
                         )
 
                         // Minutes Picker
@@ -272,7 +270,7 @@
                                     unselectedContentColor = colors.unselectedPickerContentColor,
                                     optionHeight = styles.optionHeight,
                                 ),
-                            spacing = styles.optionSpacing
+                            verticalSpacing = styles.optionSpacing
                         )
 
                         // Seconds or Period picker
@@ -296,7 +294,7 @@
                                             colors.unselectedPickerContentColor,
                                         optionHeight = styles.optionHeight,
                                     ),
-                                spacing = styles.optionSpacing
+                                verticalSpacing = styles.optionSpacing
                             )
                         }
                     }
@@ -521,7 +519,7 @@
     timePickerType: TimePickerType,
     optionalThirdPicker: PickerData?
 ): TimePickerStyles {
-    val isLargeScreen = LocalConfiguration.current.screenWidthDp > 225
+    val isLargeScreen = isLargeScreen()
     val labelTextStyle =
         if (isLargeScreen) {
                 TimePickerTokens.LabelLargeTypography
@@ -595,7 +593,6 @@
 }
 
 /* Returns the picker data for the third column (AM/PM or seconds) based on the time picker type. */
-@RequiresApi(Build.VERSION_CODES.O)
 @Composable
 private fun getOptionalThirdPicker(
     timePickerType: TimePickerType,
diff --git a/wear/compose/integration-tests/demos/build.gradle b/wear/compose/integration-tests/demos/build.gradle
index 20bb8e8..a38ede8 100644
--- a/wear/compose/integration-tests/demos/build.gradle
+++ b/wear/compose/integration-tests/demos/build.gradle
@@ -25,9 +25,9 @@
     compileSdk = 35
     defaultConfig {
         applicationId = "androidx.wear.compose.integration.demos"
-        minSdk = 25
-        versionCode = 61
-        versionName = "1.61"
+        minSdk = 30
+        versionCode = 62
+        versionName = "1.62"
     }
 
     buildTypes {
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoActivity.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoActivity.kt
index 938f23f..883f184 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoActivity.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoActivity.kt
@@ -19,13 +19,11 @@
 import android.app.Activity
 import android.content.Context
 import android.content.Intent
-import android.os.Build
 import android.os.Bundle
 import android.view.View
 import androidx.activity.ComponentActivity
 import androidx.activity.OnBackPressedCallback
 import androidx.activity.OnBackPressedDispatcher
-import androidx.annotation.RequiresApi
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.getValue
@@ -55,7 +53,6 @@
     lateinit var hostView: View
     lateinit var focusManager: FocusManager
 
-    @RequiresApi(Build.VERSION_CODES.O)
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
 
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
index 1aa5314..169ba5bc 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
@@ -16,7 +16,6 @@
 
 package androidx.wear.compose.integration.demos
 
-import android.os.Build
 import androidx.compose.foundation.layout.padding
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -147,71 +146,65 @@
             ),
             DemoCategory(
                 "Picker",
-                if (Build.VERSION.SDK_INT > 25) {
-                    listOf(
-                        ComposableDemo("Time HH:MM:SS") { params ->
-                            var timePickerTime by remember { mutableStateOf(LocalTime.now()) }
-                            TimePicker(
-                                onTimeConfirm = {
-                                    timePickerTime = it
-                                    params.navigateBack()
-                                },
-                                time = timePickerTime,
-                            )
-                        },
-                        ComposableDemo("Time 12 Hour") { params ->
-                            var timePickerTime by remember { mutableStateOf(LocalTime.now()) }
-                            TimePickerWith12HourClock(
-                                onTimeConfirm = {
-                                    timePickerTime = it
-                                    params.navigateBack()
-                                },
-                                time = timePickerTime,
-                            )
-                        },
-                        ComposableDemo("Date Picker") { params ->
-                            var datePickerDate by remember { mutableStateOf(LocalDate.now()) }
-                            DatePicker(
-                                onDateConfirm = {
-                                    datePickerDate = it
-                                    params.navigateBack()
-                                },
-                                date = datePickerDate
-                            )
-                        },
-                        ComposableDemo("From Date Picker") { params ->
-                            var datePickerDate by remember { mutableStateOf(LocalDate.now()) }
-                            DatePicker(
-                                onDateConfirm = {
-                                    datePickerDate = it
-                                    params.navigateBack()
-                                },
-                                date = datePickerDate,
-                                fromDate = datePickerDate
-                            )
-                        },
-                        ComposableDemo("To Date Picker") { params ->
-                            var datePickerDate by remember { mutableStateOf(LocalDate.now()) }
-                            DatePicker(
-                                onDateConfirm = {
-                                    datePickerDate = it
-                                    params.navigateBack()
-                                },
-                                date = datePickerDate,
-                                toDate = datePickerDate
-                            )
-                        },
-                        ComposableDemo("Simple Picker") { SimplePicker() },
-                        ComposableDemo("No gradient") { PickerWithoutGradient() },
-                        ComposableDemo("Animate picker change") { AnimateOptionChangePicker() },
-                        ComposableDemo("Sample Picker Group") { PickerGroup24Hours() },
-                        ComposableDemo("Autocentering Picker Group") { AutoCenteringPickerGroup() }
-                    )
-                } else {
-                    listOf(
-                        ComposableDemo("Simple Picker") { SimplePicker() },
-                    )
-                }
+                listOf(
+                    ComposableDemo("Time HH:MM:SS") { params ->
+                        var timePickerTime by remember { mutableStateOf(LocalTime.now()) }
+                        TimePicker(
+                            onTimeConfirm = {
+                                timePickerTime = it
+                                params.navigateBack()
+                            },
+                            time = timePickerTime,
+                        )
+                    },
+                    ComposableDemo("Time 12 Hour") { params ->
+                        var timePickerTime by remember { mutableStateOf(LocalTime.now()) }
+                        TimePickerWith12HourClock(
+                            onTimeConfirm = {
+                                timePickerTime = it
+                                params.navigateBack()
+                            },
+                            time = timePickerTime,
+                        )
+                    },
+                    ComposableDemo("Date Picker") { params ->
+                        var datePickerDate by remember { mutableStateOf(LocalDate.now()) }
+                        DatePicker(
+                            onDateConfirm = {
+                                datePickerDate = it
+                                params.navigateBack()
+                            },
+                            date = datePickerDate
+                        )
+                    },
+                    ComposableDemo("From Date Picker") { params ->
+                        var datePickerDate by remember { mutableStateOf(LocalDate.now()) }
+                        DatePicker(
+                            onDateConfirm = {
+                                datePickerDate = it
+                                params.navigateBack()
+                            },
+                            date = datePickerDate,
+                            fromDate = datePickerDate
+                        )
+                    },
+                    ComposableDemo("To Date Picker") { params ->
+                        var datePickerDate by remember { mutableStateOf(LocalDate.now()) }
+                        DatePicker(
+                            onDateConfirm = {
+                                datePickerDate = it
+                                params.navigateBack()
+                            },
+                            date = datePickerDate,
+                            toDate = datePickerDate
+                        )
+                    },
+                    ComposableDemo("Simple Picker") { SimplePicker() },
+                    ComposableDemo("No gradient") { PickerWithoutGradient() },
+                    ComposableDemo("Animate picker change") { AnimateOptionChangePicker() },
+                    ComposableDemo("Sample Picker Group") { PickerGroup24Hours() },
+                    ComposableDemo("Autocentering Picker Group") { AutoCenteringPickerGroup() }
+                )
             ),
             DemoCategory(
                 "Slider",
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
index 223bcbe..310a4b7 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/PickerDemo.kt
@@ -17,11 +17,9 @@
 package androidx.wear.compose.integration.demos
 
 import android.content.Context
-import android.os.Build
 import android.view.accessibility.AccessibilityManager
 import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener
 import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener
-import androidx.annotation.RequiresApi
 import androidx.compose.animation.core.Animatable
 import androidx.compose.foundation.focusable
 import androidx.compose.foundation.layout.Arrangement
@@ -95,7 +93,6 @@
  * @param modifier the modifiers for the `Box` containing the UI elements.
  * @param time the initial value to seed the picker with.
  */
-@RequiresApi(Build.VERSION_CODES.O)
 @Composable
 public fun TimePicker(
     onTimeConfirm: (LocalTime) -> Unit,
@@ -268,7 +265,6 @@
  * @param modifier the modifiers for the `Column` containing the UI elements.
  * @param time the initial value to seed the picker with.
  */
-@RequiresApi(Build.VERSION_CODES.O)
 @Composable
 public fun TimePickerWith12HourClock(
     onTimeConfirm: (LocalTime) -> Unit,
@@ -468,7 +464,6 @@
  * @param fromDate the minimum date to be selected in picker
  * @param toDate the maximum date to be selected in picker
  */
-@RequiresApi(Build.VERSION_CODES.O)
 @Composable
 public fun DatePicker(
     onDateConfirm: (LocalDate) -> Unit,
@@ -861,20 +856,17 @@
     }
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 private fun verifyDates(date: LocalDate, fromDate: LocalDate, toDate: LocalDate) {
     require(toDate >= fromDate) { "toDate should be greater than or equal to fromDate" }
     require(date in fromDate..toDate) { "date should lie between fromDate and toDate" }
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 private fun getMonthNames(pattern: String): List<String> {
     val monthFormatter = DateTimeFormatter.ofPattern(pattern)
     val months = 1..12
     return months.map { LocalDate.of(2022, it, 1).format(monthFormatter) }
 }
 
-@RequiresApi(Build.VERSION_CODES.O)
 internal class DatePickerState
 constructor(
     private val date: LocalDate,
diff --git a/wear/compose/integration-tests/macrobenchmark-target/build.gradle b/wear/compose/integration-tests/macrobenchmark-target/build.gradle
index dbbe105..d10859a 100644
--- a/wear/compose/integration-tests/macrobenchmark-target/build.gradle
+++ b/wear/compose/integration-tests/macrobenchmark-target/build.gradle
@@ -53,4 +53,4 @@
     implementation(project(":tracing:tracing-perfetto-binary"))
 }
 
-android.defaultConfig.minSdk = 25
+android.defaultConfig.minSdk = 30
diff --git a/wear/compose/integration-tests/macrobenchmark/build.gradle b/wear/compose/integration-tests/macrobenchmark/build.gradle
index 6526e1b..e124928 100644
--- a/wear/compose/integration-tests/macrobenchmark/build.gradle
+++ b/wear/compose/integration-tests/macrobenchmark/build.gradle
@@ -23,7 +23,7 @@
 android {
     compileSdk = 35
     defaultConfig {
-        minSdk = 29
+        minSdk = 30
     }
     namespace = "androidx.wear.compose.integration.macrobenchmark"
     targetProjectPath = ":wear:compose:integration-tests:macrobenchmark-target"
diff --git a/wear/protolayout/protolayout-material3/api/current.txt b/wear/protolayout/protolayout-material3/api/current.txt
index 07fd4fb..6d598d2 100644
--- a/wear/protolayout/protolayout-material3/api/current.txt
+++ b/wear/protolayout/protolayout-material3/api/current.txt
@@ -13,13 +13,15 @@
 
   public final class ButtonColors {
     ctor public ButtonColors();
-    ctor public ButtonColors(optional androidx.wear.protolayout.types.LayoutColor container, optional androidx.wear.protolayout.types.LayoutColor icon, optional androidx.wear.protolayout.types.LayoutColor label);
-    method public androidx.wear.protolayout.types.LayoutColor getContainer();
-    method public androidx.wear.protolayout.types.LayoutColor getIcon();
-    method public androidx.wear.protolayout.types.LayoutColor getLabel();
-    property public final androidx.wear.protolayout.types.LayoutColor container;
-    property public final androidx.wear.protolayout.types.LayoutColor icon;
-    property public final androidx.wear.protolayout.types.LayoutColor label;
+    ctor public ButtonColors(optional androidx.wear.protolayout.types.LayoutColor containerColor, optional androidx.wear.protolayout.types.LayoutColor iconColor, optional androidx.wear.protolayout.types.LayoutColor labelColor, optional androidx.wear.protolayout.types.LayoutColor secondaryLabelColor);
+    method public androidx.wear.protolayout.types.LayoutColor getContainerColor();
+    method public androidx.wear.protolayout.types.LayoutColor getIconColor();
+    method public androidx.wear.protolayout.types.LayoutColor getLabelColor();
+    method public androidx.wear.protolayout.types.LayoutColor getSecondaryLabelColor();
+    property public final androidx.wear.protolayout.types.LayoutColor containerColor;
+    property public final androidx.wear.protolayout.types.LayoutColor iconColor;
+    property public final androidx.wear.protolayout.types.LayoutColor labelColor;
+    property public final androidx.wear.protolayout.types.LayoutColor secondaryLabelColor;
   }
 
   public final class ButtonDefaults {
@@ -46,27 +48,39 @@
   }
 
   public final class ButtonKt {
-    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement button(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? content, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? backgroundContent, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
-    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement iconButton(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> iconContent, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.ButtonColors colors, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? backgroundContent, optional androidx.wear.protolayout.material3.IconButtonStyle style, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
-    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement textButton(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> labelContent, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.ButtonColors colors, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? backgroundContent, optional androidx.wear.protolayout.material3.TextButtonStyle style, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
+    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement button(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> labelContent, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? secondaryLabelContent, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? iconContent, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.ButtonColors colors, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? backgroundContent, optional androidx.wear.protolayout.material3.ButtonStyle style, optional int horizontalAlignment, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
+    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement compactButton(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? labelContent, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? iconContent, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.ButtonColors colors, optional int horizontalAlignment, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
+    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement iconButton(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> iconContent, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.ButtonColors colors, optional androidx.wear.protolayout.material3.IconButtonStyle style, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
+    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement imageButton(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> backgroundContent, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height);
+    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement textButton(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> labelContent, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.ButtonColors colors, optional androidx.wear.protolayout.material3.TextButtonStyle style, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
+  }
+
+  public final class ButtonStyle {
+    field public static final androidx.wear.protolayout.material3.ButtonStyle.Companion Companion;
+  }
+
+  public static final class ButtonStyle.Companion {
+    method public androidx.wear.protolayout.material3.ButtonStyle defaultButtonStyle();
+    method public androidx.wear.protolayout.material3.ButtonStyle largeButtonStyle();
+    method public androidx.wear.protolayout.material3.ButtonStyle smallButtonStyle();
   }
 
   public final class CardColors {
-    ctor public CardColors(androidx.wear.protolayout.types.LayoutColor background, androidx.wear.protolayout.types.LayoutColor title, androidx.wear.protolayout.types.LayoutColor content, optional androidx.wear.protolayout.types.LayoutColor time, optional androidx.wear.protolayout.types.LayoutColor label, optional androidx.wear.protolayout.types.LayoutColor secondaryIcon, optional androidx.wear.protolayout.types.LayoutColor secondaryText);
-    method public androidx.wear.protolayout.types.LayoutColor getBackground();
-    method public androidx.wear.protolayout.types.LayoutColor getContent();
-    method public androidx.wear.protolayout.types.LayoutColor getLabel();
-    method public androidx.wear.protolayout.types.LayoutColor getSecondaryIcon();
-    method public androidx.wear.protolayout.types.LayoutColor getSecondaryText();
-    method public androidx.wear.protolayout.types.LayoutColor getTime();
-    method public androidx.wear.protolayout.types.LayoutColor getTitle();
-    property public final androidx.wear.protolayout.types.LayoutColor background;
-    property public final androidx.wear.protolayout.types.LayoutColor content;
-    property public final androidx.wear.protolayout.types.LayoutColor label;
-    property public final androidx.wear.protolayout.types.LayoutColor secondaryIcon;
-    property public final androidx.wear.protolayout.types.LayoutColor secondaryText;
-    property public final androidx.wear.protolayout.types.LayoutColor time;
-    property public final androidx.wear.protolayout.types.LayoutColor title;
+    ctor public CardColors(androidx.wear.protolayout.types.LayoutColor backgroundColor, androidx.wear.protolayout.types.LayoutColor titleColor, androidx.wear.protolayout.types.LayoutColor contentColor, optional androidx.wear.protolayout.types.LayoutColor timeColor, optional androidx.wear.protolayout.types.LayoutColor labelColor, optional androidx.wear.protolayout.types.LayoutColor secondaryIconColor, optional androidx.wear.protolayout.types.LayoutColor secondaryTextColor);
+    method public androidx.wear.protolayout.types.LayoutColor getBackgroundColor();
+    method public androidx.wear.protolayout.types.LayoutColor getContentColor();
+    method public androidx.wear.protolayout.types.LayoutColor getLabelColor();
+    method public androidx.wear.protolayout.types.LayoutColor getSecondaryIconColor();
+    method public androidx.wear.protolayout.types.LayoutColor getSecondaryTextColor();
+    method public androidx.wear.protolayout.types.LayoutColor getTimeColor();
+    method public androidx.wear.protolayout.types.LayoutColor getTitleColor();
+    property public final androidx.wear.protolayout.types.LayoutColor backgroundColor;
+    property public final androidx.wear.protolayout.types.LayoutColor contentColor;
+    property public final androidx.wear.protolayout.types.LayoutColor labelColor;
+    property public final androidx.wear.protolayout.types.LayoutColor secondaryIconColor;
+    property public final androidx.wear.protolayout.types.LayoutColor secondaryTextColor;
+    property public final androidx.wear.protolayout.types.LayoutColor timeColor;
+    property public final androidx.wear.protolayout.types.LayoutColor titleColor;
   }
 
   public final class CardDefaults {
@@ -86,6 +100,24 @@
     method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement titleCard(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> title, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? content, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? time, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.CardColors colors, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? backgroundContent, optional androidx.wear.protolayout.material3.TitleCardStyle style, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding, optional int horizontalAlignment);
   }
 
+  public final class CircularProgressIndicatorDefaults {
+    method @Dimension(unit=androidx.annotation.Dimension.Companion.DP) public float calculateRecommendedGapSize(@Dimension(unit=androidx.annotation.Dimension.Companion.DP) float strokeWidth);
+    method public androidx.wear.protolayout.material3.ProgressIndicatorColors filledProgressIndicatorColors(androidx.wear.protolayout.material3.MaterialScope);
+    method public androidx.wear.protolayout.material3.ProgressIndicatorColors filledTonalProgressIndicatorColors(androidx.wear.protolayout.material3.MaterialScope);
+    method public androidx.wear.protolayout.material3.ProgressIndicatorColors filledVariantProgressIndicatorColors(androidx.wear.protolayout.material3.MaterialScope);
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec getRecommendedAnimationSpec();
+    property @Dimension(unit=androidx.annotation.Dimension.Companion.DP) public static final float LARGE_STROKE_WIDTH;
+    property @Dimension(unit=androidx.annotation.Dimension.Companion.DP) public static final float SMALL_STROKE_WIDTH;
+    property public final androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec recommendedAnimationSpec;
+    field public static final androidx.wear.protolayout.material3.CircularProgressIndicatorDefaults INSTANCE;
+    field @Dimension(unit=androidx.annotation.Dimension.Companion.DP) public static final float LARGE_STROKE_WIDTH = 8.0f;
+    field @Dimension(unit=androidx.annotation.Dimension.Companion.DP) public static final float SMALL_STROKE_WIDTH = 4.0f;
+  }
+
+  public final class CircularProgressIndicatorKt {
+    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement circularProgressIndicator(androidx.wear.protolayout.material3.MaterialScope, optional float staticProgress, optional androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat? dynamicProgress, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional float startAngleDegrees, optional float endAngleDegrees, optional @Dimension(unit=androidx.annotation.Dimension.Companion.DP) float strokeWidth, optional @Dimension(unit=androidx.annotation.Dimension.Companion.DP) float gapSize, optional androidx.wear.protolayout.material3.ProgressIndicatorColors colors, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension size);
+  }
+
   public final class ColorScheme {
     ctor public ColorScheme();
     ctor public ColorScheme(optional androidx.wear.protolayout.types.LayoutColor primary, optional androidx.wear.protolayout.types.LayoutColor primaryDim, optional androidx.wear.protolayout.types.LayoutColor primaryContainer, optional androidx.wear.protolayout.types.LayoutColor onPrimary, optional androidx.wear.protolayout.types.LayoutColor onPrimaryContainer, optional androidx.wear.protolayout.types.LayoutColor secondary, optional androidx.wear.protolayout.types.LayoutColor secondaryDim, optional androidx.wear.protolayout.types.LayoutColor secondaryContainer, optional androidx.wear.protolayout.types.LayoutColor onSecondary, optional androidx.wear.protolayout.types.LayoutColor onSecondaryContainer, optional androidx.wear.protolayout.types.LayoutColor tertiary, optional androidx.wear.protolayout.types.LayoutColor tertiaryDim, optional androidx.wear.protolayout.types.LayoutColor tertiaryContainer, optional androidx.wear.protolayout.types.LayoutColor onTertiary, optional androidx.wear.protolayout.types.LayoutColor onTertiaryContainer, optional androidx.wear.protolayout.types.LayoutColor surfaceContainerLow, optional androidx.wear.protolayout.types.LayoutColor surfaceContainer, optional androidx.wear.protolayout.types.LayoutColor surfaceContainerHigh, optional androidx.wear.protolayout.types.LayoutColor onSurface, optional androidx.wear.protolayout.types.LayoutColor onSurfaceVariant, optional androidx.wear.protolayout.types.LayoutColor outline, optional androidx.wear.protolayout.types.LayoutColor outlineVariant, optional androidx.wear.protolayout.types.LayoutColor background, optional androidx.wear.protolayout.types.LayoutColor onBackground, optional androidx.wear.protolayout.types.LayoutColor error, optional androidx.wear.protolayout.types.LayoutColor onError, optional androidx.wear.protolayout.types.LayoutColor errorContainer, optional androidx.wear.protolayout.types.LayoutColor onErrorContainer);
@@ -233,6 +265,16 @@
     method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement primaryLayout(androidx.wear.protolayout.material3.MaterialScope, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> mainSlot, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? titleSlot, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? bottomSlot, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? labelForBottomSlot, optional androidx.wear.protolayout.ModifiersBuilders.Clickable? onClick);
   }
 
+  public final class ProgressIndicatorColors {
+    ctor public ProgressIndicatorColors(androidx.wear.protolayout.types.LayoutColor indicatorColor, androidx.wear.protolayout.types.LayoutColor trackColor, optional androidx.wear.protolayout.types.LayoutColor trackOverflowColor);
+    method public androidx.wear.protolayout.types.LayoutColor getIndicatorColor();
+    method public androidx.wear.protolayout.types.LayoutColor getTrackColor();
+    method public androidx.wear.protolayout.types.LayoutColor getTrackOverflowColor();
+    property public final androidx.wear.protolayout.types.LayoutColor indicatorColor;
+    property public final androidx.wear.protolayout.types.LayoutColor trackColor;
+    property public final androidx.wear.protolayout.types.LayoutColor trackOverflowColor;
+  }
+
   public final class Shapes {
     ctor public Shapes();
     method public androidx.wear.protolayout.ModifiersBuilders.Corner getExtraLarge();
diff --git a/wear/protolayout/protolayout-material3/api/restricted_current.txt b/wear/protolayout/protolayout-material3/api/restricted_current.txt
index 07fd4fb..6d598d2 100644
--- a/wear/protolayout/protolayout-material3/api/restricted_current.txt
+++ b/wear/protolayout/protolayout-material3/api/restricted_current.txt
@@ -13,13 +13,15 @@
 
   public final class ButtonColors {
     ctor public ButtonColors();
-    ctor public ButtonColors(optional androidx.wear.protolayout.types.LayoutColor container, optional androidx.wear.protolayout.types.LayoutColor icon, optional androidx.wear.protolayout.types.LayoutColor label);
-    method public androidx.wear.protolayout.types.LayoutColor getContainer();
-    method public androidx.wear.protolayout.types.LayoutColor getIcon();
-    method public androidx.wear.protolayout.types.LayoutColor getLabel();
-    property public final androidx.wear.protolayout.types.LayoutColor container;
-    property public final androidx.wear.protolayout.types.LayoutColor icon;
-    property public final androidx.wear.protolayout.types.LayoutColor label;
+    ctor public ButtonColors(optional androidx.wear.protolayout.types.LayoutColor containerColor, optional androidx.wear.protolayout.types.LayoutColor iconColor, optional androidx.wear.protolayout.types.LayoutColor labelColor, optional androidx.wear.protolayout.types.LayoutColor secondaryLabelColor);
+    method public androidx.wear.protolayout.types.LayoutColor getContainerColor();
+    method public androidx.wear.protolayout.types.LayoutColor getIconColor();
+    method public androidx.wear.protolayout.types.LayoutColor getLabelColor();
+    method public androidx.wear.protolayout.types.LayoutColor getSecondaryLabelColor();
+    property public final androidx.wear.protolayout.types.LayoutColor containerColor;
+    property public final androidx.wear.protolayout.types.LayoutColor iconColor;
+    property public final androidx.wear.protolayout.types.LayoutColor labelColor;
+    property public final androidx.wear.protolayout.types.LayoutColor secondaryLabelColor;
   }
 
   public final class ButtonDefaults {
@@ -46,27 +48,39 @@
   }
 
   public final class ButtonKt {
-    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement button(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? content, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? backgroundContent, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
-    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement iconButton(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> iconContent, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.ButtonColors colors, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? backgroundContent, optional androidx.wear.protolayout.material3.IconButtonStyle style, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
-    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement textButton(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> labelContent, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.ButtonColors colors, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? backgroundContent, optional androidx.wear.protolayout.material3.TextButtonStyle style, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
+    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement button(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> labelContent, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? secondaryLabelContent, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? iconContent, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.ButtonColors colors, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? backgroundContent, optional androidx.wear.protolayout.material3.ButtonStyle style, optional int horizontalAlignment, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
+    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement compactButton(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? labelContent, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? iconContent, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.ButtonColors colors, optional int horizontalAlignment, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
+    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement iconButton(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> iconContent, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.ButtonColors colors, optional androidx.wear.protolayout.material3.IconButtonStyle style, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
+    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement imageButton(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> backgroundContent, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height);
+    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement textButton(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> labelContent, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension width, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.ButtonColors colors, optional androidx.wear.protolayout.material3.TextButtonStyle style, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding);
+  }
+
+  public final class ButtonStyle {
+    field public static final androidx.wear.protolayout.material3.ButtonStyle.Companion Companion;
+  }
+
+  public static final class ButtonStyle.Companion {
+    method public androidx.wear.protolayout.material3.ButtonStyle defaultButtonStyle();
+    method public androidx.wear.protolayout.material3.ButtonStyle largeButtonStyle();
+    method public androidx.wear.protolayout.material3.ButtonStyle smallButtonStyle();
   }
 
   public final class CardColors {
-    ctor public CardColors(androidx.wear.protolayout.types.LayoutColor background, androidx.wear.protolayout.types.LayoutColor title, androidx.wear.protolayout.types.LayoutColor content, optional androidx.wear.protolayout.types.LayoutColor time, optional androidx.wear.protolayout.types.LayoutColor label, optional androidx.wear.protolayout.types.LayoutColor secondaryIcon, optional androidx.wear.protolayout.types.LayoutColor secondaryText);
-    method public androidx.wear.protolayout.types.LayoutColor getBackground();
-    method public androidx.wear.protolayout.types.LayoutColor getContent();
-    method public androidx.wear.protolayout.types.LayoutColor getLabel();
-    method public androidx.wear.protolayout.types.LayoutColor getSecondaryIcon();
-    method public androidx.wear.protolayout.types.LayoutColor getSecondaryText();
-    method public androidx.wear.protolayout.types.LayoutColor getTime();
-    method public androidx.wear.protolayout.types.LayoutColor getTitle();
-    property public final androidx.wear.protolayout.types.LayoutColor background;
-    property public final androidx.wear.protolayout.types.LayoutColor content;
-    property public final androidx.wear.protolayout.types.LayoutColor label;
-    property public final androidx.wear.protolayout.types.LayoutColor secondaryIcon;
-    property public final androidx.wear.protolayout.types.LayoutColor secondaryText;
-    property public final androidx.wear.protolayout.types.LayoutColor time;
-    property public final androidx.wear.protolayout.types.LayoutColor title;
+    ctor public CardColors(androidx.wear.protolayout.types.LayoutColor backgroundColor, androidx.wear.protolayout.types.LayoutColor titleColor, androidx.wear.protolayout.types.LayoutColor contentColor, optional androidx.wear.protolayout.types.LayoutColor timeColor, optional androidx.wear.protolayout.types.LayoutColor labelColor, optional androidx.wear.protolayout.types.LayoutColor secondaryIconColor, optional androidx.wear.protolayout.types.LayoutColor secondaryTextColor);
+    method public androidx.wear.protolayout.types.LayoutColor getBackgroundColor();
+    method public androidx.wear.protolayout.types.LayoutColor getContentColor();
+    method public androidx.wear.protolayout.types.LayoutColor getLabelColor();
+    method public androidx.wear.protolayout.types.LayoutColor getSecondaryIconColor();
+    method public androidx.wear.protolayout.types.LayoutColor getSecondaryTextColor();
+    method public androidx.wear.protolayout.types.LayoutColor getTimeColor();
+    method public androidx.wear.protolayout.types.LayoutColor getTitleColor();
+    property public final androidx.wear.protolayout.types.LayoutColor backgroundColor;
+    property public final androidx.wear.protolayout.types.LayoutColor contentColor;
+    property public final androidx.wear.protolayout.types.LayoutColor labelColor;
+    property public final androidx.wear.protolayout.types.LayoutColor secondaryIconColor;
+    property public final androidx.wear.protolayout.types.LayoutColor secondaryTextColor;
+    property public final androidx.wear.protolayout.types.LayoutColor timeColor;
+    property public final androidx.wear.protolayout.types.LayoutColor titleColor;
   }
 
   public final class CardDefaults {
@@ -86,6 +100,24 @@
     method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement titleCard(androidx.wear.protolayout.material3.MaterialScope, androidx.wear.protolayout.ModifiersBuilders.Clickable onClick, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> title, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? content, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? time, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension height, optional androidx.wear.protolayout.ModifiersBuilders.Corner shape, optional androidx.wear.protolayout.material3.CardColors colors, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? backgroundContent, optional androidx.wear.protolayout.material3.TitleCardStyle style, optional androidx.wear.protolayout.ModifiersBuilders.Padding contentPadding, optional int horizontalAlignment);
   }
 
+  public final class CircularProgressIndicatorDefaults {
+    method @Dimension(unit=androidx.annotation.Dimension.Companion.DP) public float calculateRecommendedGapSize(@Dimension(unit=androidx.annotation.Dimension.Companion.DP) float strokeWidth);
+    method public androidx.wear.protolayout.material3.ProgressIndicatorColors filledProgressIndicatorColors(androidx.wear.protolayout.material3.MaterialScope);
+    method public androidx.wear.protolayout.material3.ProgressIndicatorColors filledTonalProgressIndicatorColors(androidx.wear.protolayout.material3.MaterialScope);
+    method public androidx.wear.protolayout.material3.ProgressIndicatorColors filledVariantProgressIndicatorColors(androidx.wear.protolayout.material3.MaterialScope);
+    method public androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec getRecommendedAnimationSpec();
+    property @Dimension(unit=androidx.annotation.Dimension.Companion.DP) public static final float LARGE_STROKE_WIDTH;
+    property @Dimension(unit=androidx.annotation.Dimension.Companion.DP) public static final float SMALL_STROKE_WIDTH;
+    property public final androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec recommendedAnimationSpec;
+    field public static final androidx.wear.protolayout.material3.CircularProgressIndicatorDefaults INSTANCE;
+    field @Dimension(unit=androidx.annotation.Dimension.Companion.DP) public static final float LARGE_STROKE_WIDTH = 8.0f;
+    field @Dimension(unit=androidx.annotation.Dimension.Companion.DP) public static final float SMALL_STROKE_WIDTH = 4.0f;
+  }
+
+  public final class CircularProgressIndicatorKt {
+    method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement circularProgressIndicator(androidx.wear.protolayout.material3.MaterialScope, optional float staticProgress, optional androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat? dynamicProgress, optional androidx.wear.protolayout.modifiers.LayoutModifier modifier, optional float startAngleDegrees, optional float endAngleDegrees, optional @Dimension(unit=androidx.annotation.Dimension.Companion.DP) float strokeWidth, optional @Dimension(unit=androidx.annotation.Dimension.Companion.DP) float gapSize, optional androidx.wear.protolayout.material3.ProgressIndicatorColors colors, optional androidx.wear.protolayout.DimensionBuilders.ContainerDimension size);
+  }
+
   public final class ColorScheme {
     ctor public ColorScheme();
     ctor public ColorScheme(optional androidx.wear.protolayout.types.LayoutColor primary, optional androidx.wear.protolayout.types.LayoutColor primaryDim, optional androidx.wear.protolayout.types.LayoutColor primaryContainer, optional androidx.wear.protolayout.types.LayoutColor onPrimary, optional androidx.wear.protolayout.types.LayoutColor onPrimaryContainer, optional androidx.wear.protolayout.types.LayoutColor secondary, optional androidx.wear.protolayout.types.LayoutColor secondaryDim, optional androidx.wear.protolayout.types.LayoutColor secondaryContainer, optional androidx.wear.protolayout.types.LayoutColor onSecondary, optional androidx.wear.protolayout.types.LayoutColor onSecondaryContainer, optional androidx.wear.protolayout.types.LayoutColor tertiary, optional androidx.wear.protolayout.types.LayoutColor tertiaryDim, optional androidx.wear.protolayout.types.LayoutColor tertiaryContainer, optional androidx.wear.protolayout.types.LayoutColor onTertiary, optional androidx.wear.protolayout.types.LayoutColor onTertiaryContainer, optional androidx.wear.protolayout.types.LayoutColor surfaceContainerLow, optional androidx.wear.protolayout.types.LayoutColor surfaceContainer, optional androidx.wear.protolayout.types.LayoutColor surfaceContainerHigh, optional androidx.wear.protolayout.types.LayoutColor onSurface, optional androidx.wear.protolayout.types.LayoutColor onSurfaceVariant, optional androidx.wear.protolayout.types.LayoutColor outline, optional androidx.wear.protolayout.types.LayoutColor outlineVariant, optional androidx.wear.protolayout.types.LayoutColor background, optional androidx.wear.protolayout.types.LayoutColor onBackground, optional androidx.wear.protolayout.types.LayoutColor error, optional androidx.wear.protolayout.types.LayoutColor onError, optional androidx.wear.protolayout.types.LayoutColor errorContainer, optional androidx.wear.protolayout.types.LayoutColor onErrorContainer);
@@ -233,6 +265,16 @@
     method public static androidx.wear.protolayout.LayoutElementBuilders.LayoutElement primaryLayout(androidx.wear.protolayout.material3.MaterialScope, kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement> mainSlot, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? titleSlot, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? bottomSlot, optional kotlin.jvm.functions.Function1<? super androidx.wear.protolayout.material3.MaterialScope,? extends androidx.wear.protolayout.LayoutElementBuilders.LayoutElement>? labelForBottomSlot, optional androidx.wear.protolayout.ModifiersBuilders.Clickable? onClick);
   }
 
+  public final class ProgressIndicatorColors {
+    ctor public ProgressIndicatorColors(androidx.wear.protolayout.types.LayoutColor indicatorColor, androidx.wear.protolayout.types.LayoutColor trackColor, optional androidx.wear.protolayout.types.LayoutColor trackOverflowColor);
+    method public androidx.wear.protolayout.types.LayoutColor getIndicatorColor();
+    method public androidx.wear.protolayout.types.LayoutColor getTrackColor();
+    method public androidx.wear.protolayout.types.LayoutColor getTrackOverflowColor();
+    property public final androidx.wear.protolayout.types.LayoutColor indicatorColor;
+    property public final androidx.wear.protolayout.types.LayoutColor trackColor;
+    property public final androidx.wear.protolayout.types.LayoutColor trackOverflowColor;
+  }
+
   public final class Shapes {
     ctor public Shapes();
     method public androidx.wear.protolayout.ModifiersBuilders.Corner getExtraLarge();
diff --git a/wear/protolayout/protolayout-material3/samples/src/main/java/androidx/wear/protolayout/material3/samples/Material3ComponentsSample.kt b/wear/protolayout/protolayout-material3/samples/src/main/java/androidx/wear/protolayout/material3/samples/Material3ComponentsSample.kt
index 618b67c..86b46af 100644
--- a/wear/protolayout/protolayout-material3/samples/src/main/java/androidx/wear/protolayout/material3/samples/Material3ComponentsSample.kt
+++ b/wear/protolayout/protolayout-material3/samples/src/main/java/androidx/wear/protolayout/material3/samples/Material3ComponentsSample.kt
@@ -19,16 +19,21 @@
 import android.content.Context
 import androidx.annotation.Sampled
 import androidx.wear.protolayout.DeviceParametersBuilders.DeviceParameters
+import androidx.wear.protolayout.DimensionBuilders.dp
 import androidx.wear.protolayout.DimensionBuilders.expand
 import androidx.wear.protolayout.DimensionBuilders.weight
 import androidx.wear.protolayout.LayoutElementBuilders
+import androidx.wear.protolayout.LayoutElementBuilders.Box
 import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement
 import androidx.wear.protolayout.ModifiersBuilders
 import androidx.wear.protolayout.ModifiersBuilders.Clickable
+import androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat
 import androidx.wear.protolayout.expression.DynamicBuilders.DynamicString
 import androidx.wear.protolayout.material3.AppCardStyle
 import androidx.wear.protolayout.material3.CardDefaults.filledTonalCardColors
 import androidx.wear.protolayout.material3.CardDefaults.filledVariantCardColors
+import androidx.wear.protolayout.material3.CircularProgressIndicatorDefaults
+import androidx.wear.protolayout.material3.CircularProgressIndicatorDefaults.filledVariantProgressIndicatorColors
 import androidx.wear.protolayout.material3.DataCardStyle.Companion.extraLargeDataCardStyle
 import androidx.wear.protolayout.material3.DataCardStyle.Companion.largeCompactDataCardStyle
 import androidx.wear.protolayout.material3.GraphicDataCardStyle.Companion.largeGraphicDataCardStyle
@@ -39,11 +44,14 @@
 import androidx.wear.protolayout.material3.button
 import androidx.wear.protolayout.material3.buttonGroup
 import androidx.wear.protolayout.material3.card
+import androidx.wear.protolayout.material3.circularProgressIndicator
+import androidx.wear.protolayout.material3.compactButton
 import androidx.wear.protolayout.material3.graphicDataCard
 import androidx.wear.protolayout.material3.icon
 import androidx.wear.protolayout.material3.iconButton
 import androidx.wear.protolayout.material3.iconDataCard
 import androidx.wear.protolayout.material3.iconEdgeButton
+import androidx.wear.protolayout.material3.imageButton
 import androidx.wear.protolayout.material3.materialScope
 import androidx.wear.protolayout.material3.primaryLayout
 import androidx.wear.protolayout.material3.text
@@ -307,7 +315,7 @@
     }
 
 @Sampled
-fun buttonSample(
+fun customButtonSample(
     context: Context,
     deviceConfiguration: DeviceParameters,
     clickable: Clickable
@@ -315,6 +323,7 @@
     materialScope(context, deviceConfiguration) {
         primaryLayout(
             mainSlot = {
+                // Button with custom content inside
                 button(
                     onClick = clickable,
                     modifier =
@@ -322,7 +331,10 @@
                             .backgroundColor(colorScheme.primary),
                     width = expand(),
                     height = expand(),
-                    content = { text("Button!".layoutString) }
+                    labelContent = {
+                        // This can be further built.
+                        Box.Builder().build()
+                    }
                 )
             }
         )
@@ -390,7 +402,7 @@
     materialScope(context, deviceConfiguration) {
         primaryLayout(
             mainSlot = {
-                button(
+                imageButton(
                     onClick = clickable,
                     modifier =
                         LayoutModifier.contentDescription("Big button with image background"),
@@ -401,3 +413,65 @@
             }
         )
     }
+
+@Sampled
+fun singleSegmentCircularProgressIndicator(
+    context: Context,
+    deviceParameters: DeviceParameters,
+): LayoutElement =
+    materialScope(context, deviceParameters) {
+        circularProgressIndicator(
+            dynamicProgress =
+                DynamicFloat.animate(
+                    0.0F,
+                    1.1F,
+                    CircularProgressIndicatorDefaults.recommendedAnimationSpec
+                ),
+            startAngleDegrees = 200F,
+            endAngleDegrees = 520F,
+            colors = filledVariantProgressIndicatorColors(),
+            size = dp(85F)
+        )
+    }
+
+@Sampled
+fun pillShapeButtonsSample(
+    context: Context,
+    deviceConfiguration: DeviceParameters,
+    clickable: Clickable
+): LayoutElement =
+    materialScope(context, deviceConfiguration) {
+        primaryLayout(
+            mainSlot = {
+                button(
+                    onClick = clickable,
+                    modifier = LayoutModifier.contentDescription("Pill shape button"),
+                    width = expand(),
+                    height = expand(),
+                    labelContent = { text("First label".layoutString) },
+                    secondaryLabelContent = { text("Second label".layoutString) },
+                    iconContent = { icon("id") }
+                )
+            }
+        )
+    }
+
+@Sampled
+fun compactButtonsSample(
+    context: Context,
+    deviceConfiguration: DeviceParameters,
+    clickable: Clickable
+): LayoutElement =
+    materialScope(context, deviceConfiguration) {
+        primaryLayout(
+            mainSlot = {
+                compactButton(
+                    onClick = clickable,
+                    modifier = LayoutModifier.contentDescription("Compact button"),
+                    width = expand(),
+                    labelContent = { text("Action".layoutString) },
+                    iconContent = { icon("id") }
+                )
+            }
+        )
+    }
diff --git a/wear/protolayout/protolayout-material3/src/androidTest/java/androidx/wear/protolayout/material3/TestCasesGenerator.kt b/wear/protolayout/protolayout-material3/src/androidTest/java/androidx/wear/protolayout/material3/TestCasesGenerator.kt
index fd7ae36..2aa2b52 100644
--- a/wear/protolayout/protolayout-material3/src/androidTest/java/androidx/wear/protolayout/material3/TestCasesGenerator.kt
+++ b/wear/protolayout/protolayout-material3/src/androidTest/java/androidx/wear/protolayout/material3/TestCasesGenerator.kt
@@ -19,9 +19,11 @@
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.wear.protolayout.DeviceParametersBuilders
+import androidx.wear.protolayout.DimensionBuilders.dp
 import androidx.wear.protolayout.DimensionBuilders.expand
 import androidx.wear.protolayout.LayoutElementBuilders
 import androidx.wear.protolayout.LayoutElementBuilders.Box
+import androidx.wear.protolayout.LayoutElementBuilders.Column
 import androidx.wear.protolayout.ModifiersBuilders.Background
 import androidx.wear.protolayout.ModifiersBuilders.Corner
 import androidx.wear.protolayout.ModifiersBuilders.Modifiers
@@ -29,12 +31,19 @@
 import androidx.wear.protolayout.material3.ButtonDefaults.filledButtonColors
 import androidx.wear.protolayout.material3.ButtonDefaults.filledTonalButtonColors
 import androidx.wear.protolayout.material3.ButtonDefaults.filledVariantButtonColors
+import androidx.wear.protolayout.material3.ButtonGroupDefaults.DEFAULT_SPACER_BETWEEN_BUTTON_GROUPS
 import androidx.wear.protolayout.material3.CardDefaults.filledVariantCardColors
+import androidx.wear.protolayout.material3.CircularProgressIndicatorDefaults.filledVariantProgressIndicatorColors
 import androidx.wear.protolayout.material3.DataCardStyle.Companion.smallCompactDataCardStyle
+import androidx.wear.protolayout.material3.IconButtonStyle.Companion.largeIconButtonStyle
 import androidx.wear.protolayout.material3.MaterialGoldenTest.Companion.pxToDp
+import androidx.wear.protolayout.material3.TextButtonStyle.Companion.extraLargeTextButtonStyle
+import androidx.wear.protolayout.material3.TextButtonStyle.Companion.largeTextButtonStyle
+import androidx.wear.protolayout.material3.TextButtonStyle.Companion.smallTextButtonStyle
 import androidx.wear.protolayout.material3.TitleContentPlacementInDataCard.Companion.Bottom
 import androidx.wear.protolayout.modifiers.LayoutModifier
 import androidx.wear.protolayout.modifiers.clickable
+import androidx.wear.protolayout.modifiers.clip
 import androidx.wear.protolayout.modifiers.contentDescription
 import androidx.wear.protolayout.types.LayoutColor
 import androidx.wear.protolayout.types.layoutString
@@ -120,23 +129,7 @@
                                     "steps".layoutString,
                                 )
                             },
-                            // TODO: b/368272767 - Update this to CPI
-                            graphic = {
-                                Box.Builder()
-                                    .setWidth(expand())
-                                    .setHeight(expand())
-                                    .setModifiers(
-                                        Modifiers.Builder()
-                                            .setBackground(
-                                                Background.Builder()
-                                                    .setCorner(shapes.full)
-                                                    .setColor(colorScheme.background.prop)
-                                                    .build()
-                                            )
-                                            .build()
-                                    )
-                                    .build()
-                            }
+                            graphic = { circularProgressIndicator(staticProgress = 0.5F) }
                         )
                     },
                 )
@@ -179,9 +172,9 @@
                                     secondaryText = { text("Label".layoutString) },
                                     colors =
                                         CardColors(
-                                            background = colorScheme.onSecondary,
-                                            title = colorScheme.secondary,
-                                            content = colorScheme.secondaryDim
+                                            backgroundColor = colorScheme.onSecondary,
+                                            titleColor = colorScheme.secondary,
+                                            contentColor = colorScheme.secondaryDim
                                         )
                                 )
                             }
@@ -279,9 +272,9 @@
                             style = smallCompactDataCardStyle(),
                             colors =
                                 CardColors(
-                                    background = colorScheme.errorContainer,
-                                    title = colorScheme.onErrorContainer,
-                                    content = colorScheme.onError
+                                    backgroundColor = colorScheme.errorContainer,
+                                    titleColor = colorScheme.onErrorContainer,
+                                    contentColor = colorScheme.onError
                                 ),
                             height = expand()
                         )
@@ -361,10 +354,144 @@
             ) {
                 primaryLayout(
                     mainSlot = {
-                        coloredBox(color = colorScheme.tertiaryDim, shape = shapes.extraLarge)
+                        Column.Builder()
+                            .setWidth(expand())
+                            .setHeight(expand())
+                            .addContent(
+                                button(
+                                    onClick = clickable,
+                                    labelContent = { text("Primary label".layoutString) },
+                                    secondaryLabelContent = {
+                                        text("Secondary label".layoutString)
+                                    },
+                                    iconContent = { icon(ICON_ID) },
+                                    width = expand()
+                                )
+                            )
+                            .addContent(
+                                buttonGroup {
+                                    buttonGroupItem {
+                                        compactButton(
+                                            onClick = clickable,
+                                            labelContent = { text("Label".layoutString) },
+                                        )
+                                    }
+                                    buttonGroupItem {
+                                        imageButton(
+                                            onClick = clickable,
+                                            backgroundContent = { backgroundImage(IMAGE_ID) },
+                                            modifier = LayoutModifier.clip(shapes.extraSmall)
+                                        )
+                                    }
+                                }
+                            )
+                            .build()
                     },
                 )
             }
+        testCases["primarylayout_oneslotbuttons_golden$NORMAL_SCALE_SUFFIX"] =
+            materialScope(
+                ApplicationProvider.getApplicationContext(),
+                deviceParameters,
+                allowDynamicTheme = false
+            ) {
+                primaryLayout(
+                    mainSlot = {
+                        Column.Builder()
+                            .setWidth(expand())
+                            .setHeight(expand())
+                            .addContent(
+                                buttonGroup {
+                                    buttonGroupItem {
+                                        iconButton(
+                                            onClick = clickable,
+                                            iconContent = { icon(ICON_ID) }
+                                        )
+                                    }
+                                    buttonGroupItem {
+                                        iconButton(
+                                            onClick = clickable,
+                                            iconContent = { icon(ICON_ID) },
+                                            style = largeIconButtonStyle(),
+                                            colors = filledTonalButtonColors(),
+                                            width = expand(),
+                                            height = expand(),
+                                            shape = shapes.large
+                                        )
+                                    }
+                                    buttonGroupItem {
+                                        textButton(
+                                            onClick = clickable,
+                                            labelContent = { text("000".layoutString) },
+                                            style = smallTextButtonStyle(),
+                                        )
+                                    }
+                                }
+                            )
+                            .addContent(DEFAULT_SPACER_BETWEEN_BUTTON_GROUPS)
+                            .addContent(
+                                buttonGroup {
+                                    buttonGroupItem {
+                                        textButton(
+                                            onClick = clickable,
+                                            labelContent = { text("1".layoutString) },
+                                            width = expand(),
+                                            shape = shapes.small
+                                        )
+                                    }
+                                    buttonGroupItem {
+                                        textButton(
+                                            onClick = clickable,
+                                            labelContent = { text("2".layoutString) },
+                                            style = largeTextButtonStyle(),
+                                            colors = filledTonalButtonColors(),
+                                            height = expand()
+                                        )
+                                    }
+                                    buttonGroupItem {
+                                        textButton(
+                                            onClick = clickable,
+                                            labelContent = { text("3".layoutString) },
+                                            style = extraLargeTextButtonStyle(),
+                                            colors = filledVariantButtonColors(),
+                                            width = expand(),
+                                            height = expand()
+                                        )
+                                    }
+                                }
+                            )
+                            .build()
+                    },
+                )
+            }
+        testCases["primarylayout_circularprogressindicators_golden$NORMAL_SCALE_SUFFIX"] =
+            materialScope(
+                ApplicationProvider.getApplicationContext(),
+                deviceParameters,
+                allowDynamicTheme = false
+            ) {
+                primaryLayout(
+                    mainSlot = {
+                        buttonGroup(height = dp(50F)) {
+                            buttonGroupItem { circularProgressIndicator() }
+                            buttonGroupItem {
+                                circularProgressIndicator(
+                                    staticProgress = 0.75F,
+                                    colors = filledVariantProgressIndicatorColors()
+                                )
+                            }
+                            buttonGroupItem {
+                                circularProgressIndicator(
+                                    staticProgress = 1.5F,
+                                    startAngleDegrees = 200F,
+                                    endAngleDegrees = 520F,
+                                    colors = filledVariantProgressIndicatorColors()
+                                )
+                            }
+                        }
+                    }
+                )
+            }
 
         return collectTestCases(testCases)
     }
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/Button.kt b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/Button.kt
index 8fd28cf..c6d834e 100644
--- a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/Button.kt
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/Button.kt
@@ -17,8 +17,14 @@
 package androidx.wear.protolayout.material3
 
 import androidx.wear.protolayout.DimensionBuilders.ContainerDimension
+import androidx.wear.protolayout.DimensionBuilders.dp
 import androidx.wear.protolayout.DimensionBuilders.expand
 import androidx.wear.protolayout.DimensionBuilders.weight
+import androidx.wear.protolayout.LayoutElementBuilders.Box
+import androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER
+import androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_END
+import androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_START
+import androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignment
 import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement
 import androidx.wear.protolayout.ModifiersBuilders.Clickable
 import androidx.wear.protolayout.ModifiersBuilders.Corner
@@ -26,13 +32,23 @@
 import androidx.wear.protolayout.material3.ButtonDefaults.DEFAULT_CONTENT_PADDING
 import androidx.wear.protolayout.material3.ButtonDefaults.IMAGE_BUTTON_DEFAULT_SIZE_DP
 import androidx.wear.protolayout.material3.ButtonDefaults.METADATA_TAG_BUTTON
+import androidx.wear.protolayout.material3.ButtonDefaults.buildContentForCompactButton
+import androidx.wear.protolayout.material3.ButtonDefaults.buildContentForPillShapeButton
 import androidx.wear.protolayout.material3.ButtonDefaults.filledButtonColors
+import androidx.wear.protolayout.material3.ButtonStyle.Companion.defaultButtonStyle
+import androidx.wear.protolayout.material3.CompactButtonStyle.COMPACT_BUTTON_DEFAULT_CONTENT_PADDING_DP
+import androidx.wear.protolayout.material3.CompactButtonStyle.COMPACT_BUTTON_HEIGHT_DP
+import androidx.wear.protolayout.material3.CompactButtonStyle.COMPACT_BUTTON_ICON_SIZE_LARGE_DP
+import androidx.wear.protolayout.material3.CompactButtonStyle.COMPACT_BUTTON_ICON_SIZE_SMALL_DP
+import androidx.wear.protolayout.material3.CompactButtonStyle.COMPACT_BUTTON_LABEL_TYPOGRAPHY
 import androidx.wear.protolayout.material3.IconButtonStyle.Companion.defaultIconButtonStyle
 import androidx.wear.protolayout.material3.TextButtonStyle.Companion.defaultTextButtonStyle
 import androidx.wear.protolayout.modifiers.LayoutModifier
 import androidx.wear.protolayout.modifiers.background
 import androidx.wear.protolayout.modifiers.clip
 import androidx.wear.protolayout.modifiers.contentDescription
+import androidx.wear.protolayout.modifiers.tag
+import androidx.wear.protolayout.modifiers.toProtoLayoutModifiers
 
 /**
  * Opinionated ProtoLayout Material3 icon button that offers a single slot to take content
@@ -56,12 +72,8 @@
  *   [ButtonDefaults.filledTonalButtonColors] and [ButtonDefaults.filledVariantButtonColors]. If
  *   using custom colors, it is important to choose a color pair from same role to ensure
  *   accessibility with sufficient color contrast.
- * @param backgroundContent The background object to be used behind the content in the button. It is
- *   recommended to use the default styling that is automatically provided by only calling
- *   [backgroundImage] with the content. It can be combined with the specified
- *   [ButtonColors.container] behind it.
  * @param style The style which provides the attribute values required for constructing this icon
- *   button its inner content. It also provides default style for the inner content, that can be
+ *   button and its inner content. It also provides default style for the inner content, that can be
  *   overridden by each content slot.
  * @param contentPadding The inner padding used to prevent inner content from being too close to the
  *   button's edge. It's highly recommended to keep the default.
@@ -79,21 +91,19 @@
     height: ContainerDimension = wrapWithMinTapTargetDimension(),
     shape: Corner = shapes.full,
     colors: ButtonColors = filledButtonColors(),
-    backgroundContent: (MaterialScope.() -> LayoutElement)? = null,
     style: IconButtonStyle = defaultIconButtonStyle(),
-    contentPadding: Padding = DEFAULT_CONTENT_PADDING
+    contentPadding: Padding = style.innerPadding
 ): LayoutElement =
-    button(
+    buttonContainer(
         onClick = onClick,
-        modifier = modifier.background(color = colors.container, corner = shape),
+        modifier = modifier.background(color = colors.containerColor, corner = shape),
         width = width,
         height = height,
-        backgroundContent = backgroundContent,
         contentPadding = contentPadding,
         content = {
             withStyle(
                     defaultIconStyle =
-                        IconStyle(size = style.iconSize.toDp(), tintColor = colors.icon)
+                        IconStyle(size = dp(style.iconSize), tintColor = colors.iconColor)
                 )
                 .iconContent()
         }
@@ -121,18 +131,14 @@
  *   [ButtonDefaults.filledTonalButtonColors] and [ButtonDefaults.filledVariantButtonColors]. If
  *   using custom colors, it is important to choose a color pair from same role to ensure
  *   accessibility with sufficient color contrast.
- * @param backgroundContent The background object to be used behind the content in the button. It is
- *   recommended to use the default styling that is automatically provided by only calling
- *   [backgroundImage] with the content. It can be combined with the specified
- *   [ButtonColors.container] behind it.
- * @param style The style which provides the attribute values required for constructing this icon
- *   button its inner content. It also provides default style for the inner content, that can be
+ * @param style The style which provides the attribute values required for constructing this text
+ *   button and its inner content. It also provides default style for the inner content, that can be
  *   overridden by each content slot.
  * @param contentPadding The inner padding used to prevent inner content from being too close to the
  *   button's edge. It's highly recommended to keep the default.
  * @param labelContent The text slot for content displayed in this button. It is recommended to use
- *   default styling that is automatically provided by only calling [text] with the resource ID.
- *   This should be small, usually up to 3 characters text.
+ *   default styling that is automatically provided by only calling [text]. This should be small
+ *   text, usually up to 3 characters text.
  * @sample androidx.wear.protolayout.material3.samples.oneSlotButtonsSample
  */
 // TODO: b/346958146 - Link Button visuals in DAC
@@ -145,27 +151,277 @@
     height: ContainerDimension = wrapWithMinTapTargetDimension(),
     shape: Corner = shapes.full,
     colors: ButtonColors = filledButtonColors(),
-    backgroundContent: (MaterialScope.() -> LayoutElement)? = null,
     style: TextButtonStyle = defaultTextButtonStyle(),
-    contentPadding: Padding = DEFAULT_CONTENT_PADDING
+    contentPadding: Padding = style.innerPadding
 ): LayoutElement =
-    button(
+    buttonContainer(
         onClick = onClick,
-        modifier = modifier.background(color = colors.container, corner = shape),
+        modifier = modifier.background(color = colors.containerColor, corner = shape),
+        width = width,
+        height = height,
+        contentPadding = contentPadding,
+        content = {
+            withStyle(
+                    defaultTextElementStyle =
+                        TextElementStyle(
+                            typography = style.labelTypography,
+                            color = colors.labelColor
+                        )
+                )
+                .labelContent()
+        }
+    )
+
+/**
+ * Opinionated ProtoLayout Material3 pill shape button that offers up to three slots to take content
+ * representing vertically stacked label and secondary label, and an icon next to it.
+ *
+ * @param onClick Associated [Clickable] for click events. When the button is clicked it will fire
+ *   the associated action.
+ * @param labelContent The text slot for content displayed in this button. It is recommended to use
+ *   default styling that is automatically provided by only calling [text].
+ * @param modifier Modifiers to set to this element. It's highly recommended to set a content
+ *   description using [contentDescription].
+ * @param secondaryLabelContent The text slot for content displayed in this button. It is
+ *   recommended to use default styling that is automatically provided by only calling [text].
+ * @param iconContent The icon slot for content displayed in this button. It is recommended to use
+ *   default styling that is automatically provided by only calling [icon] with the resource ID.
+ * @param shape Defines the button's shape, in other words the corner radius for this button.
+ * @param width The width of this button. It's highly recommended to set this to [expand] or
+ *   [weight]
+ * @param height The height of this button. It's highly recommended to set this to [expand] or
+ *   [weight]
+ * @param colors The colors used for this button. If not set, [ButtonDefaults.filledButtonColors]
+ *   will be used as high emphasis button. Other recommended colors are
+ *   [ButtonDefaults.filledTonalButtonColors] and [ButtonDefaults.filledVariantButtonColors]. If
+ *   using custom colors, it is important to choose a color pair from same role to ensure
+ *   accessibility with sufficient color contrast.
+ * @param backgroundContent The background object to be used behind the content in the button. It is
+ *   recommended to use the default styling that is automatically provided by only calling
+ *   [backgroundImage] with the content. It can be combined with the specified
+ *   [ButtonColors.containerColor] behind it.
+ * @param style The style which provides the attribute values required for constructing this pill
+ *   shape button and its inner content. It also provides default style for the inner content, that
+ *   can be overridden by each content slot.
+ * @param horizontalAlignment The horizontal placement of the [labelContent] and
+ *   [secondaryLabelContent] content. If [iconContent] is present, this should be
+ *   [HORIZONTAL_ALIGN_START]. Defaults to [HORIZONTAL_ALIGN_CENTER] if only [labelContent] is
+ *   present, otherwise it default to [HORIZONTAL_ALIGN_START].
+ * @param contentPadding The inner padding used to prevent inner content from being too close to the
+ *   button's edge. It's highly recommended to keep the default.
+ * @sample androidx.wear.protolayout.material3.samples.pillShapeButtonsSample
+ * @sample androidx.wear.protolayout.material3.samples.customButtonSample
+ */
+// TODO: b/346958146 - Link Button visuals in DAC
+// TODO: b/373578620 - Add how corners affects margins in the layout.
+public fun MaterialScope.button(
+    onClick: Clickable,
+    labelContent: (MaterialScope.() -> LayoutElement),
+    modifier: LayoutModifier = LayoutModifier,
+    secondaryLabelContent: (MaterialScope.() -> LayoutElement)? = null,
+    iconContent: (MaterialScope.() -> LayoutElement)? = null,
+    width: ContainerDimension = wrapWithMinTapTargetDimension(),
+    height: ContainerDimension = wrapWithMinTapTargetDimension(),
+    shape: Corner = shapes.full,
+    colors: ButtonColors = filledButtonColors(),
+    backgroundContent: (MaterialScope.() -> LayoutElement)? = null,
+    style: ButtonStyle = defaultButtonStyle(),
+    @HorizontalAlignment
+    horizontalAlignment: Int =
+        if (iconContent == null && secondaryLabelContent == null) HORIZONTAL_ALIGN_CENTER
+        else HORIZONTAL_ALIGN_START,
+    contentPadding: Padding = style.innerPadding
+): LayoutElement =
+    buttonContainer(
+        onClick = onClick,
+        modifier = modifier.background(color = colors.containerColor, corner = shape),
         width = width,
         height = height,
         backgroundContent = backgroundContent,
         contentPadding = contentPadding,
         content = {
-            withStyle(
-                    defaultTextElementStyle =
-                        TextElementStyle(typography = style.labelTypography, color = colors.label)
-                )
-                .labelContent()
+            buildContentForPillShapeButton(
+                label =
+                    withStyle(
+                            defaultTextElementStyle =
+                                TextElementStyle(
+                                    typography = style.labelTypography,
+                                    color = colors.labelColor
+                                )
+                        )
+                        .labelContent(),
+                secondaryLabel =
+                    secondaryLabelContent?.let {
+                        withStyle(
+                                defaultTextElementStyle =
+                                    TextElementStyle(
+                                        typography = style.secondaryLabelTypography,
+                                        color = colors.secondaryLabelColor
+                                    )
+                            )
+                            .secondaryLabelContent()
+                    },
+                icon =
+                    iconContent?.let {
+                        withStyle(
+                                defaultIconStyle =
+                                    IconStyle(
+                                        size = dp(style.iconSize),
+                                        tintColor = colors.iconColor
+                                    )
+                            )
+                            .iconContent()
+                    },
+                horizontalAlignment = horizontalAlignment,
+                style = style
+            )
         }
     )
 
 /**
+ * ProtoLayout Material3 clickable image button that doesn't offer additional slots, only image (for
+ * example [backgroundImage] as a background.
+ *
+ * The button is usually stadium or circle shaped with fully rounded corners by default. It is
+ * highly recommended to set its width and height to fill the available space, by [expand] or
+ * [weight] for optimal experience across different screen sizes, and use [buttonGroup] to arrange
+ * them.
+ *
+ * @param onClick Associated [Clickable] for click events. When the button is clicked it will fire
+ *   the associated action.
+ * @param modifier Modifiers to set to this element. It's highly recommended to set a content
+ *   description using [contentDescription]. If [LayoutModifier.background] modifier is used and the
+ *   the background image is also specified, the image will be laid out on top of this color. In
+ *   case of the fully opaque background image, then the background color will not be shown.
+ * @param backgroundContent The background object to be used behind the content in the button. It is
+ *   recommended to use the default styling that is automatically provided by only calling
+ *   [backgroundImage] with the content. It can be combined with the specified
+ *   [LayoutModifier.background] behind it.
+ * @param width The width of this button. It's highly recommended to set this to [expand] or
+ *   [weight]
+ * @param height The height of this button. It's highly recommended to set this to [expand] or
+ *   [weight]
+ * @sample androidx.wear.protolayout.material3.samples.imageButtonSample
+ */
+public fun MaterialScope.imageButton(
+    onClick: Clickable,
+    backgroundContent: (MaterialScope.() -> LayoutElement),
+    modifier: LayoutModifier = LayoutModifier,
+    width: ContainerDimension = IMAGE_BUTTON_DEFAULT_SIZE_DP.toDp(),
+    height: ContainerDimension = IMAGE_BUTTON_DEFAULT_SIZE_DP.toDp()
+): LayoutElement =
+    buttonContainer(
+        onClick = onClick,
+        modifier = modifier,
+        width = width,
+        height = height,
+        backgroundContent = backgroundContent
+    )
+
+/**
+ * Opinionated ProtoLayout Material3 compact button that offers up to two slots to take horizontally
+ * stacked content representing an icon and text next to it.
+ *
+ * @param onClick Associated [Clickable] for click events. When the button is clicked it will fire
+ *   the associated action.
+ * @param modifier Modifiers to set to this element. It's highly recommended to set a content
+ *   description using [contentDescription].
+ * @param labelContent The text slot for content displayed in this button. It is recommended to use
+ *   default styling that is automatically provided by calling [text] with only the text data
+ *   parameter.
+ * @param iconContent The icon slot for content displayed in this button. It is recommended to use
+ *   default styling that is automatically provided by only calling [icon] with the resource ID.
+ * @param shape Defines the button's shape, in other words the corner radius for this button.
+ * @param width The width of this button. It's highly recommended to set this to [expand] or
+ *   [weight]
+ * @param colors The colors used for this button. If not set, [ButtonDefaults.filledButtonColors]
+ *   will be used as high emphasis button. Other recommended colors are
+ *   [ButtonDefaults.filledTonalButtonColors] and [ButtonDefaults.filledVariantButtonColors]. If
+ *   using custom colors, it is important to choose colors from the same role to ensure
+ *   accessibility with sufficient color contrast.
+ * @param horizontalAlignment The horizontal placement of the [labelContent] and [iconContent]
+ *   content. If both are present, this should be [HORIZONTAL_ALIGN_START] or [HORIZONTAL_ALIGN_END]
+ *   (in which case [iconContent] would be on the start or end side, respectively). Defaults to
+ *   [HORIZONTAL_ALIGN_CENTER] if only [labelContent] or [iconContent] is present, otherwise it
+ *   default to [HORIZONTAL_ALIGN_START].
+ * @param contentPadding The inner padding used to prevent inner content from being too close to the
+ *   button's edge. It's highly recommended to keep the default.
+ * @sample androidx.wear.protolayout.material3.samples.compactButtonsSample
+ */
+// TODO: b/346958146 - Link Button visuals in DAC
+// TODO: b/373578620 - Add how corners affects margins in the layout.
+public fun MaterialScope.compactButton(
+    onClick: Clickable,
+    modifier: LayoutModifier = LayoutModifier,
+    labelContent: (MaterialScope.() -> LayoutElement)? = null,
+    iconContent: (MaterialScope.() -> LayoutElement)? = null,
+    width: ContainerDimension = wrapWithMinTapTargetDimension(),
+    shape: Corner = shapes.full,
+    colors: ButtonColors = filledButtonColors(),
+    @HorizontalAlignment
+    horizontalAlignment: Int =
+        if (iconContent != null && labelContent != null) HORIZONTAL_ALIGN_START
+        else HORIZONTAL_ALIGN_CENTER,
+    contentPadding: Padding =
+        Padding.Builder()
+            .setStart(COMPACT_BUTTON_DEFAULT_CONTENT_PADDING_DP.toDp())
+            .setEnd(COMPACT_BUTTON_DEFAULT_CONTENT_PADDING_DP.toDp())
+            .build()
+): LayoutElement =
+    // Compact button has a fixed height of 32 dp, we need to wrap it in a box to add 8dp margin on
+    // its top and bottom for accessibility.
+    Box.Builder()
+        .addContent(
+            // The actual visible part of compact button
+            componentContainer(
+                onClick = onClick,
+                modifier = modifier.background(color = colors.containerColor, corner = shape),
+                width = width,
+                height = dp(COMPACT_BUTTON_HEIGHT_DP),
+                contentPadding = contentPadding,
+                backgroundContent = null,
+                metadataTag = null,
+                content = {
+                    buildContentForCompactButton(
+                        label =
+                            labelContent?.let {
+                                withStyle(
+                                        defaultTextElementStyle =
+                                            TextElementStyle(
+                                                typography = COMPACT_BUTTON_LABEL_TYPOGRAPHY,
+                                                color = colors.labelColor
+                                            )
+                                    )
+                                    .labelContent()
+                            },
+                        icon =
+                            iconContent?.let {
+                                withStyle(
+                                        defaultIconStyle =
+                                            IconStyle(
+                                                size =
+                                                    dp(
+                                                        if (labelContent == null)
+                                                            COMPACT_BUTTON_ICON_SIZE_LARGE_DP
+                                                        else COMPACT_BUTTON_ICON_SIZE_SMALL_DP
+                                                    ),
+                                                tintColor = colors.iconColor
+                                            )
+                                    )
+                                    .iconContent()
+                            },
+                        horizontalAlignment = horizontalAlignment,
+                        width = width
+                    )
+                }
+            )
+        )
+        .setModifiers(LayoutModifier.tag(METADATA_TAG_BUTTON).toProtoLayoutModifiers())
+        .setHeight(MINIMUM_TAP_TARGET_SIZE)
+        .setWidth(width)
+        .build()
+
+/**
  * ProtoLayout Material3 clickable component button that offers a single slot to take any content.
  *
  * The button is usually stadium or circle shaped with fully rounded corners by default. It is
@@ -175,9 +431,6 @@
  *
  * It can be used for displaying any clickable container with additional data, text or images.
  *
- * This button can also be used to create image button that only has a background image and no inner
- * content, see [androidx.wear.protolayout.material3.samples.imageButtonSample]
- *
  * @param onClick Associated [Clickable] for click events. When the button is clicked it will fire
  *   the associated action.
  * @param modifier Modifiers to set to this element. It's highly recommended to set a content
@@ -195,12 +448,8 @@
  * @param contentPadding The inner padding used to prevent inner content from being too close to the
  *   button's edge. It's highly recommended to keep the default.
  * @param content The inner content to be put inside of this button.
- * @sample androidx.wear.protolayout.material3.samples.buttonSample
- * @sample androidx.wear.protolayout.material3.samples.imageButtonSample
  */
-// TODO: b/346958146 - Link Button visuals in DAC
-// TODO: b/373578620 - Add how corners affects margins in the layout.
-public fun MaterialScope.button(
+internal fun MaterialScope.buttonContainer(
     onClick: Clickable,
     modifier: LayoutModifier = LayoutModifier,
     content: (MaterialScope.() -> LayoutElement)? = null,
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/ButtonDefaults.kt b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/ButtonDefaults.kt
index f105a4b..491d263 100644
--- a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/ButtonDefaults.kt
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/ButtonDefaults.kt
@@ -19,8 +19,17 @@
 import android.graphics.Color
 import androidx.annotation.Dimension
 import androidx.annotation.Dimension.Companion.DP
+import androidx.wear.protolayout.DimensionBuilders
+import androidx.wear.protolayout.DimensionBuilders.expand
+import androidx.wear.protolayout.LayoutElementBuilders.Box
+import androidx.wear.protolayout.LayoutElementBuilders.Column
+import androidx.wear.protolayout.LayoutElementBuilders.HORIZONTAL_ALIGN_START
+import androidx.wear.protolayout.LayoutElementBuilders.HorizontalAlignment
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement
+import androidx.wear.protolayout.LayoutElementBuilders.Row
 import androidx.wear.protolayout.ModifiersBuilders.Padding
 import androidx.wear.protolayout.material3.ButtonDefaults.DEFAULT_CONTENT_PADDING
+import androidx.wear.protolayout.material3.CompactButtonStyle.COMPACT_BUTTON_ICON_LABEL_SPACE_DP
 import androidx.wear.protolayout.material3.Typography.TypographyToken
 import androidx.wear.protolayout.modifiers.padding
 import androidx.wear.protolayout.types.LayoutColor
@@ -32,15 +41,79 @@
  */
 public class ButtonColors(
     /** The container color to be used for a button. */
-    public val container: LayoutColor = Color.BLACK.argb,
+    public val containerColor: LayoutColor = Color.BLACK.argb,
     /** The icon tint color to be used for a button. */
-    public val icon: LayoutColor = Color.BLACK.argb,
+    public val iconColor: LayoutColor = Color.BLACK.argb,
     /** The label color to be used for a button. */
-    public val label: LayoutColor = Color.BLACK.argb,
+    public val labelColor: LayoutColor = Color.BLACK.argb,
+    /** The secondary label color to be used for a button. */
+    public val secondaryLabelColor: LayoutColor = Color.BLACK.argb,
 )
 
 public object ButtonDefaults {
     /**
+     * Returns [LayoutElement] describing the inner content for the pill shape button.
+     *
+     * This is a [Row] containing the following:
+     * * icon
+     * * spacing if icon is present
+     * * labels that are in [Column]
+     */
+    internal fun buildContentForPillShapeButton(
+        label: LayoutElement,
+        secondaryLabel: LayoutElement?,
+        icon: LayoutElement?,
+        @HorizontalAlignment horizontalAlignment: Int,
+        style: ButtonStyle
+    ): LayoutElement {
+        val labels: Column.Builder =
+            Column.Builder().setWidth(expand()).setHorizontalAlignment(horizontalAlignment)
+
+        val row: Row.Builder = Row.Builder()
+
+        ContainerWithSpacersBuilder<LayoutElement>(labels::addContent, label)
+            .addElement(secondaryLabel, horizontalSpacer(style.labelsSpaceDp))
+
+        ContainerWithSpacersBuilder<LayoutElement>(row::addContent, icon)
+            .addElement(labels.build(), verticalSpacer(style.iconToLabelsSpaceDp))
+
+        return row.build()
+    }
+
+    /**
+     * Returns [LayoutElement] describing the inner content for the compact button.
+     *
+     * This is a [Row] wrapped inside of the Box for alignment, containing the following:
+     * * icon
+     * * spacing if icon is present
+     * * label
+     */
+    internal fun buildContentForCompactButton(
+        label: LayoutElement?,
+        icon: LayoutElement?,
+        @HorizontalAlignment horizontalAlignment: Int,
+        width: DimensionBuilders.ContainerDimension
+    ): LayoutElement {
+        val row: Row.Builder = Row.Builder()
+
+        // Icon can be placed on start or on end position, so we need to figure our which is first
+        // and which is second element.
+        val firstElement = if (horizontalAlignment == HORIZONTAL_ALIGN_START) icon else label
+        val secondElement = if (horizontalAlignment == HORIZONTAL_ALIGN_START) label else icon
+
+        ContainerWithSpacersBuilder<LayoutElement>(row::addContent, firstElement)
+            .addElement(secondElement, verticalSpacer(COMPACT_BUTTON_ICON_LABEL_SPACE_DP))
+
+        return Box.Builder()
+            // No need to set height specifically as that is done by the container that has it
+            // fixed.
+            .setWidth(width)
+            .addContent(row.build())
+            .setHorizontalAlignment(horizontalAlignment)
+            .build()
+    }
+
+    /**
      * [ButtonColors] for the high-emphasis button representing the primary, most important or most
      * common action on a screen.
      *
@@ -49,9 +122,10 @@
      */
     public fun MaterialScope.filledButtonColors(): ButtonColors =
         ButtonColors(
-            container = theme.colorScheme.primary,
-            icon = theme.colorScheme.onPrimary,
-            label = theme.colorScheme.onPrimary
+            containerColor = theme.colorScheme.primary,
+            iconColor = theme.colorScheme.onPrimary,
+            labelColor = theme.colorScheme.onPrimary,
+            secondaryLabelColor = theme.colorScheme.onPrimary.withOpacity(0.8f)
         )
 
     /**
@@ -62,9 +136,10 @@
      */
     public fun MaterialScope.filledTonalButtonColors(): ButtonColors =
         ButtonColors(
-            container = theme.colorScheme.surfaceContainer,
-            icon = theme.colorScheme.primary,
-            label = theme.colorScheme.onSurface
+            containerColor = theme.colorScheme.surfaceContainer,
+            iconColor = theme.colorScheme.primary,
+            labelColor = theme.colorScheme.onSurface,
+            secondaryLabelColor = theme.colorScheme.onSurfaceVariant
         )
 
     /**
@@ -75,9 +150,10 @@
      */
     public fun MaterialScope.filledVariantButtonColors(): ButtonColors =
         ButtonColors(
-            container = theme.colorScheme.primaryContainer,
-            icon = theme.colorScheme.onPrimaryContainer,
-            label = theme.colorScheme.onPrimaryContainer
+            containerColor = theme.colorScheme.primaryContainer,
+            iconColor = theme.colorScheme.onPrimaryContainer,
+            labelColor = theme.colorScheme.onPrimaryContainer,
+            secondaryLabelColor = theme.colorScheme.onPrimaryContainer.withOpacity(0.9f)
         )
 
     internal const val METADATA_TAG_BUTTON: String = "BTN"
@@ -85,10 +161,20 @@
     @Dimension(DP) internal const val IMAGE_BUTTON_DEFAULT_SIZE_DP = 52
 }
 
+/** Provides style values for the compact button component. */
+internal object CompactButtonStyle {
+    @Dimension(DP) internal const val COMPACT_BUTTON_HEIGHT_DP: Float = 32f
+    @Dimension(DP) internal const val COMPACT_BUTTON_ICON_SIZE_SMALL_DP: Float = 20f
+    @Dimension(DP) internal const val COMPACT_BUTTON_ICON_SIZE_LARGE_DP: Float = 24f
+    @Dimension(DP) internal const val COMPACT_BUTTON_DEFAULT_CONTENT_PADDING_DP: Int = 12
+    @Dimension(DP) internal const val COMPACT_BUTTON_ICON_LABEL_SPACE_DP = 6
+    @TypographyToken internal const val COMPACT_BUTTON_LABEL_TYPOGRAPHY = Typography.LABEL_SMALL
+}
+
 /** Provides style values for the icon button component. */
 public class IconButtonStyle
 internal constructor(
-    @Dimension(unit = DP) internal val iconSize: Int,
+    @Dimension(unit = DP) internal val iconSize: Float,
     internal val innerPadding: Padding = DEFAULT_CONTENT_PADDING
 ) {
     public companion object {
@@ -96,13 +182,13 @@
          * Default style variation for the [iconButton] where all opinionated inner content is
          * displayed in a medium size.
          */
-        public fun defaultIconButtonStyle(): IconButtonStyle = IconButtonStyle(26)
+        public fun defaultIconButtonStyle(): IconButtonStyle = IconButtonStyle(26f)
 
         /**
          * Default style variation for the [iconButton] where all opinionated inner content is
          * displayed in a large size.
          */
-        public fun largeIconButtonStyle(): IconButtonStyle = IconButtonStyle(32)
+        public fun largeIconButtonStyle(): IconButtonStyle = IconButtonStyle(32f)
     }
 }
 
@@ -142,3 +228,58 @@
             TextButtonStyle(Typography.DISPLAY_MEDIUM)
     }
 }
+
+/** Provides style values for the pill shape button component. */
+public class ButtonStyle
+internal constructor(
+    @TypographyToken internal val labelTypography: Int,
+    @TypographyToken internal val secondaryLabelTypography: Int,
+    @Dimension(DP) internal val iconSize: Float,
+    internal val innerPadding: Padding,
+    @Dimension(DP) internal val labelsSpaceDp: Int,
+    @Dimension(DP) internal val iconToLabelsSpaceDp: Int,
+) {
+    public companion object {
+        /**
+         * Default style variation for the [button] where all opinionated inner content is displayed
+         * in a small size.
+         */
+        public fun smallButtonStyle(): ButtonStyle =
+            ButtonStyle(
+                labelTypography = Typography.LABEL_MEDIUM,
+                secondaryLabelTypography = Typography.BODY_SMALL,
+                iconSize = 24f,
+                innerPadding = padding(horizontal = 14f, vertical = 10f),
+                labelsSpaceDp = 2,
+                iconToLabelsSpaceDp = 6
+            )
+
+        /**
+         * Default style variation for the [button] where all opinionated inner content is displayed
+         * in a medium size.
+         */
+        public fun defaultButtonStyle(): ButtonStyle =
+            ButtonStyle(
+                labelTypography = Typography.TITLE_MEDIUM,
+                secondaryLabelTypography = Typography.LABEL_SMALL,
+                iconSize = 26f,
+                innerPadding = padding(horizontal = 14f, vertical = 6f),
+                labelsSpaceDp = 0,
+                iconToLabelsSpaceDp = 8
+            )
+
+        /**
+         * Default style variation for the [button] where all opinionated inner content is displayed
+         * in a large size.
+         */
+        public fun largeButtonStyle(): ButtonStyle =
+            ButtonStyle(
+                labelTypography = Typography.LABEL_LARGE,
+                secondaryLabelTypography = Typography.LABEL_SMALL,
+                iconSize = 32f,
+                innerPadding = padding(horizontal = 14f, vertical = 8f),
+                labelsSpaceDp = 0,
+                iconToLabelsSpaceDp = 10
+            )
+    }
+}
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/Card.kt b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/Card.kt
index 8a2d807..c5fce5f 100644
--- a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/Card.kt
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/Card.kt
@@ -54,12 +54,13 @@
  * @param onClick Associated [Clickable] for click events. When the card is clicked it will fire the
  *   associated action.
  * @param title A slot for displaying the title of the card, expected to be one or two lines of
- *   text. Uses [CardColors.title] color by default.
+ *   text. Uses [CardColors.titleColor] color by default.
  * @param modifier Modifiers to set to this element. It's highly recommended to set a content
  *   description using [contentDescription].
- * @param content The optional body content of the card. Uses [CardColors.content] color by default.
+ * @param content The optional body content of the card. Uses [CardColors.contentColor] color by
+ *   default.
  * @param time An optional slot for displaying the time relevant to the contents of the card,
- *   expected to be a short piece of text. Uses [CardColors.time] color by default.
+ *   expected to be a short piece of text. Uses [CardColors.timeColor] color by default.
  * @param height The height of this card. It's highly recommended to set this to [expand] or
  *   [weight]
  * @param shape Defines the card's shape, in other words the corner radius for this card.
@@ -105,7 +106,7 @@
 ): LayoutElement =
     card(
         onClick = onClick,
-        modifier = modifier.background(colors.background).clip(shape),
+        modifier = modifier.background(colors.backgroundColor).clip(shape),
         width = expand(),
         height = height,
         backgroundContent = backgroundContent,
@@ -117,7 +118,7 @@
                         defaultTextElementStyle =
                             TextElementStyle(
                                 typography = style.titleTypography,
-                                color = colors.title,
+                                color = colors.titleColor,
                                 maxLines = 2,
                                 multilineAlignment =
                                     horizontalAlignment.horizontalAlignToTextAlign()
@@ -130,7 +131,7 @@
                             defaultTextElementStyle =
                                 TextElementStyle(
                                     typography = style.contentTypography,
-                                    color = colors.content,
+                                    color = colors.contentColor,
                                     multilineAlignment =
                                         horizontalAlignment.horizontalAlignToTextAlign()
                                 )
@@ -143,7 +144,7 @@
                             defaultTextElementStyle =
                                 TextElementStyle(
                                     typography = style.timeTypography,
-                                    color = colors.time,
+                                    color = colors.timeColor,
                                     multilineAlignment =
                                         horizontalAlignment.horizontalAlignToTextAlign()
                                 )
@@ -172,15 +173,16 @@
  * @param onClick Associated [Clickable] for click events. When the card is clicked it will fire the
  *   associated action.
  * @param title A slot for displaying the title of the card, expected to be one line of text. Uses
- *   [CardColors.title] color by default.
+ *   [CardColors.titleColor] color by default.
  * @param modifier Modifiers to set to this element. It's highly recommended to set a content
  *   description using [contentDescription].
- * @param content The optional body content of the card. Uses [CardColors.content] color by default.
+ * @param content The optional body content of the card. Uses [CardColors.contentColor] color by
+ *   default.
  * @param avatar An optional slot in header for displaying small image, such as [avatarImage].
- * @param label An optional slot in header for displaying short, label text. Uses [CardColors.label]
- *   color by default.
+ * @param label An optional slot in header for displaying short, label text. Uses
+ *   [CardColors.labelColor] color by default.
  * @param time An optional slot for displaying the time relevant to the contents of the card,
- *   expected to be a short piece of text. Uses [CardColors.time] color by default.
+ *   expected to be a short piece of text. Uses [CardColors.timeColor] color by default.
  * @param height The height of this card. It's highly recommended to leave this with default value
  *   as `wrap` if there's only 1 card on the screen. If there are two cards, it is highly
  *   recommended to set this to [expand] and use the smaller styles.
@@ -224,7 +226,7 @@
 ): LayoutElement =
     card(
         onClick = onClick,
-        modifier = modifier.background(colors.background).clip(shape),
+        modifier = modifier.background(colors.backgroundColor).clip(shape),
         width = expand(),
         height = height,
         backgroundContent = backgroundContent,
@@ -236,7 +238,7 @@
                         defaultTextElementStyle =
                             TextElementStyle(
                                 typography = style.titleTypography,
-                                color = colors.title,
+                                color = colors.titleColor,
                                 multilineAlignment = TEXT_ALIGN_START
                             )
                     )
@@ -247,7 +249,7 @@
                             defaultTextElementStyle =
                                 TextElementStyle(
                                     typography = style.contentTypography,
-                                    color = colors.content,
+                                    color = colors.contentColor,
                                     multilineAlignment = TEXT_ALIGN_START
                                 )
                         )
@@ -259,7 +261,7 @@
                             defaultTextElementStyle =
                                 TextElementStyle(
                                     typography = style.timeTypography,
-                                    color = colors.time,
+                                    color = colors.timeColor,
                                 )
                         )
                         .it()
@@ -270,7 +272,7 @@
                             defaultTextElementStyle =
                                 TextElementStyle(
                                     typography = style.labelTypography,
-                                    color = colors.label,
+                                    color = colors.labelColor,
                                     multilineAlignment = TEXT_ALIGN_START
                                 )
                         )
@@ -302,10 +304,11 @@
  * @param modifier Modifiers to set to this element. It's highly recommended to set a content
  *   description using [contentDescription].
  * @param title A slot for displaying the title of the card, expected to be one line of text. Uses
- *   [CardColors.title] color by default.
- * @param content The optional body content of the card. Uses [CardColors.content] color by default.
+ *   [CardColors.titleColor] color by default.
+ * @param content The optional body content of the card. Uses [CardColors.contentColor] color by
+ *   default.
  * @param secondaryText An optional slot for displaying short, secondary text. Uses
- *   [CardColors.secondaryText] color by default.
+ *   [CardColors.secondaryTextColor] color by default.
  * @param width The width of this card. It's highly recommended to set this to [expand] or [weight]
  *   for the most optimal experience across different screen sizes.
  * @param height The height of this card. It's highly recommended to set this to [expand] for the
@@ -354,7 +357,7 @@
 ): LayoutElement =
     card(
         onClick = onClick,
-        modifier = modifier.background(colors.background).clip(shape),
+        modifier = modifier.background(colors.backgroundColor).clip(shape),
         width = width,
         height = height,
         backgroundContent = backgroundContent,
@@ -366,7 +369,7 @@
                         defaultTextElementStyle =
                             TextElementStyle(
                                 typography = style.titleTypography,
-                                color = colors.title
+                                color = colors.titleColor
                             )
                     )
                     .title(),
@@ -376,7 +379,7 @@
                             defaultTextElementStyle =
                                 TextElementStyle(
                                     typography = style.contentTypography,
-                                    color = colors.content
+                                    color = colors.contentColor
                                 )
                         )
                         .it()
@@ -387,7 +390,7 @@
                             defaultTextElementStyle =
                                 TextElementStyle(
                                     typography = style.secondaryLabelTypography,
-                                    color = colors.secondaryText
+                                    color = colors.secondaryTextColor
                                 )
                         )
                         .it()
@@ -414,10 +417,11 @@
  * @param modifier Modifiers to set to this element. It's highly recommended to set a content
  *   description using [contentDescription].
  * @param title A slot for displaying the title of the card, expected to be one line of text. Uses
- *   [CardColors.title] color by default.
- * @param content The optional body content of the card. Uses [CardColors.content] color by default.
+ *   [CardColors.titleColor] color by default.
+ * @param content The optional body content of the card. Uses [CardColors.contentColor] color by
+ *   default.
  * @param secondaryIcon An optional slot for displaying small icon, such as [secondaryIcon]. Uses
- *   [CardColors.secondaryIcon] tint color by default.
+ *   [CardColors.secondaryIconColor] tint color by default.
  * @param width The width of this card. It's highly recommended to set this to [expand] or [weight]
  *   for the most optimal experience across different screen sizes.
  * @param height The height of this card. It's highly recommended to set this to [expand] for the
@@ -469,7 +473,7 @@
 ): LayoutElement =
     card(
         onClick = onClick,
-        modifier = modifier.background(colors.background).clip(shape),
+        modifier = modifier.background(colors.backgroundColor).clip(shape),
         width = width,
         height = height,
         backgroundContent = backgroundContent,
@@ -481,7 +485,7 @@
                         defaultTextElementStyle =
                             TextElementStyle(
                                 typography = style.titleTypography,
-                                color = colors.title
+                                color = colors.titleColor
                             )
                     )
                     .title(),
@@ -491,7 +495,7 @@
                             defaultTextElementStyle =
                                 TextElementStyle(
                                     typography = style.contentTypography,
-                                    color = colors.content
+                                    color = colors.contentColor
                                 )
                         )
                         .it()
@@ -502,7 +506,7 @@
                             defaultIconStyle =
                                 IconStyle(
                                     size = style.iconSize.toDp(),
-                                    tintColor = colors.secondaryIcon
+                                    tintColor = colors.secondaryIconColor
                                 )
                         )
                         .it()
@@ -520,10 +524,11 @@
  * @param onClick Associated [Clickable] for click events. When the card is clicked it will fire the
  *   associated action.
  * @param title A slot for displaying the title of the card, expected to be one line of text. Uses
- *   [CardColors.title] color by default.
+ *   [CardColors.titleColor] color by default.
  * @param modifier Modifiers to set to this element. It's highly recommended to set a content
  *   description using [contentDescription].
- * @param content The optional body content of the card. Uses [CardColors.content] color by default.
+ * @param content The optional body content of the card. Uses [CardColors.contentColor] color by
+ *   default.
  * @param graphic A slot for displaying graphic data, such as progress indicator.
  * @param height The width of this card. It's highly recommended to set this to [expand] for the
  *   most optimal experience across different screen sizes.
@@ -564,7 +569,7 @@
 ): LayoutElement =
     card(
         onClick = onClick,
-        modifier = modifier.background(colors.background).clip(shape),
+        modifier = modifier.background(colors.backgroundColor).clip(shape),
         width = expand(),
         height = height,
         contentPadding = contentPadding
@@ -575,7 +580,7 @@
                         defaultTextElementStyle =
                             TextElementStyle(
                                 typography = style.titleTypography,
-                                color = colors.title
+                                color = colors.titleColor
                             )
                     )
                     .title(),
@@ -585,7 +590,7 @@
                             defaultTextElementStyle =
                                 TextElementStyle(
                                     typography = style.contentTypography,
-                                    color = colors.content
+                                    color = colors.contentColor
                                 )
                         )
                         .it()
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/CardDefaults.kt b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/CardDefaults.kt
index ad91cc6..5d677d6 100644
--- a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/CardDefaults.kt
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/CardDefaults.kt
@@ -21,22 +21,22 @@
 /**
  * Represents colors used in card components, such as [titleCard] or [appCard].
  *
- * @param background [LayoutColor] which is used to as the background color for the card.
- * @param title the color used for title for the card.
- * @param content the content color for the card.
- * @param time the color used for time for the card.
- * @param label the color used for label for the card.
- * @param secondaryIcon the color used for icon in the data card type.
- * @param secondaryText the color used for secondary label for the data card type.
+ * @param backgroundColor [LayoutColor] which is used to as the background color for the card.
+ * @param titleColor the color used for title for the card.
+ * @param contentColor the content color for the card.
+ * @param timeColor the color used for time for the card.
+ * @param labelColor the color used for label for the card.
+ * @param secondaryIconColor the color used for icon in the data card type.
+ * @param secondaryTextColor the color used for secondary label for the data card type.
  */
 public class CardColors(
-    public val background: LayoutColor,
-    public val title: LayoutColor,
-    public val content: LayoutColor,
-    public val time: LayoutColor = content,
-    public val label: LayoutColor = title,
-    public val secondaryIcon: LayoutColor = title,
-    public val secondaryText: LayoutColor = time,
+    public val backgroundColor: LayoutColor,
+    public val titleColor: LayoutColor,
+    public val contentColor: LayoutColor,
+    public val timeColor: LayoutColor = contentColor,
+    public val labelColor: LayoutColor = titleColor,
+    public val secondaryIconColor: LayoutColor = titleColor,
+    public val secondaryTextColor: LayoutColor = timeColor,
 )
 
 public object CardDefaults {
@@ -49,9 +49,9 @@
      */
     public fun MaterialScope.filledCardColors(): CardColors =
         CardColors(
-            background = theme.colorScheme.primary,
-            title = theme.colorScheme.onPrimary,
-            content = theme.colorScheme.onPrimary.withOpacity(0.8f)
+            backgroundColor = theme.colorScheme.primary,
+            titleColor = theme.colorScheme.onPrimary,
+            contentColor = theme.colorScheme.onPrimary.withOpacity(0.8f)
         )
 
     /**
@@ -62,10 +62,10 @@
      */
     public fun MaterialScope.filledTonalCardColors(): CardColors =
         CardColors(
-            background = theme.colorScheme.surfaceContainer,
-            title = theme.colorScheme.onSurface,
-            content = theme.colorScheme.onSurfaceVariant,
-            secondaryIcon = theme.colorScheme.primary
+            backgroundColor = theme.colorScheme.surfaceContainer,
+            titleColor = theme.colorScheme.onSurface,
+            contentColor = theme.colorScheme.onSurfaceVariant,
+            secondaryIconColor = theme.colorScheme.primary
         )
 
     /**
@@ -76,9 +76,9 @@
      */
     public fun MaterialScope.filledVariantCardColors(): CardColors =
         CardColors(
-            background = theme.colorScheme.primaryContainer,
-            title = theme.colorScheme.onPrimaryContainer,
-            content = theme.colorScheme.onPrimaryContainer.withOpacity(0.9f)
+            backgroundColor = theme.colorScheme.primaryContainer,
+            titleColor = theme.colorScheme.onPrimaryContainer,
+            contentColor = theme.colorScheme.onPrimaryContainer.withOpacity(0.9f)
         )
 
     /**
@@ -88,9 +88,9 @@
      */
     public fun MaterialScope.imageBackgroundCardColors(): CardColors =
         CardColors(
-            background = theme.colorScheme.background,
-            title = theme.colorScheme.onBackground,
-            content = theme.colorScheme.onBackground
+            backgroundColor = theme.colorScheme.background,
+            titleColor = theme.colorScheme.onBackground,
+            contentColor = theme.colorScheme.onBackground
         )
 
     internal const val METADATA_TAG: String = "CR"
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/CircularProgressIndicator.kt b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/CircularProgressIndicator.kt
new file mode 100644
index 0000000..4a80fc3
--- /dev/null
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/CircularProgressIndicator.kt
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.protolayout.material3
+
+import androidx.annotation.Dimension
+import androidx.annotation.Dimension.Companion.DP
+import androidx.wear.protolayout.ColorBuilders.ColorProp
+import androidx.wear.protolayout.DimensionBuilders.AngularLayoutConstraint
+import androidx.wear.protolayout.DimensionBuilders.ContainerDimension
+import androidx.wear.protolayout.DimensionBuilders.DegreesProp
+import androidx.wear.protolayout.DimensionBuilders.ExpandedDimensionProp
+import androidx.wear.protolayout.DimensionBuilders.WrappedDimensionProp
+import androidx.wear.protolayout.DimensionBuilders.degrees
+import androidx.wear.protolayout.DimensionBuilders.dp
+import androidx.wear.protolayout.DimensionBuilders.expand
+import androidx.wear.protolayout.LayoutElementBuilders
+import androidx.wear.protolayout.LayoutElementBuilders.Arc
+import androidx.wear.protolayout.LayoutElementBuilders.ArcSpacer
+import androidx.wear.protolayout.LayoutElementBuilders.Box
+import androidx.wear.protolayout.LayoutElementBuilders.DashedArcLine
+import androidx.wear.protolayout.LayoutElementBuilders.DashedLinePattern
+import androidx.wear.protolayout.LayoutElementBuilders.LayoutElement
+import androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationParameters
+import androidx.wear.protolayout.expression.AnimationParameterBuilders.AnimationSpec
+import androidx.wear.protolayout.expression.AnimationParameterBuilders.Easing
+import androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor
+import androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat
+import androidx.wear.protolayout.material3.CircularProgressIndicatorDefaults.LARGE_STROKE_WIDTH
+import androidx.wear.protolayout.material3.CircularProgressIndicatorDefaults.METADATA_TAG
+import androidx.wear.protolayout.material3.CircularProgressIndicatorDefaults.calculateRecommendedGapSize
+import androidx.wear.protolayout.material3.CircularProgressIndicatorDefaults.filledProgressIndicatorColors
+import androidx.wear.protolayout.modifiers.LayoutModifier
+import androidx.wear.protolayout.modifiers.contentDescription
+import androidx.wear.protolayout.modifiers.tag
+import androidx.wear.protolayout.modifiers.toProtoLayoutModifiers
+import androidx.wear.protolayout.types.LayoutColor
+import kotlin.math.min
+
+/**
+ * Protolayout Material3 design circular progress indicator.
+ *
+ * @param staticProgress The static progress of this progress indicator where 0 represent no
+ *   progress and 1 represents completion. Progress above 1 is also allowed. If [dynamicProgress] is
+ *   also set, this static value will be ignored. By default it equals to 0.
+ * @param dynamicProgress The static progress of this progress indicator where 0 represent no
+ *   progress and 1 represents completion. Progress above 1 is also allowed. If not provided, the
+ *   [staticProgress] is used.
+ * @param modifier Modifiers to set to this element. It's highly recommended to set a content
+ *   description using [contentDescription].
+ * @param startAngleDegrees The starting position of the progress arc, measured clockwise in degrees
+ *   from the 12 o'clock position.
+ * @param endAngleDegrees The ending position of the progress arc, measured clockwise in degrees
+ *   from 12 o'clock position. Its value must be bigger than [startAngleDegrees], otherwise an
+ *   exception would be thrown. By default it equals to 'startAngleDegrees + 360'.
+ * @param strokeWidth The stroke width for the progress indicator. The recommended values are
+ *   [CircularProgressIndicatorDefaults.LARGE_STROKE_WIDTH] and
+ *   [CircularProgressIndicatorDefaults.SMALL_STROKE_WIDTH].
+ * @param gapSize The size in dp of the gap between the ends of the progress indicator and the
+ *   track. The stroke end caps are not included in this distance.
+ * @param colors [ProgressIndicatorColors] that will be used to resolve the indicator and track
+ *   color for this progress indicator.
+ * @param size The bounding box size of this progress indicator, applies to both width and height.
+ *   The indicator arc and track arc are located on the largest circle that can be inscribed inside.
+ *   It is highly recommended for the progress indicator in a graphics card to have its size as
+ *   [ExpandedDimensionProp], which is the default, to fill the available space for the best result
+ *   across different screen sizes. Setting [size] with a [WrappedDimensionProp] instance will cause
+ *   failure and throws an [IllegalArgumentException].
+ * @throws IllegalArgumentException When [size] is set to be [WrappedDimensionProp] instance or the
+ *   provided [endAngleDegrees] is smaller than the [startAngleDegrees].
+ * @sample androidx.wear.protolayout.material3.samples.singleSegmentCircularProgressIndicator
+ */
+public fun MaterialScope.circularProgressIndicator(
+    staticProgress: Float = 0F,
+    dynamicProgress: DynamicFloat? = null,
+    modifier: LayoutModifier = LayoutModifier,
+    startAngleDegrees: Float = 0F,
+    endAngleDegrees: Float = startAngleDegrees + 360F,
+    @Dimension(unit = DP) strokeWidth: Float = LARGE_STROKE_WIDTH,
+    @Dimension(unit = DP) gapSize: Float = calculateRecommendedGapSize(strokeWidth),
+    colors: ProgressIndicatorColors = filledProgressIndicatorColors(),
+    size: ContainerDimension = expand(),
+): LayoutElement {
+    if (size is WrappedDimensionProp) {
+        throw IllegalArgumentException("CircularProgressIndicator could not have size as wrap")
+    }
+
+    val modifiers = (LayoutModifier.tag(METADATA_TAG) then modifier).toProtoLayoutModifiers()
+    val validEndAngleDegrees = checkAndAdjustEndAngle(startAngleDegrees, endAngleDegrees)
+
+    return singleSegmentImpl(
+            startAngleDegrees = startAngleDegrees,
+            endAngleDegrees = validEndAngleDegrees,
+            staticProgress = staticProgress,
+            dynamicProgress = dynamicProgress,
+            strokeWidth = strokeWidth,
+            gapSize = gapSize,
+            colors = colors
+        )
+        .setModifiers(modifiers)
+        .setWidth(size)
+        .setHeight(size)
+        .build()
+}
+
+/**
+ * Layout the content for single segment progress indicator using [DashedArcLine].
+ *
+ * Note that we require valid start and end angles for calling this method.
+ */
+private fun MaterialScope.singleSegmentImpl(
+    startAngleDegrees: Float,
+    endAngleDegrees: Float,
+    staticProgress: Float,
+    dynamicProgress: DynamicFloat?,
+    @Dimension(unit = DP) strokeWidth: Float,
+    @Dimension(unit = DP) gapSize: Float,
+    colors: ProgressIndicatorColors
+): Box.Builder {
+    val sweepAngle = endAngleDegrees - startAngleDegrees
+    val progressInDegrees = progressInDegrees(sweepAngle, staticProgress, dynamicProgress)
+    val trackInDegrees = trackInDegrees(sweepAngle, progressInDegrees)
+
+    // Indicator: anchor end to startAngle, counter clockwise
+    // | half gap spacer | progress arc | full gap |
+    //                                  Track: anchor end to endAngle, clockwise
+    //                                  | full gap |  indicator arc | half gap spacer|
+    val linePattern =
+        DashedLinePattern.Builder()
+            // We set doubled gap size, as zero is the center of the gap, and we only draw
+            // from zero, this gives us one gap size as commented above. This allows
+            //    1. have a gap between indicator and track arclines
+            //    2. have a gap between head and tail when the sweep angle is 360 and only one
+            //       arcline is displayed (progress is zero or one).
+            .setGapSize(gapSize * 2)
+            .setGapLocations(0f)
+            .build()
+    val spacer =
+        ArcSpacer.Builder().setAngularLength(dp(gapSize / 2)).setThickness(dp(strokeWidth)).build()
+    return Box.Builder()
+        .addContent( // the track
+            createArc(
+                    anchorAngle = degrees(endAngleDegrees),
+                    anchorType = LayoutElementBuilders.ARC_ANCHOR_END,
+                    arcLength = trackInDegrees,
+                    arcColor = trackColor(staticProgress, dynamicProgress, colors),
+                    strokeWidth = strokeWidth,
+                    linePattern = linePattern,
+                    arcDirection = LayoutElementBuilders.ARC_DIRECTION_CLOCKWISE
+                )
+                .addContent(spacer)
+                .build()
+        )
+        .addContent( // the indicator
+            createArc(
+                    anchorAngle = degrees(-startAngleDegrees),
+                    anchorType = LayoutElementBuilders.ARC_ANCHOR_END,
+                    arcLength = progressInDegrees,
+                    arcColor = colors.indicatorColor.prop,
+                    strokeWidth = strokeWidth,
+                    linePattern = linePattern,
+                    arcDirection = LayoutElementBuilders.ARC_DIRECTION_COUNTER_CLOCKWISE
+                )
+                .addContent(spacer)
+                .build()
+        )
+}
+
+public object CircularProgressIndicatorDefaults {
+    /**
+     * Returns the recommended [ProgressIndicatorColors] object to be used when placing the progress
+     * indicator inside a graphic card with [CardDefaults.filledCardColors].
+     */
+    public fun MaterialScope.filledProgressIndicatorColors(): ProgressIndicatorColors =
+        ProgressIndicatorColors(
+            theme.colorScheme.onPrimary,
+            theme.colorScheme.onPrimary.withOpacity(0.2F),
+            theme.colorScheme.onPrimary.withOpacity(0.6F)
+        )
+
+    /**
+     * Returns the recommended [ProgressIndicatorColors] object to be used when placing the progress
+     * indicator inside a graphic card with [CardDefaults.filledTonalCardColors].
+     */
+    public fun MaterialScope.filledTonalProgressIndicatorColors(): ProgressIndicatorColors =
+        ProgressIndicatorColors(
+            theme.colorScheme.primary,
+            theme.colorScheme.primary.withOpacity(0.2F),
+            theme.colorScheme.primary.withOpacity(0.6F)
+        )
+
+    /**
+     * Returns the recommended [ProgressIndicatorColors] object to be used when placing the progress
+     * indicator inside a graphic card with [CardDefaults.filledVariantCardColors].
+     */
+    public fun MaterialScope.filledVariantProgressIndicatorColors(): ProgressIndicatorColors =
+        ProgressIndicatorColors(
+            theme.colorScheme.onPrimaryContainer,
+            theme.colorScheme.onPrimaryContainer.withOpacity(0.2F),
+            theme.colorScheme.onPrimaryContainer.withOpacity(0.6F),
+        )
+
+    /**
+     * The recommended animation spec for animations from current progress to a new progress value.
+     */
+    public val recommendedAnimationSpec: AnimationSpec =
+        AnimationSpec.Builder()
+            .setAnimationParameters(
+                AnimationParameters.Builder()
+                    .setDurationMillis(450)
+                    .setEasing(Easing.cubicBezier(0.2f, 0f, 0f, 1f))
+                    .build()
+            )
+            .build()
+
+    /** Large stroke width for circular progress indicator. */
+    @Dimension(unit = DP) public const val LARGE_STROKE_WIDTH: Float = 8F
+
+    /** Small stroke width for circular progress indicator. */
+    @Dimension(unit = DP) public const val SMALL_STROKE_WIDTH: Float = 4F
+
+    /**
+     * Returns recommended size of the gap based on [strokeWidth].
+     *
+     * The absolute value can be customized with `gapSize` parameter on [circularProgressIndicator].
+     */
+    @Dimension(unit = DP)
+    public fun calculateRecommendedGapSize(@Dimension(unit = DP) strokeWidth: Float): Float =
+        strokeWidth / 3F
+
+    internal const val METADATA_TAG: String = "M3CPI"
+}
+
+/**
+ * Represents the indicator and track colors used in progress indicator.
+ *
+ * @param indicatorColor Color used to draw the indicator of progress indicator.
+ * @param trackColor Color used to draw the track of progress indicator.
+ * @param trackOverflowColor Color used to draw the track for progress overflow (>1).
+ */
+public class ProgressIndicatorColors(
+    public val indicatorColor: LayoutColor,
+    public val trackColor: LayoutColor,
+    public val trackOverflowColor: LayoutColor = trackColor
+)
+
+/**
+ * A small offset to make the progress arc remaining when the progress is 1, with the module
+ * operation applied for handling overflow.
+ */
+private const val TRIVIAL_ARC_OFFSET: Float = 0.05f
+
+/*
+ * Check the endAngle is valid with the provided startAngle, and adjust the sweep angle to be 360
+ * maximum.
+ * @throws IllegalArgumentException When the  engAngle is smaller than the startAngle.
+ */
+private fun checkAndAdjustEndAngle(startAngle: Float, endAngle: Float): Float {
+    if (endAngle < startAngle) {
+        throw IllegalArgumentException("End angle must be bigger than start angle")
+    }
+
+    // the maximum sweep angle is 360
+    return min(endAngle, startAngle + 360F)
+}
+
+private fun progressInDegrees(
+    sweepAngle: Float,
+    staticProgress: Float,
+    dynamicProgress: DynamicFloat?,
+): DegreesProp =
+    DegreesProp.Builder((staticProgress * sweepAngle - TRIVIAL_ARC_OFFSET).mod(sweepAngle))
+        .apply {
+            dynamicProgress?.let {
+                setDynamicValue(it.times(sweepAngle).minus(TRIVIAL_ARC_OFFSET).rem(sweepAngle))
+            }
+        }
+        .build()
+
+private fun trackInDegrees(sweepAngle: Float, progressInDegrees: DegreesProp): DegreesProp =
+    DegreesProp.Builder(sweepAngle - progressInDegrees.value)
+        .apply {
+            progressInDegrees.dynamicValue?.let {
+                setDynamicValue(DynamicFloat.constant(sweepAngle).minus(it))
+            }
+        }
+        .build()
+
+private fun trackColor(
+    staticProgress: Float,
+    dynamicProgress: DynamicFloat?,
+    colors: ProgressIndicatorColors
+): ColorProp =
+    ColorProp.Builder(
+            if (staticProgress > 1) colors.trackOverflowColor.prop.argb
+            else colors.trackColor.prop.argb
+        )
+        .apply {
+            dynamicProgress?.let {
+                setDynamicValue(
+                    DynamicColor.onCondition(it.gt(1F))
+                        .use(colors.trackOverflowColor.prop.argb)
+                        .elseUse(colors.trackColor.prop.argb)
+                )
+            }
+        }
+        .build()
+
+private fun createArc(
+    anchorAngle: DegreesProp,
+    anchorType: Int,
+    arcLength: DegreesProp,
+    arcColor: ColorProp,
+    @Dimension(unit = DP) strokeWidth: Float,
+    linePattern: DashedLinePattern,
+    arcDirection: Int
+): Arc.Builder {
+    return Arc.Builder()
+        .setAnchorAngle(anchorAngle)
+        .setAnchorType(anchorType)
+        .setArcDirection(arcDirection)
+        .addContent(
+            DashedArcLine.Builder()
+                .setColor(arcColor)
+                .setThickness(strokeWidth)
+                .setLinePattern(linePattern)
+                .setLength(arcLength)
+                .setLayoutConstraintsForDynamicLength(
+                    // We use one Arc container to put one arcline, so it is fine to put 360 here
+                    // as layout constraint.
+                    AngularLayoutConstraint.Builder(360f).setAngularAlignment(anchorType).build()
+                )
+                .build()
+        )
+}
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/EdgeButton.kt b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/EdgeButton.kt
index cf093bc..e503797 100644
--- a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/EdgeButton.kt
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/EdgeButton.kt
@@ -16,7 +16,6 @@
 
 package androidx.wear.protolayout.material3
 
-import android.R.attr.clickable
 import androidx.annotation.Dimension
 import androidx.annotation.Dimension.Companion.DP
 import androidx.wear.protolayout.DimensionBuilders.dp
@@ -85,7 +84,10 @@
     iconContent: (MaterialScope.() -> LayoutElement)
 ): LayoutElement =
     edgeButton(onClick = onClick, modifier = modifier, colors = colors, style = DEFAULT) {
-        withStyle(defaultIconStyle = IconStyle(size = ICON_SIZE_DP.toDp(), tintColor = colors.icon))
+        withStyle(
+                defaultIconStyle =
+                    IconStyle(size = ICON_SIZE_DP.toDp(), tintColor = colors.iconColor)
+            )
             .iconContent()
     }
 
@@ -126,7 +128,7 @@
                 defaultTextElementStyle =
                     TextElementStyle(
                         typography = Typography.LABEL_MEDIUM,
-                        color = colors.icon,
+                        color = colors.iconColor,
                         scalable = false
                     )
             )
@@ -179,7 +181,7 @@
     var mod =
         (LayoutModifier.semanticsRole(SEMANTICS_ROLE_BUTTON) then modifier)
             .clickable(onClick)
-            .background(colors.container)
+            .background(colors.containerColor)
             .clip(TOP_CORNER_RADIUS)
             .clipBottomLeft(bottomCornerRadiusX, bottomCornerRadiusY)
             .clipBottomRight(bottomCornerRadiusX, bottomCornerRadiusY)
diff --git a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/Helpers.kt b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/Helpers.kt
index ed51c87..a95093c 100644
--- a/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/Helpers.kt
+++ b/wear/protolayout/protolayout-material3/src/main/java/androidx/wear/protolayout/material3/Helpers.kt
@@ -157,13 +157,16 @@
     height: ContainerDimension,
     backgroundContent: (MaterialScope.() -> LayoutElement)?,
     contentPadding: Padding,
-    metadataTag: String,
+    metadataTag: String?,
     content: (MaterialScope.() -> LayoutElement)?
 ): LayoutElement {
-
     val mod =
         LayoutModifier.semanticsRole(SEMANTICS_ROLE_BUTTON) then
-            modifier.clickable(onClick).tag(metadataTag)
+            if (metadataTag != null) {
+                modifier.clickable(onClick).tag(metadataTag)
+            } else {
+                modifier.clickable(onClick)
+            }
 
     val container =
         Box.Builder().setHeight(height).setWidth(width).apply {
diff --git a/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/ButtonTest.kt b/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/ButtonTest.kt
index e56e836..7f18399 100644
--- a/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/ButtonTest.kt
+++ b/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/ButtonTest.kt
@@ -21,7 +21,9 @@
 import androidx.test.core.app.ApplicationProvider.getApplicationContext
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.wear.protolayout.DeviceParametersBuilders
+import androidx.wear.protolayout.DimensionBuilders.dp
 import androidx.wear.protolayout.DimensionBuilders.expand
+import androidx.wear.protolayout.material3.CompactButtonStyle.COMPACT_BUTTON_HEIGHT_DP
 import androidx.wear.protolayout.modifiers.LayoutModifier
 import androidx.wear.protolayout.modifiers.backgroundColor
 import androidx.wear.protolayout.modifiers.clickable
@@ -72,12 +74,37 @@
     }
 
     @Test
+    fun pillButton_size_default() {
+        LayoutElementAssertionsProvider(DEFAULT_BUTTON)
+            .onRoot()
+            .assert(hasWidth(wrapWithMinTapTargetDimension()))
+            .assert(hasHeight(wrapWithMinTapTargetDimension()))
+            .assert(hasTag(ButtonDefaults.METADATA_TAG_BUTTON))
+    }
+
+    @Test
+    fun compactButton_size_default() {
+        LayoutElementAssertionsProvider(DEFAULT_COMPACT_BUTTON)
+            .onRoot()
+            .assert(hasWidth(wrapWithMinTapTargetDimension()))
+            // Invisible box
+            .assert(hasHeight(MINIMUM_TAP_TARGET_SIZE))
+            .assert(hasTag(ButtonDefaults.METADATA_TAG_BUTTON))
+
+        // Assert the visible height
+        LayoutElementAssertionsProvider(DEFAULT_COMPACT_BUTTON)
+            .onElement(hasColor(ColorScheme().primary.staticArgb))
+            .assert(hasHeight(dp(COMPACT_BUTTON_HEIGHT_DP)))
+    }
+
+    @Test
     fun imageButton_size_default() {
         LayoutElementAssertionsProvider(
                 materialScope(CONTEXT, DEVICE_CONFIGURATION) {
-                    button(
+                    imageButton(
                         onClick = CLICKABLE,
-                        modifier = LayoutModifier.contentDescription(CONTENT_DESCRIPTION)
+                        modifier = LayoutModifier.contentDescription(CONTENT_DESCRIPTION),
+                        backgroundContent = { backgroundImage(IMAGE_ID) }
                     )
                 }
             )
@@ -122,10 +149,39 @@
     }
 
     @Test
-    fun containerButton_hasBackgroundImage() {
+    fun pillButton_hasLabel_asText() {
+        LayoutElementAssertionsProvider(DEFAULT_BUTTON).onElement(hasText(TEXT)).assertExists()
+    }
+
+    @Test
+    fun pillButton_hasSecondaryLabel_asText() {
+        LayoutElementAssertionsProvider(DEFAULT_BUTTON).onElement(hasText(TEXT2)).assertExists()
+    }
+
+    @Test
+    fun pillButton_hasIcon_asIcon() {
+        LayoutElementAssertionsProvider(DEFAULT_BUTTON).onElement(hasImage(ICON_ID)).assertExists()
+    }
+
+    @Test
+    fun compactButton_hasLabel_asText() {
+        LayoutElementAssertionsProvider(DEFAULT_COMPACT_BUTTON)
+            .onElement(hasText(TEXT))
+            .assertExists()
+    }
+
+    @Test
+    fun compactButton_hasIcon_asIcon() {
+        LayoutElementAssertionsProvider(DEFAULT_COMPACT_BUTTON)
+            .onElement(hasImage(ICON_ID))
+            .assertExists()
+    }
+
+    @Test
+    fun imageButton_hasBackgroundImage() {
         val button =
             materialScope(CONTEXT, DEVICE_CONFIGURATION) {
-                button(
+                imageButton(
                     onClick = CLICKABLE,
                     modifier = LayoutModifier.contentDescription(CONTENT_DESCRIPTION),
                     backgroundContent = { backgroundImage(IMAGE_ID) }
@@ -143,7 +199,7 @@
         val color = Color.YELLOW
         val button =
             materialScope(CONTEXT, DEVICE_CONFIGURATION) {
-                button(
+                buttonContainer(
                     onClick = CLICKABLE,
                     modifier =
                         LayoutModifier.contentDescription(CONTENT_DESCRIPTION)
@@ -165,7 +221,7 @@
         val height = 12
         val button =
             materialScope(CONTEXT, DEVICE_CONFIGURATION) {
-                button(
+                buttonContainer(
                     onClick = CLICKABLE,
                     modifier = LayoutModifier.contentDescription(CONTENT_DESCRIPTION),
                     width = expand(),
@@ -199,10 +255,11 @@
         private const val ICON_ID = "id"
 
         private const val TEXT = "Container button"
+        private const val TEXT2 = "Secondary label"
 
         private val DEFAULT_CONTAINER_BUTTON_WITH_TEXT =
             materialScope(CONTEXT, DEVICE_CONFIGURATION) {
-                button(
+                buttonContainer(
                     onClick = CLICKABLE,
                     modifier = LayoutModifier.contentDescription(CONTENT_DESCRIPTION),
                     content = { text(TEXT.layoutString) }
@@ -226,5 +283,26 @@
                     labelContent = { text(TEXT.layoutString) }
                 )
             }
+
+        private val DEFAULT_BUTTON =
+            materialScope(CONTEXT, DEVICE_CONFIGURATION) {
+                button(
+                    onClick = CLICKABLE,
+                    modifier = LayoutModifier.contentDescription(CONTENT_DESCRIPTION),
+                    labelContent = { text(TEXT.layoutString) },
+                    secondaryLabelContent = { text(TEXT2.layoutString) },
+                    iconContent = { icon(ICON_ID) }
+                )
+            }
+
+        private val DEFAULT_COMPACT_BUTTON =
+            materialScope(CONTEXT, DEVICE_CONFIGURATION) {
+                compactButton(
+                    onClick = CLICKABLE,
+                    modifier = LayoutModifier.contentDescription(CONTENT_DESCRIPTION),
+                    labelContent = { text(TEXT.layoutString) },
+                    iconContent = { icon(ICON_ID) }
+                )
+            }
     }
 }
diff --git a/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/CardTest.kt b/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/CardTest.kt
index d2d2a81..c6f8562 100644
--- a/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/CardTest.kt
+++ b/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/CardTest.kt
@@ -267,10 +267,10 @@
                     modifier = LayoutModifier.contentDescription(CONTENT_DESCRIPTION),
                     colors =
                         CardColors(
-                            background = backgroundColor.argb,
-                            title = titleColor.argb,
-                            content = contentColor.argb,
-                            time = timeColor.argb
+                            backgroundColor = backgroundColor.argb,
+                            titleColor = titleColor.argb,
+                            contentColor = contentColor.argb,
+                            timeColor = timeColor.argb
                         ),
                     title = { text(TEXT.layoutString) },
                     content = { text(TEXT2.layoutString) },
@@ -301,11 +301,11 @@
                     modifier = LayoutModifier.contentDescription(CONTENT_DESCRIPTION),
                     colors =
                         CardColors(
-                            background = backgroundColor.argb,
-                            title = titleColor.argb,
-                            content = contentColor.argb,
-                            time = timeColor.argb,
-                            label = labelColor.argb
+                            backgroundColor = backgroundColor.argb,
+                            titleColor = titleColor.argb,
+                            contentColor = contentColor.argb,
+                            timeColor = timeColor.argb,
+                            labelColor = labelColor.argb
                         ),
                     title = { text(TEXT.layoutString) },
                     content = { text(TEXT2.layoutString) },
@@ -337,10 +337,10 @@
                     modifier = LayoutModifier.contentDescription(CONTENT_DESCRIPTION),
                     colors =
                         CardColors(
-                            background = backgroundColor.argb,
-                            title = titleColor.argb,
-                            content = contentColor.argb,
-                            secondaryIcon = iconColor.argb
+                            backgroundColor = backgroundColor.argb,
+                            titleColor = titleColor.argb,
+                            contentColor = contentColor.argb,
+                            secondaryIconColor = iconColor.argb
                         ),
                     title = { this.text(TEXT.layoutString) },
                     content = { this.text(TEXT2.layoutString) },
@@ -372,10 +372,10 @@
                     modifier = LayoutModifier.contentDescription(CONTENT_DESCRIPTION),
                     colors =
                         CardColors(
-                            background = backgroundColor.argb,
-                            title = titleColor.argb,
-                            content = contentColor.argb,
-                            secondaryText = secondaryLabelColor.argb
+                            backgroundColor = backgroundColor.argb,
+                            titleColor = titleColor.argb,
+                            contentColor = contentColor.argb,
+                            secondaryTextColor = secondaryLabelColor.argb
                         ),
                     title = { this.text(TEXT.layoutString) },
                     content = { this.text(TEXT2.layoutString) },
@@ -408,9 +408,9 @@
                     modifier = LayoutModifier.contentDescription(CONTENT_DESCRIPTION),
                     colors =
                         CardColors(
-                            background = backgroundColor.argb,
-                            title = titleColor.argb,
-                            content = contentColor.argb,
+                            backgroundColor = backgroundColor.argb,
+                            titleColor = titleColor.argb,
+                            contentColor = contentColor.argb,
                         ),
                     title = { text(TEXT.layoutString) },
                     content = { text(TEXT2.layoutString) },
diff --git a/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/CircularProgressIndicatorTest.kt b/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/CircularProgressIndicatorTest.kt
new file mode 100644
index 0000000..07973b83
--- /dev/null
+++ b/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/CircularProgressIndicatorTest.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.protolayout.material3
+
+import android.content.Context
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.wear.protolayout.DeviceParametersBuilders
+import androidx.wear.protolayout.DimensionBuilders.expand
+import androidx.wear.protolayout.testing.LayoutElementAssertionsProvider
+import androidx.wear.protolayout.testing.hasHeight
+import androidx.wear.protolayout.testing.hasWidth
+import org.junit.Assert.assertThrows
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.annotation.internal.DoNotInstrument
+
+@RunWith(AndroidJUnit4::class)
+@DoNotInstrument
+class CircularProgressIndicatorTest {
+    @Test
+    fun containerSize_default() {
+        LayoutElementAssertionsProvider(DEFAULT_PROGRESS_INDICATOR)
+            .onRoot()
+            .assert(hasWidth(expand()))
+            .assert(hasHeight(expand()))
+    }
+
+    @Test
+    fun containerSize_wrap_failure() {
+        assertThrows(IllegalArgumentException::class.java) {
+            materialScope(CONTEXT, DEVICE_CONFIGURATION) {
+                circularProgressIndicator(
+                    staticProgress = STATIC_PROGRESS,
+                    size = wrapWithMinTapTargetDimension(),
+                )
+            }
+        }
+    }
+
+    // TODO: b/372916396 - More tests when the testing framework also deals with ArcLayoutElements
+
+    companion object {
+        private val CONTEXT = getApplicationContext() as Context
+
+        private val DEVICE_CONFIGURATION =
+            DeviceParametersBuilders.DeviceParameters.Builder()
+                .setScreenWidthDp(192)
+                .setScreenHeightDp(192)
+                .build()
+
+        private const val STATIC_PROGRESS = 0.5F
+
+        private val DEFAULT_PROGRESS_INDICATOR =
+            materialScope(CONTEXT, DEVICE_CONFIGURATION) {
+                circularProgressIndicator(staticProgress = STATIC_PROGRESS)
+            }
+    }
+}
diff --git a/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/EdgeButtonTest.kt b/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/EdgeButtonTest.kt
index ec85a48..c8c40e5 100644
--- a/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/EdgeButtonTest.kt
+++ b/wear/protolayout/protolayout-material3/src/test/java/androidx/wear/protolayout/material3/EdgeButtonTest.kt
@@ -100,8 +100,8 @@
                         modifier = LayoutModifier.contentDescription(CONTENT_DESCRIPTION),
                         colors =
                             ButtonColors(
-                                container = COLOR_SCHEME.tertiaryContainer,
-                                icon = COLOR_SCHEME.onTertiary
+                                containerColor = COLOR_SCHEME.tertiaryContainer,
+                                iconColor = COLOR_SCHEME.onTertiary
                             ),
                     ) {
                         icon(RES_ID)
diff --git a/wear/protolayout/protolayout/api/current.txt b/wear/protolayout/protolayout/api/current.txt
index c8453dc..21886f5 100644
--- a/wear/protolayout/protolayout/api/current.txt
+++ b/wear/protolayout/protolayout/api/current.txt
@@ -1584,11 +1584,11 @@
     property @ColorInt public final int staticArgb;
   }
 
-  public final class LayoutColorKt {
-    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.types.LayoutColor asLayoutColor(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor, @ColorInt int staticArgb);
-    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.types.LayoutColor asLayoutColor(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor, @ColorInt long staticArgb);
-    method public static androidx.wear.protolayout.types.LayoutColor getArgb(int);
-    method public static androidx.wear.protolayout.types.LayoutColor getArgb(long);
+  public final class LayoutColorUtil {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.types.LayoutColor createLayoutColor(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor, @ColorInt int staticArgb);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.types.LayoutColor createLayoutColor(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor, @ColorInt long staticArgb);
+    method public static androidx.wear.protolayout.types.LayoutColor createLayoutColor(int);
+    method public static androidx.wear.protolayout.types.LayoutColor createLayoutColor(long);
   }
 
   public final class LayoutString {
@@ -1602,10 +1602,10 @@
     property public final String staticValue;
   }
 
-  public final class LayoutStringKt {
+  public final class LayoutStringUtil {
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint asLayoutConstraint(String, optional int alignment);
-    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.types.LayoutString asLayoutString(androidx.wear.protolayout.expression.DynamicBuilders.DynamicString, String staticValue, androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint layoutConstraint);
-    method public static androidx.wear.protolayout.types.LayoutString getLayoutString(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.types.LayoutString createLayoutString(androidx.wear.protolayout.expression.DynamicBuilders.DynamicString, String staticValue, androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint layoutConstraint);
+    method public static androidx.wear.protolayout.types.LayoutString createLayoutString(String);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint stringLayoutConstraint(String longestPattern);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint stringLayoutConstraint(String longestPattern, optional int alignment);
   }
diff --git a/wear/protolayout/protolayout/api/restricted_current.txt b/wear/protolayout/protolayout/api/restricted_current.txt
index c8453dc..21886f5 100644
--- a/wear/protolayout/protolayout/api/restricted_current.txt
+++ b/wear/protolayout/protolayout/api/restricted_current.txt
@@ -1584,11 +1584,11 @@
     property @ColorInt public final int staticArgb;
   }
 
-  public final class LayoutColorKt {
-    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.types.LayoutColor asLayoutColor(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor, @ColorInt int staticArgb);
-    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.types.LayoutColor asLayoutColor(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor, @ColorInt long staticArgb);
-    method public static androidx.wear.protolayout.types.LayoutColor getArgb(int);
-    method public static androidx.wear.protolayout.types.LayoutColor getArgb(long);
+  public final class LayoutColorUtil {
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.types.LayoutColor createLayoutColor(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor, @ColorInt int staticArgb);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.types.LayoutColor createLayoutColor(androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor, @ColorInt long staticArgb);
+    method public static androidx.wear.protolayout.types.LayoutColor createLayoutColor(int);
+    method public static androidx.wear.protolayout.types.LayoutColor createLayoutColor(long);
   }
 
   public final class LayoutString {
@@ -1602,10 +1602,10 @@
     property public final String staticValue;
   }
 
-  public final class LayoutStringKt {
+  public final class LayoutStringUtil {
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint asLayoutConstraint(String, optional int alignment);
-    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.types.LayoutString asLayoutString(androidx.wear.protolayout.expression.DynamicBuilders.DynamicString, String staticValue, androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint layoutConstraint);
-    method public static androidx.wear.protolayout.types.LayoutString getLayoutString(String);
+    method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.types.LayoutString createLayoutString(androidx.wear.protolayout.expression.DynamicBuilders.DynamicString, String staticValue, androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint layoutConstraint);
+    method public static androidx.wear.protolayout.types.LayoutString createLayoutString(String);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint stringLayoutConstraint(String longestPattern);
     method @androidx.wear.protolayout.expression.RequiresSchemaVersion(major=1, minor=200) public static androidx.wear.protolayout.TypeBuilders.StringLayoutConstraint stringLayoutConstraint(String longestPattern, optional int alignment);
   }
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java
index 548240c..1092f7e 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/LayoutElementBuilders.java
@@ -5401,9 +5401,9 @@
                 DimensionProto.AngularDimension angularDimensionProto =
                         angularLength.toAngularDimensionProto();
                 if ((angularDimensionProto.hasDegrees()
-                                && angularDimensionProto.getDegrees().getDynamicValue() != null)
+                        && angularDimensionProto.getDegrees().hasDynamicValue())
                         || (angularDimensionProto.hasDp()
-                                && angularDimensionProto.getDp().getDynamicValue() != null)) {
+                        && angularDimensionProto.getDp().hasDynamicValue())) {
                     throw new IllegalArgumentException(
                             "ArcSpacer.Builder.setAngularLength doesn't support dynamic values.");
                 }
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/types/LayoutColor.kt b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/types/LayoutColor.kt
index 83a5575..3a1ac50 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/types/LayoutColor.kt
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/types/LayoutColor.kt
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:JvmName("LayoutColorUtil")
 
 package androidx.wear.protolayout.types
 
@@ -54,17 +55,18 @@
 
 /** Extension for creating a [LayoutColor] from an ARGB Color Int. */
 val Int.argb: LayoutColor
-    get() = LayoutColor(this)
+    @JvmName("createLayoutColor") get() = LayoutColor(this)
 
 /** Extension for creating a [LayoutColor] from an ARGB Color Long. */
 val Long.argb: LayoutColor
-    get() = LayoutColor(this.toInt())
+    @JvmName("createLayoutColor") get() = LayoutColor(this.toInt())
 
 /**
  * Extension for creating a [LayoutColor] from a [DynamicColor]
  *
  * @param staticArgb the static value that can be used when the `dynamicValue` can't be resolved.
  */
+@JvmName("createLayoutColor")
 @RequiresSchemaVersion(major = 1, minor = 200)
 fun DynamicColor.asLayoutColor(@ColorInt staticArgb: Int) = LayoutColor(staticArgb, this)
 
@@ -73,5 +75,6 @@
  *
  * @param staticArgb the static value that can be used when the `dynamicValue` can't be resolved.
  */
+@JvmName("createLayoutColor")
 @RequiresSchemaVersion(major = 1, minor = 200)
 fun DynamicColor.asLayoutColor(@ColorInt staticArgb: Long) = LayoutColor(staticArgb.toInt(), this)
diff --git a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/types/LayoutString.kt b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/types/LayoutString.kt
index 8fafce3..735361c 100644
--- a/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/types/LayoutString.kt
+++ b/wear/protolayout/protolayout/src/main/java/androidx/wear/protolayout/types/LayoutString.kt
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+@file:JvmName("LayoutStringUtil")
 
 package androidx.wear.protolayout.types
 
@@ -86,7 +87,7 @@
 
 /** Extension for creating a [LayoutString] from a String. */
 val String.layoutString: LayoutString
-    get() = LayoutString(this)
+    @JvmName("createLayoutString") get() = LayoutString(this)
 
 /**
  * Extension for creating a [LayoutString] from a [DynamicString]
@@ -96,6 +97,7 @@
  *   ensure that the layout is of a known size during the layout pass regardless of the
  *   `dynamicValue` String.
  */
+@JvmName("createLayoutString")
 @RequiresSchemaVersion(major = 1, minor = 200)
 fun DynamicString.asLayoutString(staticValue: String, layoutConstraint: StringLayoutConstraint) =
     LayoutString(staticValue, this, layoutConstraint)
diff --git a/wear/tiles/tiles-samples/src/main/java/androidx/wear/tiles/samples/tile/PlaygroundTileService.kt b/wear/tiles/tiles-samples/src/main/java/androidx/wear/tiles/samples/tile/PlaygroundTileService.kt
index 7e18422..9171bf1 100644
--- a/wear/tiles/tiles-samples/src/main/java/androidx/wear/tiles/samples/tile/PlaygroundTileService.kt
+++ b/wear/tiles/tiles-samples/src/main/java/androidx/wear/tiles/samples/tile/PlaygroundTileService.kt
@@ -37,7 +37,9 @@
 import androidx.wear.protolayout.material3.TextButtonStyle.Companion.smallTextButtonStyle
 import androidx.wear.protolayout.material3.appCard
 import androidx.wear.protolayout.material3.avatarImage
+import androidx.wear.protolayout.material3.button
 import androidx.wear.protolayout.material3.buttonGroup
+import androidx.wear.protolayout.material3.compactButton
 import androidx.wear.protolayout.material3.graphicDataCard
 import androidx.wear.protolayout.material3.icon
 import androidx.wear.protolayout.material3.iconButton
@@ -133,6 +135,25 @@
         )
     }
 
+private fun MaterialScope.pillShapeButton() =
+    button(
+        onClick = clickable(),
+        modifier = LayoutModifier.contentDescription("Pill button"),
+        width = expand(),
+        iconContent = { icon(ICON_ID) },
+        labelContent = { text("Primary label".layoutString) },
+        secondaryLabelContent = { text("Secondary label".layoutString) },
+    )
+
+private fun MaterialScope.compactShapeButton() =
+    compactButton(
+        onClick = clickable(),
+        modifier = LayoutModifier.contentDescription("Compact button"),
+        width = expand(),
+        iconContent = { icon(ICON_ID) },
+        labelContent = { text("Overflowing compact button".layoutString) },
+    )
+
 private fun MaterialScope.oneSlotButtons() = buttonGroup {
     buttonGroupItem {
         iconButton(
@@ -173,10 +194,10 @@
         modifier = LayoutModifier.contentDescription("Sample Card"),
         colors =
             CardColors(
-                background = colorScheme.tertiary,
-                title = colorScheme.onTertiary,
-                content = colorScheme.onTertiary,
-                time = colorScheme.onTertiary
+                backgroundColor = colorScheme.tertiary,
+                titleColor = colorScheme.onTertiary,
+                contentColor = colorScheme.onTertiary,
+                timeColor = colorScheme.onTertiary
             ),
         title = {
             text(
diff --git a/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/ComplicationData.kt b/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/ComplicationData.kt
index dd2f39f..b7ae82d 100644
--- a/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/ComplicationData.kt
+++ b/wear/watchface/watchface-complications-data/src/main/java/android/support/wearable/complications/ComplicationData.kt
@@ -1877,8 +1877,8 @@
          *
          * Returns this Builder to allow chaining.
          */
-        fun setColorRampIsSmoothShaded(isSmoothShaded: Boolean?) = apply {
-            putOrRemoveField(FIELD_COLOR_RAMP_INTERPOLATED, isSmoothShaded)
+        fun setColorRampInterpolated(isColorRampInterpolated: Boolean?) = apply {
+            putOrRemoveField(FIELD_COLOR_RAMP_INTERPOLATED, isColorRampInterpolated)
         }
 
         /**
diff --git a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Data.kt b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Data.kt
index d5f3a4c..f76741d 100644
--- a/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Data.kt
+++ b/wear/watchface/watchface-complications-data/src/main/java/androidx/wear/watchface/complications/data/Data.kt
@@ -42,7 +42,6 @@
 import androidx.wear.watchface.complications.data.RangedValueComplicationData.Companion.TYPE_RATING
 import androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Companion.PLACEHOLDER
 import androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Companion.getMaxElements
-import androidx.wear.watchface.complications.data.WeightedElementsComplicationData.Element
 import java.time.Instant
 
 internal const val TAG = "Data.kt"
@@ -1229,7 +1228,7 @@
         builder.setTapActionLostDueToSerialization(tapActionLostDueToSerialization)
         colorRamp?.let {
             builder.setColorRamp(it.colors)
-            builder.setColorRampIsSmoothShaded(it.interpolated)
+            builder.setColorRampInterpolated(it.interpolated)
         }
         builder.setRangedValueType(valueType)
     }
@@ -1589,7 +1588,7 @@
         builder.setTapActionLostDueToSerialization(tapActionLostDueToSerialization)
         colorRamp?.let {
             builder.setColorRamp(it.colors)
-            builder.setColorRampIsSmoothShaded(it.interpolated)
+            builder.setColorRampInterpolated(it.interpolated)
         }
     }
 
diff --git a/wear/watchface/watchface-complications-data/src/test/java/android/support/wearable/complications/ComplicationDataEqualityTest.kt b/wear/watchface/watchface-complications-data/src/test/java/android/support/wearable/complications/ComplicationDataEqualityTest.kt
index 81209bd..5f17f9b 100644
--- a/wear/watchface/watchface-complications-data/src/test/java/android/support/wearable/complications/ComplicationDataEqualityTest.kt
+++ b/wear/watchface/watchface-complications-data/src/test/java/android/support/wearable/complications/ComplicationDataEqualityTest.kt
@@ -211,8 +211,8 @@
             { setColorRamp(intArrayOf(3, 4)).build() },
         ),
         COLOR_RAMP_IS_SMOOTH_SHADED(
-            { setColorRampIsSmoothShaded(true).build() },
-            { setColorRampIsSmoothShaded(false).build() },
+            { setColorRampInterpolated(true).build() },
+            { setColorRampInterpolated(false).build() },
         ),
         LIST_ENTRY_COLLECTION(
             { setListEntryCollection(listOf(staticData("1"))).build() },
diff --git a/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/DataTest.kt b/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/DataTest.kt
index 6be3482..2042f20 100644
--- a/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/DataTest.kt
+++ b/wear/watchface/watchface-complications-data/src/test/java/androidx/wear/watchface/complications/data/DataTest.kt
@@ -710,7 +710,7 @@
                     .setContentDescription(WireComplicationText.plainText("content description"))
                     .setDataSource(dataSource)
                     .setColorRamp(intArrayOf(Color.RED, Color.GREEN, Color.BLUE))
-                    .setColorRampIsSmoothShaded(true)
+                    .setColorRampInterpolated(true)
                     .setPersistencePolicy(ComplicationPersistencePolicies.CACHING_ALLOWED)
                     .setDisplayPolicy(ComplicationDisplayPolicies.ALWAYS_DISPLAY)
                     .build()
@@ -767,7 +767,7 @@
                     .setContentDescription(WireComplicationText.plainText("content description"))
                     .setDataSource(dataSource)
                     .setColorRamp(intArrayOf(Color.RED, Color.GREEN, Color.BLUE))
-                    .setColorRampIsSmoothShaded(true)
+                    .setColorRampInterpolated(true)
                     .setPersistencePolicy(ComplicationPersistencePolicies.CACHING_ALLOWED)
                     .setDisplayPolicy(ComplicationDisplayPolicies.ALWAYS_DISPLAY)
                     .build()
@@ -830,7 +830,7 @@
                     .setContentDescription(WireComplicationText.plainText("content description"))
                     .setDataSource(dataSource)
                     .setColorRamp(intArrayOf(Color.RED, Color.GREEN, Color.BLUE))
-                    .setColorRampIsSmoothShaded(true)
+                    .setColorRampInterpolated(true)
                     .setPersistencePolicy(ComplicationPersistencePolicies.CACHING_ALLOWED)
                     .setDisplayPolicy(ComplicationDisplayPolicies.ALWAYS_DISPLAY)
                     .setExtras(extras)
@@ -1491,7 +1491,7 @@
                             )
                             .setDataSource(dataSource)
                             .setColorRamp(intArrayOf(Color.RED, Color.GREEN, Color.BLUE))
-                            .setColorRampIsSmoothShaded(false)
+                            .setColorRampInterpolated(false)
                             .setPersistencePolicy(ComplicationPersistencePolicies.CACHING_ALLOWED)
                             .setDisplayPolicy(ComplicationDisplayPolicies.ALWAYS_DISPLAY)
                             .setExtras(extras)
@@ -1630,7 +1630,7 @@
                             )
                             .setDataSource(dataSource)
                             .setColorRamp(intArrayOf(Color.RED, Color.GREEN, Color.BLUE))
-                            .setColorRampIsSmoothShaded(true)
+                            .setColorRampInterpolated(true)
                             .setPersistencePolicy(ComplicationPersistencePolicies.CACHING_ALLOWED)
                             .setDisplayPolicy(ComplicationDisplayPolicies.ALWAYS_DISPLAY)
                             .setExtras(extras)
@@ -1974,7 +1974,7 @@
                 .setShortTitle(WireComplicationText.plainText("steps"))
                 .setContentDescription(WireComplicationText.plainText("content description"))
                 .setColorRamp(intArrayOf(Color.RED, Color.GREEN, Color.BLUE))
-                .setColorRampIsSmoothShaded(false)
+                .setColorRampInterpolated(false)
                 .setPersistencePolicy(ComplicationPersistencePolicies.CACHING_ALLOWED)
                 .setDisplayPolicy(ComplicationDisplayPolicies.ALWAYS_DISPLAY)
                 .build(),
@@ -1991,7 +1991,7 @@
                 .setShortTitle(WireComplicationText.plainText("steps"))
                 .setContentDescription(WireComplicationText.plainText("content description"))
                 .setColorRamp(intArrayOf(Color.RED, Color.GREEN, Color.BLUE))
-                .setColorRampIsSmoothShaded(false)
+                .setColorRampInterpolated(false)
                 .setPersistencePolicy(ComplicationPersistencePolicies.CACHING_ALLOWED)
                 .setDisplayPolicy(ComplicationDisplayPolicies.ALWAYS_DISPLAY)
                 .build(),
@@ -2159,7 +2159,7 @@
                             WireComplicationText.plainText("content description")
                         )
                         .setColorRamp(intArrayOf(Color.RED, Color.GREEN, Color.BLUE))
-                        .setColorRampIsSmoothShaded(true)
+                        .setColorRampInterpolated(true)
                         .setIcon(icon)
                         .setPersistencePolicy(ComplicationPersistencePolicies.CACHING_ALLOWED)
                         .setDisplayPolicy(ComplicationDisplayPolicies.ALWAYS_DISPLAY)
@@ -2799,7 +2799,7 @@
                     .setShortTitle(WireComplicationText.plainText("steps"))
                     .setContentDescription(WireComplicationText.plainText("content description"))
                     .setColorRamp(intArrayOf(Color.YELLOW, Color.MAGENTA))
-                    .setColorRampIsSmoothShaded(true)
+                    .setColorRampInterpolated(true)
                     .setStartDateTimeMillis(testStartInstant.toEpochMilli())
                     .setEndDateTimeMillis(testEndDateInstant.toEpochMilli())
                     .setPersistencePolicy(ComplicationPersistencePolicies.CACHING_ALLOWED)
@@ -3002,7 +3002,7 @@
                                 WireComplicationText.plainText("content description")
                             )
                             .setColorRamp(intArrayOf(Color.RED, Color.GREEN, Color.BLUE))
-                            .setColorRampIsSmoothShaded(false)
+                            .setColorRampInterpolated(false)
                             .setPersistencePolicy(ComplicationPersistencePolicies.CACHING_ALLOWED)
                             .setDisplayPolicy(ComplicationDisplayPolicies.ALWAYS_DISPLAY)
                             .build()
diff --git a/webkit/integration-tests/instrumentation/src/androidTest/java/androidx/webkit/URLUtilCompatTest.java b/webkit/integration-tests/instrumentation/src/androidTest/java/androidx/webkit/URLUtilCompatTest.java
index 74087c7..c31152b 100644
--- a/webkit/integration-tests/instrumentation/src/androidTest/java/androidx/webkit/URLUtilCompatTest.java
+++ b/webkit/integration-tests/instrumentation/src/androidTest/java/androidx/webkit/URLUtilCompatTest.java
@@ -31,7 +31,7 @@
 /**
  * Tests for {@link URLUtilCompat}.
  *
- * This test suite does not use "image/jpeg" as a mime type, as this can result in 2
+ * <p>This test suite does not use "image/jpeg" as a mime type, as this can result in 2
  * different extensions depending on the OS platform, which leads to flakes.
  */
 @SmallTest
@@ -39,16 +39,6 @@
 public class URLUtilCompatTest {
 
     @Test
-    public void guessFileName_ctsTest() {
-        // This test mirrors the test in
-        // cts/tests/tests/webkit/src/android/webkit/cts/URLUtilTest.java for completeness.
-        String url = "ftp://example.url/test";
-        assertEquals("test.gif", URLUtilCompat.guessFileName(url, null, "image/gif"));
-        assertEquals("test.bin",
-                URLUtilCompat.guessFileName(url, null, "application/octet-stream"));
-    }
-
-    @Test
     public void guessFileName_extractPathSegmentFromUrl() {
         String url = "https://example.com/resources/image?size=large";
         assertEquals("image.gif", URLUtilCompat.guessFileName(url, null, "image/gif"));
@@ -77,15 +67,9 @@
     }
 
     @Test
-    public void guessFileName_txtExtensionForUnknownTxtType() {
-        String url = "https://example.com/index";
-        assertEquals("index.txt", URLUtilCompat.guessFileName(url, null, "text/fantasy"));
-    }
-
-    @Test
     public void guessFileName_fallbackIfNoFilenamesAvailable() {
         String url = "https://example.com/";
-        assertEquals("downloadfile.bin", URLUtilCompat.guessFileName(url, null, null));
+        assertEquals("downloadfile", URLUtilCompat.guessFileName(url, null, null));
     }
 
     @Test
@@ -96,11 +80,17 @@
     }
 
     @Test
-    public void guessFileName_contentDispositionNameGetsAppendedMimeType() {
+    public void guessFileName_contentDispositionDoesNotGetMimeTypeExtension() {
         String url = "https://example.com/wrong";
         String contentDisposition = "attachment; filename=Test.png";
-        assertEquals("Test.png.gif",
-                URLUtilCompat.guessFileName(url, contentDisposition, "image/gif"));
+        assertEquals("Test.png", URLUtilCompat.guessFileName(url, contentDisposition, "image/gif"));
+    }
+
+    @Test
+    public void guessFileName_contentDispositionDoesNotGetMimeTypeExtensionEvenIfMissing() {
+        String url = "https://example.com/wrong";
+        String contentDisposition = "attachment; filename=Test";
+        assertEquals("Test", URLUtilCompat.guessFileName(url, contentDisposition, "image/gif"));
     }
 
     @Test
@@ -124,7 +114,6 @@
         assertEquals("Test.png", URLUtilCompat.guessFileName(url, contentDisposition, null));
     }
 
-
     @Test
     public void parseContentDisposition_nullIfDispositionIsInline() {
         assertNull(URLUtilCompat.getFilenameFromContentDisposition("inline; filename=Test.png"));
diff --git a/webkit/webkit/api/current.txt b/webkit/webkit/api/current.txt
index 9e58425..77fa0ba 100644
--- a/webkit/webkit/api/current.txt
+++ b/webkit/webkit/api/current.txt
@@ -54,6 +54,15 @@
     field public final int httpResponseStatusCode;
   }
 
+  @SuppressCompatibility @androidx.webkit.WebViewCompat.ExperimentalUrlPrerender public class PrerenderException extends java.lang.Exception {
+    ctor public PrerenderException(String, Throwable?);
+  }
+
+  @SuppressCompatibility @androidx.webkit.WebViewCompat.ExperimentalUrlPrerender public interface PrerenderOperationCallback {
+    method public void onError(androidx.webkit.PrerenderException);
+    method public void onPrerenderActivated();
+  }
+
   public class ProcessGlobalConfig {
     ctor public ProcessGlobalConfig();
     method public static void apply(androidx.webkit.ProcessGlobalConfig);
@@ -397,6 +406,8 @@
     method @AnyThread @RequiresFeature(name=androidx.webkit.WebViewFeature.MULTI_PROCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean isMultiProcessEnabled();
     method @RequiresFeature(name=androidx.webkit.WebViewFeature.VISUAL_STATE_CALLBACK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") @UiThread public static void postVisualStateCallback(android.webkit.WebView, long, androidx.webkit.WebViewCompat.VisualStateCallback);
     method @RequiresFeature(name=androidx.webkit.WebViewFeature.POST_WEB_MESSAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") @UiThread public static void postWebMessage(android.webkit.WebView, androidx.webkit.WebMessageCompat, android.net.Uri);
+    method @SuppressCompatibility @AnyThread @RequiresFeature(name=androidx.webkit.WebViewFeature.PRERENDER_WITH_URL, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") @androidx.webkit.WebViewCompat.ExperimentalUrlPrerender public static void prerenderUrlAsync(android.webkit.WebView, String, androidx.core.os.CancellationSignal?, androidx.webkit.PrerenderOperationCallback);
+    method @SuppressCompatibility @AnyThread @RequiresFeature(name=androidx.webkit.WebViewFeature.PRERENDER_WITH_URL, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") @androidx.webkit.WebViewCompat.ExperimentalUrlPrerender public static void prerenderUrlAsync(android.webkit.WebView, String, androidx.core.os.CancellationSignal?, androidx.webkit.SpeculativeLoadingParameters, androidx.webkit.PrerenderOperationCallback);
     method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_LISTENER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") @UiThread public static void removeWebMessageListener(android.webkit.WebView, String);
     method @RequiresFeature(name=androidx.webkit.WebViewFeature.MUTE_AUDIO, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") @UiThread public static void setAudioMuted(android.webkit.WebView, boolean);
     method @AnyThread @RequiresFeature(name=androidx.webkit.WebViewFeature.DEFAULT_TRAFFICSTATS_TAGGING, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setDefaultTrafficStatsTag(int);
@@ -412,6 +423,9 @@
   @SuppressCompatibility @RequiresOptIn(level=androidx.annotation.RequiresOptIn.Level.ERROR) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD}) public static @interface WebViewCompat.ExperimentalAsyncStartUp {
   }
 
+  @SuppressCompatibility @RequiresOptIn(level=androidx.annotation.RequiresOptIn.Level.ERROR) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD}) public static @interface WebViewCompat.ExperimentalUrlPrerender {
+  }
+
   public static interface WebViewCompat.VisualStateCallback {
     method @UiThread public void onComplete(long);
   }
@@ -448,6 +462,7 @@
     field public static final String MUTE_AUDIO = "MUTE_AUDIO";
     field public static final String OFF_SCREEN_PRERASTER = "OFF_SCREEN_PRERASTER";
     field public static final String POST_WEB_MESSAGE = "POST_WEB_MESSAGE";
+    field @SuppressCompatibility @androidx.webkit.WebViewCompat.ExperimentalUrlPrerender public static final String PRERENDER_WITH_URL = "PRERENDER_URL";
     field @SuppressCompatibility @androidx.webkit.Profile.ExperimentalUrlPrefetch public static final String PROFILE_URL_PREFETCH = "PREFETCH_URL_V3";
     field public static final String PROXY_OVERRIDE = "PROXY_OVERRIDE";
     field public static final String PROXY_OVERRIDE_REVERSE_BYPASS = "PROXY_OVERRIDE_REVERSE_BYPASS";
diff --git a/webkit/webkit/api/restricted_current.txt b/webkit/webkit/api/restricted_current.txt
index 9e58425..77fa0ba 100644
--- a/webkit/webkit/api/restricted_current.txt
+++ b/webkit/webkit/api/restricted_current.txt
@@ -54,6 +54,15 @@
     field public final int httpResponseStatusCode;
   }
 
+  @SuppressCompatibility @androidx.webkit.WebViewCompat.ExperimentalUrlPrerender public class PrerenderException extends java.lang.Exception {
+    ctor public PrerenderException(String, Throwable?);
+  }
+
+  @SuppressCompatibility @androidx.webkit.WebViewCompat.ExperimentalUrlPrerender public interface PrerenderOperationCallback {
+    method public void onError(androidx.webkit.PrerenderException);
+    method public void onPrerenderActivated();
+  }
+
   public class ProcessGlobalConfig {
     ctor public ProcessGlobalConfig();
     method public static void apply(androidx.webkit.ProcessGlobalConfig);
@@ -397,6 +406,8 @@
     method @AnyThread @RequiresFeature(name=androidx.webkit.WebViewFeature.MULTI_PROCESS, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static boolean isMultiProcessEnabled();
     method @RequiresFeature(name=androidx.webkit.WebViewFeature.VISUAL_STATE_CALLBACK, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") @UiThread public static void postVisualStateCallback(android.webkit.WebView, long, androidx.webkit.WebViewCompat.VisualStateCallback);
     method @RequiresFeature(name=androidx.webkit.WebViewFeature.POST_WEB_MESSAGE, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") @UiThread public static void postWebMessage(android.webkit.WebView, androidx.webkit.WebMessageCompat, android.net.Uri);
+    method @SuppressCompatibility @AnyThread @RequiresFeature(name=androidx.webkit.WebViewFeature.PRERENDER_WITH_URL, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") @androidx.webkit.WebViewCompat.ExperimentalUrlPrerender public static void prerenderUrlAsync(android.webkit.WebView, String, androidx.core.os.CancellationSignal?, androidx.webkit.PrerenderOperationCallback);
+    method @SuppressCompatibility @AnyThread @RequiresFeature(name=androidx.webkit.WebViewFeature.PRERENDER_WITH_URL, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") @androidx.webkit.WebViewCompat.ExperimentalUrlPrerender public static void prerenderUrlAsync(android.webkit.WebView, String, androidx.core.os.CancellationSignal?, androidx.webkit.SpeculativeLoadingParameters, androidx.webkit.PrerenderOperationCallback);
     method @RequiresFeature(name=androidx.webkit.WebViewFeature.WEB_MESSAGE_LISTENER, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") @UiThread public static void removeWebMessageListener(android.webkit.WebView, String);
     method @RequiresFeature(name=androidx.webkit.WebViewFeature.MUTE_AUDIO, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") @UiThread public static void setAudioMuted(android.webkit.WebView, boolean);
     method @AnyThread @RequiresFeature(name=androidx.webkit.WebViewFeature.DEFAULT_TRAFFICSTATS_TAGGING, enforcement="androidx.webkit.WebViewFeature#isFeatureSupported") public static void setDefaultTrafficStatsTag(int);
@@ -412,6 +423,9 @@
   @SuppressCompatibility @RequiresOptIn(level=androidx.annotation.RequiresOptIn.Level.ERROR) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD}) public static @interface WebViewCompat.ExperimentalAsyncStartUp {
   }
 
+  @SuppressCompatibility @RequiresOptIn(level=androidx.annotation.RequiresOptIn.Level.ERROR) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD}) public static @interface WebViewCompat.ExperimentalUrlPrerender {
+  }
+
   public static interface WebViewCompat.VisualStateCallback {
     method @UiThread public void onComplete(long);
   }
@@ -448,6 +462,7 @@
     field public static final String MUTE_AUDIO = "MUTE_AUDIO";
     field public static final String OFF_SCREEN_PRERASTER = "OFF_SCREEN_PRERASTER";
     field public static final String POST_WEB_MESSAGE = "POST_WEB_MESSAGE";
+    field @SuppressCompatibility @androidx.webkit.WebViewCompat.ExperimentalUrlPrerender public static final String PRERENDER_WITH_URL = "PRERENDER_URL";
     field @SuppressCompatibility @androidx.webkit.Profile.ExperimentalUrlPrefetch public static final String PROFILE_URL_PREFETCH = "PREFETCH_URL_V3";
     field public static final String PROXY_OVERRIDE = "PROXY_OVERRIDE";
     field public static final String PROXY_OVERRIDE_REVERSE_BYPASS = "PROXY_OVERRIDE_REVERSE_BYPASS";
diff --git a/webkit/webkit/src/main/java/androidx/webkit/PrerenderException.java b/webkit/webkit/src/main/java/androidx/webkit/PrerenderException.java
new file mode 100644
index 0000000..e05f88a
--- /dev/null
+++ b/webkit/webkit/src/main/java/androidx/webkit/PrerenderException.java
@@ -0,0 +1,32 @@
+/*
+ * 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.webkit;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+/**
+ * Super class for all asynchronous exceptions produced by
+ * {@link WebViewCompat} prerender operations.
+ */
[email protected]
+public class PrerenderException extends Exception {
+
+    public PrerenderException(@NonNull String error, @Nullable Throwable cause) {
+        super(error, cause);
+    }
+}
diff --git a/webkit/webkit/src/main/java/androidx/webkit/PrerenderOperationCallback.java b/webkit/webkit/src/main/java/androidx/webkit/PrerenderOperationCallback.java
new file mode 100644
index 0000000..377ef26
--- /dev/null
+++ b/webkit/webkit/src/main/java/androidx/webkit/PrerenderOperationCallback.java
@@ -0,0 +1,40 @@
+/*
+ * 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.webkit;
+
+import org.jspecify.annotations.NonNull;
+
+/**
+ * Callback interface for the prerender operation.
+ */
[email protected]
+public interface PrerenderOperationCallback {
+    /**
+     * Called when a prerendered page is activated (used for an actual navigation).
+     * Use this callback to perform any necessary actions when the prerendering completes and the
+     * page becomes active.
+     */
+    void onPrerenderActivated();
+
+    /**
+     * Called when the prerender operation fails.
+     *
+     * @param exception The exception indicating the cause of the failure.
+     */
+    void onError(@NonNull PrerenderException exception);
+
+}
diff --git a/webkit/webkit/src/main/java/androidx/webkit/SpeculativeLoadingParameters.java b/webkit/webkit/src/main/java/androidx/webkit/SpeculativeLoadingParameters.java
index aacc89a..b485d51 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/SpeculativeLoadingParameters.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/SpeculativeLoadingParameters.java
@@ -16,6 +16,8 @@
 
 package androidx.webkit;
 
+import android.webkit.WebSettings;
+
 import androidx.annotation.RequiresFeature;
 
 import org.jspecify.annotations.NonNull;
@@ -96,6 +98,10 @@
          * for the same key, the latest value will be used.
          * <p>
          * Header keys must be RFC 2616-compliant.
+         * <p>
+         * The logic for handling additional header isn't guaranteed to match the
+         * {@link android.webkit.WebView#loadUrl(String, Map)}'s logic and is subject to change
+         * in the future.
          */
         @Profile.ExperimentalUrlPrefetch
         public @NonNull Builder addAdditionalHeader(@NonNull String key, @NonNull String value) {
@@ -135,6 +141,10 @@
          * {@code true} if the WebView's that will be loading the prefetched
          * response will have javascript enabled. This affects whether or not
          * client hints header is sent with the prefetch request.
+         * <p>
+         * Note: This flag is ignored for prefetches initiated by the
+         * prerendering API. The value from
+         * {@link WebSettings#getJavaScriptEnabled()} will be used instead.
          */
         @Profile.ExperimentalUrlPrefetch
         public @NonNull Builder setJavaScriptEnabled(boolean javaScriptEnabled) {
diff --git a/webkit/webkit/src/main/java/androidx/webkit/URLUtilCompat.java b/webkit/webkit/src/main/java/androidx/webkit/URLUtilCompat.java
index 38c92ae..4761400 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/URLUtilCompat.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/URLUtilCompat.java
@@ -48,26 +48,15 @@
      * <ul>
      *  <li>This method uses an updated parsing of {@code contentDisposition}, making this
      *  available on older Android versions. See {@link #getFilenameFromContentDisposition(String)}.
-     *  <li>If the filename guessed from {@code url} or {@code contentDisposition} already
-     *  contains an extension, but this extension differs from the one expected from the
-     *  {@code mimeType}, then this method will append the expected extension instead of
-     *  replacing the one already present. This is done to preserve filenames that contain a
-     *  {@code "."} as part of a filename but where the last part is not meant as an  extension.
-     *  <li>If the filename guessed from {@code contentDisposition} contains a {@code "/"}
-     *  character, it will be replaced with {@code "_"}, unlike
-     *  {@link android.webkit.URLUtil#guessFileName(String, String, String)} which will only
-     *  return the part after the last {@code "/" character}.
-     * </ul>
-     * <p>
-     * This method will use {@link #getFilenameFromContentDisposition(String)} to parse the
-     * passed {@code contentDisposition}.
-     * <ul>
-     * <li>If not file extension is present in the guessed file name, one will be added based on
-     * the
-     * {@code mimetype} (this will be {@code ".bin"} if {@code mimeType} is {@code null}).
-     * <li>If the guessed file name already contains an extension, but this extension doesn't
-     * match a provided {@code mimeType}, then a new file extension will be added that matches
-     * the {@code mimeType}.
+     *  <li>If the {@code contentDisposition} parameter is valid and contains a filename, that
+     *  filename will be returned. The {@code url} and {@code mimeType} parameters will not be
+     *  used in this case.
+     *  <li>Otherwise the filename will be deduced from the path of the {@code url} and the
+     *  {@code mimeType}. If a {@code mimeType} is provided and the canonical extension for that
+     *  filetype does not match the filename derived from the {@code url}, then the canonical
+     *  extension will be appended.
+     *  <li>If the {@code mimeType} is {@code null}, {@code "application/octet-stream"}, or not
+     *  known by the system, no extension will be appended to the filename.
      * </ul>
      *
      * @param url                Url to the content. Must not be {@code null}
@@ -79,33 +68,8 @@
      */
     public static @NonNull String guessFileName(@NonNull String url,
             @Nullable String contentDisposition, @Nullable String mimeType) {
-        String filename = getFilenameSuggestion(url, contentDisposition);
-        // Split filename between base and extension
-        // Add an extension if filename does not have one
-        String extensionFromMimeType = suggestExtensionFromMimeType(mimeType);
 
-        if (filename.indexOf('.') < 0) {
-            // Filename does not have an extension, use the suggested one.
-            return filename + extensionFromMimeType;
-        }
-
-        // Filename already contains at least one dot.
-        // Compare the last segment of the extension against the mime type.
-        // If there's a mismatch, add the suggested extension instead.
-        if (mimeType != null && extensionDifferentFromMimeType(filename, mimeType)) {
-            return filename + extensionFromMimeType;
-        }
-        return filename;
-    }
-
-    /**
-     * Get the suggested file name from the {@code contentDisposition} or {@code url}. Will
-     * ensure that the filename contains no path separators by replacing them with the {@code "_"}
-     * character.
-     */
-    private static @NonNull String getFilenameSuggestion(@NonNull String url,
-            @Nullable String contentDisposition) {
-        // First attempt to parse the Content-Disposition header if available
+        // First attempt to parse the Content-Disposition header if available.
         if (contentDisposition != null) {
             String filename = getFilenameFromContentDisposition(contentDisposition);
             if (filename != null) {
@@ -113,17 +77,23 @@
             }
         }
 
-        // Try to generate a filename based on the URL.
+        // Fallback filename.
+        String filename = "downloadfile";
+
         Uri parsedUri = Uri.parse(url);
         if (parsedUri != null) {
             String lastPathSegment = parsedUri.getLastPathSegment();
             if (lastPathSegment != null) {
-                return replacePathSeparators(lastPathSegment);
+                filename = replacePathSeparators(lastPathSegment);
             }
         }
 
-        // Finally, if couldn't get filename from URI, get a generic filename.
-        return "downloadfile";
+        // Ensure that filenames guessed from the URL path has an extension matching the mimeType.
+        if (filename.indexOf('.') < 0 || extensionDifferentFromMimeType(filename, mimeType)) {
+            String extensionFromMimeType = suggestExtensionFromMimeType(mimeType);
+            return filename + extensionFromMimeType;
+        }
+        return filename;
     }
 
     /**
@@ -136,40 +106,45 @@
 
 
     /**
-     * Check if the {@code filename} has an extension that is different from the expected one based
-     * on the {@code mimeType}.
-     */
-    private static boolean extensionDifferentFromMimeType(@NonNull String filename,
-            @NonNull String mimeType) {
-        int lastDotIndex = filename.lastIndexOf('.');
-        String typeFromExt = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
-                filename.substring(lastDotIndex + 1));
-        return typeFromExt != null && !typeFromExt.equalsIgnoreCase(mimeType);
-    }
-
-    /**
      * Get a candidate file extension (including the @{code .}) for the given mimeType.
-     * will return {@code ".bin"} if {@code mimeType} is {@code null}
+     * Will return empty string for {@code null}, {@code "application/octet-stream"}, and any
+     * unknown mime types.
      *
      * @param mimeType Reported mimetype
-     * @return A file extension, including the {@code .}
+     * @return A file extension, including the {@code .}, or empty string
      */
     private static @NonNull String suggestExtensionFromMimeType(@Nullable String mimeType) {
         if (mimeType == null) {
-            return ".bin";
+            return "";
+        }
+        mimeType = mimeType.trim().toLowerCase(Locale.ROOT);
+        if (mimeType.equals("application/octet-stream")) {
+            // Octet-stream is a generic extension that really doesn't map to anything, despite the
+            // MimeTypeMap insisting that it maps to ".bin".
+            // Handle this as a special case and return an empty guess.
+            return "";
         }
         String extensionFromMimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType(
                 mimeType);
         if (extensionFromMimeType != null) {
             return "." + extensionFromMimeType;
         }
-        if (mimeType.equalsIgnoreCase("text/html")) {
-            return ".html";
-        } else if (mimeType.toLowerCase(Locale.ROOT).startsWith("text/")) {
-            return ".txt";
-        } else {
-            return ".bin";
+        return "";
+    }
+
+    /**
+     * Check if the {@code filename} has an extension that is different from the expected one based
+     * on the {@code mimeType}.
+     */
+    private static boolean extensionDifferentFromMimeType(@NonNull String filename,
+            @Nullable String mimeType) {
+        if (mimeType == null) {
+            return false;
         }
+        int lastDotIndex = filename.lastIndexOf('.');
+        String typeFromExt = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
+                filename.substring(lastDotIndex + 1));
+        return typeFromExt != null && !typeFromExt.equalsIgnoreCase(mimeType);
     }
 
     /**
@@ -179,6 +154,7 @@
      * For the single- and double-quoted options, the pattern allows escaped quotes as part of
      * the value, as per
      * <a href="https://datatracker.ietf.org/doc/html/rfc2616#section-2.2">RFC 2616 section 2.2</a>
+     *
      * @noinspection RegExpRepeatedSpace Spaces are ignored by parser, there for readability.
      */
     private static final Pattern DISPOSITION_PATTERN = Pattern.compile(
diff --git a/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java b/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java
index e2791fe..0fde2c0 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java
@@ -35,6 +35,7 @@
 import androidx.annotation.RequiresOptIn;
 import androidx.annotation.RestrictTo;
 import androidx.annotation.UiThread;
+import androidx.core.os.CancellationSignal;
 import androidx.webkit.internal.ApiFeature;
 import androidx.webkit.internal.ApiHelperForM;
 import androidx.webkit.internal.ApiHelperForO;
@@ -1328,6 +1329,94 @@
         }
     }
 
+    /**
+     * Denotes that the PrerenderUrl API surface is experimental.
+     * <p>
+     * It may change without warning and should not be relied upon for non-experimental purposes.
+     */
+    @Retention(RetentionPolicy.CLASS)
+    @Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD})
+    @RequiresOptIn(level = RequiresOptIn.Level.ERROR)
+    public @interface ExperimentalUrlPrerender {
+    }
+
+    /**
+     * Starts a URL prerender request for this WebView. Can be called from any
+     * thread.
+     * <p>
+     * This WebView will use a URL request matching algorithm during execution
+     * of all variants of {@link android.webkit.WebView#loadUrl(String)} for
+     * determining if there was a prerender request executed for the
+     * provided URL. This includes prerender requests that are "in progress".
+     * If a prerender request is matched, WebView will leverage that for
+     * handling the URL, otherwise the URL will be handled normally (i.e.
+     * through a network request).
+     * <p>
+     * Applications will still be responsible for calling
+     * {@link android.webkit.WebView#loadUrl(String)} to display web contents
+     * in a WebView.
+     * <p>
+     * A prerendered page can also match a navigation initiated by clicking a
+     * hyperlink.
+     * <p>
+     * Only supports HTTPS scheme.
+     * <p>
+     * The {@link CancellationSignal} will make the best effort to cancel an
+     * in-flight prerender request; however cancellation it is not guaranteed.
+     * <p>
+     * All result callbacks will be resolved on the calling thread.
+     *
+     * @param webView            the WebView for which we trigger the prerender request.
+     * @param url                the url associated with the prerender request.
+     * @param cancellationSignal used to trigger prerender cancellation.
+     * @param callback           callbacks for reporting result back to application.
+     */
+    @RequiresFeature(name = WebViewFeature.PRERENDER_WITH_URL,
+            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
+    @AnyThread
+    @ExperimentalUrlPrerender
+    public static void prerenderUrlAsync(
+            @NonNull WebView webView,
+            @NonNull String url,
+            @Nullable CancellationSignal cancellationSignal,
+            @NonNull PrerenderOperationCallback callback) {
+        ApiFeature.NoFramework feature = WebViewFeatureInternal.PRERENDER_WITH_URL;
+        if (feature.isSupportedByWebView()) {
+            getProvider(webView).prerenderUrlAsync(url, cancellationSignal, callback);
+        } else {
+            throw WebViewFeatureInternal.getUnsupportedOperationException();
+        }
+    }
+
+    /**
+     * The same as
+     * {@link WebViewCompat#prerenderUrlAsync(WebView, String, CancellationSignal, PrerenderOperationCallback)},
+     * but allows customizing the request by providing {@link SpeculativeLoadingParameters}.
+     *
+     * @param webView            the WebView for which we trigger the prerender request.
+     * @param url                the url associated with the prerender request.
+     * @param cancellationSignal used to trigger prerender cancellation.
+     * @param params             parameters to customize the prerender request.
+     * @param callback           callbacks for reporting result back to application.
+     */
+    @RequiresFeature(name = WebViewFeature.PRERENDER_WITH_URL,
+            enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
+    @AnyThread
+    @ExperimentalUrlPrerender
+    public static void prerenderUrlAsync(
+            @NonNull WebView webView,
+            @NonNull String url,
+            @Nullable CancellationSignal cancellationSignal,
+            @NonNull SpeculativeLoadingParameters params,
+            @NonNull PrerenderOperationCallback callback) {
+        ApiFeature.NoFramework feature = WebViewFeatureInternal.PRERENDER_WITH_URL;
+        if (feature.isSupportedByWebView()) {
+            getProvider(webView).prerenderUrlAsync(url, cancellationSignal, params, callback);
+        } else {
+            throw WebViewFeatureInternal.getUnsupportedOperationException();
+        }
+    }
+
     private static WebViewProviderFactory getFactory() {
         return WebViewGlueCommunicator.getFactory();
     }
diff --git a/webkit/webkit/src/main/java/androidx/webkit/WebViewFeature.java b/webkit/webkit/src/main/java/androidx/webkit/WebViewFeature.java
index 3d3a653..2ff0751 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/WebViewFeature.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/WebViewFeature.java
@@ -118,6 +118,7 @@
             BACK_FORWARD_CACHE,
             DEFAULT_TRAFFICSTATS_TAGGING,
             DELETE_BROWSING_DATA,
+            PRERENDER_WITH_URL,
     })
     @Retention(RetentionPolicy.SOURCE)
     @Target({ElementType.PARAMETER, ElementType.METHOD})
@@ -650,6 +651,15 @@
     public static final String DELETE_BROWSING_DATA = "DELETE_BROWSING_DATA";
 
     /**
+     * Feature for {@link #isFeatureSupported(String)}.
+     * This feature covers
+     * {@link androidx.webkit.WebViewCompat#prerenderUrlAsync(WebView, String,
+     * SpeculativeLoadingParameters, CancellationSignal, PrerenderOperationCallback)}}
+     */
+    @WebViewCompat.ExperimentalUrlPrerender
+    public static final String PRERENDER_WITH_URL = "PRERENDER_URL";
+
+    /**
      * Return whether a feature is supported at run-time. This will check whether a feature is
      * supported, depending on the combination of the desired feature, the Android version of
      * device, and the WebView APK on the device.
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
index efde9bc..dc818ef 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
@@ -686,6 +686,16 @@
             new ApiFeature.NoFramework(WebViewFeature.DEFAULT_TRAFFICSTATS_TAGGING,
                     Features.DEFAULT_TRAFFICSTATS_TAGGING);
 
+    /**
+     * Feature for {@link WebViewFeature#isFeatureSupported(String)}.
+     * This feature covers {@link androidx.webkit.WebViewCompat#prerenderUrlAsync(WebView, String,
+     * SpeculativeLoadingParameters, CancellationSignal, PrerenderOperationCallback)}}
+     */
+    public static final ApiFeature.NoFramework PRERENDER_WITH_URL =
+            new ApiFeature.NoFramework(WebViewFeature.PRERENDER_WITH_URL,
+                    Features.PRERENDER_WITH_URL);
+
+
     // --- Add new feature constants above this line ---
 
     private WebViewFeatureInternal() {
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewProviderAdapter.java b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewProviderAdapter.java
index f1b08cd..1eb7d18 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewProviderAdapter.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewProviderAdapter.java
@@ -18,11 +18,16 @@
 
 import android.annotation.SuppressLint;
 import android.net.Uri;
+import android.webkit.ValueCallback;
 import android.webkit.WebChromeClient;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
 
+import androidx.core.os.CancellationSignal;
+import androidx.webkit.PrerenderException;
+import androidx.webkit.PrerenderOperationCallback;
 import androidx.webkit.Profile;
+import androidx.webkit.SpeculativeLoadingParameters;
 import androidx.webkit.WebMessageCompat;
 import androidx.webkit.WebMessagePortCompat;
 import androidx.webkit.WebViewCompat;
@@ -188,4 +193,57 @@
     public void setAudioMuted(boolean mute) {
         mImpl.setAudioMuted(mute);
     }
+
+    /**
+     * Adapter method for
+     * {@link WebViewCompat#prerenderUrlAsync(WebView, String, CancellationSignal,
+     * PrerenderOperationCallback)}.
+     */
+    public void prerenderUrlAsync(
+            @NonNull String url,
+            @Nullable CancellationSignal cancellationSignal,
+            @NonNull PrerenderOperationCallback callback) {
+
+        ValueCallback<Void> activationCallback = (value) -> {
+            // value will always be null.
+            callback.onPrerenderActivated();
+        };
+        ValueCallback<Throwable> errorCallback = (throwable) -> {
+            callback.onError(new PrerenderException("Prerender operation failed", throwable));
+        };
+        mImpl.prerenderUrl(
+                url,
+                cancellationSignal,
+                activationCallback,
+                errorCallback);
+    }
+
+    /**
+     * Adapter method for
+     * {@link WebViewCompat#prerenderUrlAsync(WebView, String, CancellationSignal,
+     * SpeculativeLoadingParameters, PrerenderOperationCallback)}.
+     */
+    public void prerenderUrlAsync(
+            @NonNull String url,
+            @Nullable CancellationSignal cancellationSignal,
+            @NonNull SpeculativeLoadingParameters params,
+            @NonNull PrerenderOperationCallback callback) {
+
+        InvocationHandler paramsBoundaryInterface =
+                BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(
+                        new SpeculativeLoadingParametersAdapter(params));
+        ValueCallback<Void> activationCallback = (value) -> {
+            // value will always be null.
+            callback.onPrerenderActivated();
+        };
+        ValueCallback<Throwable> errorCallback = (throwable) -> {
+            callback.onError(new PrerenderException("Prerender operation failed", throwable));
+        };
+        mImpl.prerenderUrl(
+                url,
+                cancellationSignal,
+                paramsBoundaryInterface,
+                activationCallback,
+                errorCallback);
+    }
 }
diff --git a/window/window-demos/demo/lint-baseline.xml b/window/window-demos/demo/lint-baseline.xml
index d4d73fc..57a5f51 100644
--- a/window/window-demos/demo/lint-baseline.xml
+++ b/window/window-demos/demo/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.9.0-alpha06" type="baseline" client="gradle" dependencies="false" name="AGP (8.9.0-alpha06)" variant="all" version="8.9.0-alpha06">
+<issues format="6" by="lint 8.8.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (8.8.0-alpha08)" variant="all" version="8.8.0-alpha08">
 
     <issue
         id="NewApi"
@@ -29,19 +29,19 @@
     </issue>
 
     <issue
-        id="NewApi"
-        message="Call requires API level 30 (current min is 23): `android.view.WindowManager.LayoutParams#setFitInsetsTypes`"
-        errorLine1="            attrs.fitInsetsTypes = WindowInsets.Type.statusBars()"
-        errorLine2="                                 ~">
+        id="WrongConstant"
+        message="Must be one or more of: LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON, LayoutParams.FLAG_DIM_BEHIND, LayoutParams.FLAG_BLUR_BEHIND, LayoutParams.FLAG_NOT_FOCUSABLE, LayoutParams.FLAG_NOT_TOUCHABLE, LayoutParams.FLAG_NOT_TOUCH_MODAL, LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING, LayoutParams.FLAG_KEEP_SCREEN_ON, LayoutParams.FLAG_LAYOUT_IN_SCREEN, LayoutParams.FLAG_LAYOUT_NO_LIMITS, LayoutParams.FLAG_FULLSCREEN, LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, LayoutParams.FLAG_DITHER, LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SCALED, LayoutParams.FLAG_IGNORE_CHEEK_PRESSES, LayoutParams.FLAG_LAYOUT_INSET_DECOR, LayoutParams.FLAG_ALT_FOCUSABLE_IM, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_SHOW_WHEN_LOCKED, LayoutParams.FLAG_SHOW_WALLPAPER, LayoutParams.FLAG_TURN_SCREEN_ON, LayoutParams.FLAG_DISMISS_KEYGUARD, LayoutParams.FLAG_SPLIT_TOUCH, LayoutParams.FLAG_HARDWARE_ACCELERATED, LayoutParams.FLAG_LAYOUT_IN_OVERSCAN, LayoutParams.FLAG_TRANSLUCENT_STATUS, LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, LayoutParams.FLAG_LOCAL_FOCUS_MODE, LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR, LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS"
+        errorLine1="                        ?.or(android.R.attr.showWhenLocked or android.R.attr.turnScreenOn)"
+        errorLine2="                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
-            file="src/main/java/androidx/window/demo/embedding/SplitImeActivityPlaceholder.kt"/>
+            file="src/main/java/androidx/window/demo/PresentationActivity.kt"/>
     </issue>
 
     <issue
         id="WrongConstant"
         message="Must be one or more of: LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON, LayoutParams.FLAG_DIM_BEHIND, LayoutParams.FLAG_BLUR_BEHIND, LayoutParams.FLAG_NOT_FOCUSABLE, LayoutParams.FLAG_NOT_TOUCHABLE, LayoutParams.FLAG_NOT_TOUCH_MODAL, LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING, LayoutParams.FLAG_KEEP_SCREEN_ON, LayoutParams.FLAG_LAYOUT_IN_SCREEN, LayoutParams.FLAG_LAYOUT_NO_LIMITS, LayoutParams.FLAG_FULLSCREEN, LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, LayoutParams.FLAG_DITHER, LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SCALED, LayoutParams.FLAG_IGNORE_CHEEK_PRESSES, LayoutParams.FLAG_LAYOUT_INSET_DECOR, LayoutParams.FLAG_ALT_FOCUSABLE_IM, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_SHOW_WHEN_LOCKED, LayoutParams.FLAG_SHOW_WALLPAPER, LayoutParams.FLAG_TURN_SCREEN_ON, LayoutParams.FLAG_DISMISS_KEYGUARD, LayoutParams.FLAG_SPLIT_TOUCH, LayoutParams.FLAG_HARDWARE_ACCELERATED, LayoutParams.FLAG_LAYOUT_IN_OVERSCAN, LayoutParams.FLAG_TRANSLUCENT_STATUS, LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, LayoutParams.FLAG_LOCAL_FOCUS_MODE, LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR, LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS"
         errorLine1="                        ?.or(android.R.attr.showWhenLocked or android.R.attr.turnScreenOn)"
-        errorLine2="                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine2="                                                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="src/main/java/androidx/window/demo/PresentationActivity.kt"/>
     </issue>
diff --git a/window/window/src/androidTest/java/androidx/window/TestActivityEdgeToEdge.kt b/window/window/src/androidTest/java/androidx/window/TestActivityEdgeToEdge.kt
index 3541b59..bd16e08 100644
--- a/window/window/src/androidTest/java/androidx/window/TestActivityEdgeToEdge.kt
+++ b/window/window/src/androidTest/java/androidx/window/TestActivityEdgeToEdge.kt
@@ -18,10 +18,8 @@
 
 import android.os.Build
 import android.os.Bundle
-import android.view.View
 import android.view.WindowManager.LayoutParams
 import androidx.core.view.WindowCompat
-import androidx.window.layout.WindowMetricsCalculator
 
 @Suppress("DEPRECATION") // Old ways of setting edge to edge are deprecated
 class TestActivityEdgeToEdge : TestActivity() {
@@ -31,40 +29,16 @@
         window.setFlags(LayoutParams.FLAG_FULLSCREEN, LayoutParams.FLAG_FULLSCREEN)
         WindowCompat.setDecorFitsSystemWindows(window, false)
 
-        val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
         if (Build.VERSION.SDK_INT >= 30) {
-            windowInsetsController.hide(android.view.WindowInsets.Type.statusBars())
-            windowInsetsController.hide(android.view.WindowInsets.Type.navigationBars())
-            windowInsetsController.hide(android.view.WindowInsets.Type.displayCutout())
-            windowInsetsController.hide(android.view.WindowInsets.Type.systemBars())
+            window.attributes.layoutInDisplayCutoutMode =
+                LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+        } else if (Build.VERSION.SDK_INT >= 28) {
+            window.attributes.layoutInDisplayCutoutMode =
+                LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
         }
 
         setContentView(androidx.window.test.R.layout.activity_edge_to_edge)
 
-        val rootView = findViewById<View>(androidx.window.test.R.id.view_home).rootView
-        rootView.systemUiVisibility =
-            View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN
-
-        if (Build.VERSION.SDK_INT >= 28) {
-            val params = LayoutParams()
-            params.layoutInDisplayCutoutMode = LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
-            window.attributes = params
-        }
         this.actionBar?.hide()
     }
-
-    fun waitForExpectedBounds() {
-        val currentWindowMetrics =
-            WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this)
-        val rootView = findViewById<View>(androidx.window.test.R.id.view_home).rootView
-        if (
-            currentWindowMetrics.bounds.width() == rootView.width &&
-                currentWindowMetrics.bounds.height() == rootView.height
-        ) {
-            return
-        } else {
-            resetLayoutCounter()
-            waitForLayout()
-        }
-    }
 }
diff --git a/window/window/src/androidTest/java/androidx/window/layout/WindowMetricsCalculatorCompatTest.kt b/window/window/src/androidTest/java/androidx/window/layout/WindowMetricsCalculatorCompatTest.kt
index 4c6ca0c..66eccdd 100644
--- a/window/window/src/androidTest/java/androidx/window/layout/WindowMetricsCalculatorCompatTest.kt
+++ b/window/window/src/androidTest/java/androidx/window/layout/WindowMetricsCalculatorCompatTest.kt
@@ -282,7 +282,6 @@
     fun testWindowMetricBoundsMatchesEdgeToEdgeFullScreenView() {
         val scenario = ActivityScenario.launch(TestActivityEdgeToEdge::class.java)
         scenario.moveToState(Lifecycle.State.RESUMED)
-        scenario.onActivity { activity -> activity.waitForExpectedBounds() }
         scenario.onActivity { activity ->
             val windowMetrics =
                 WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity)
diff --git a/work/work-runtime/src/androidTest/java/androidx/work/impl/background/systemjob/SystemJobInfoConverterTest.java b/work/work-runtime/src/androidTest/java/androidx/work/impl/background/systemjob/SystemJobInfoConverterTest.java
index 6397ca8..63dec45 100644
--- a/work/work-runtime/src/androidTest/java/androidx/work/impl/background/systemjob/SystemJobInfoConverterTest.java
+++ b/work/work-runtime/src/androidTest/java/androidx/work/impl/background/systemjob/SystemJobInfoConverterTest.java
@@ -230,8 +230,10 @@
 
     @Test
     @SmallTest
-    @SdkSuppress(minSdkVersion = 29)
+    @SdkSuppress(minSdkVersion = 29, maxSdkVersion = 34)
     public void testConvert_setImportantWhileForeground() {
+        // Switch maxSdkVersion to 35 after B gets an official SDK version.
+        // setImportantWhileInForeground() turns into a no-op starting API 36.
         WorkSpec workSpec = getTestWorkSpecWithConstraints(new Constraints.Builder().build());
         workSpec.lastEnqueueTime = System.currentTimeMillis();
         JobInfo jobInfo = mConverter.convert(workSpec, JOB_ID);
diff --git a/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/AnchorTest.kt b/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/AnchorTest.kt
index 49453a2..063267d 100644
--- a/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/AnchorTest.kt
+++ b/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/AnchorTest.kt
@@ -38,7 +38,6 @@
 import kotlinx.coroutines.test.runTest
 import org.junit.After
 import org.junit.Before
-import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -47,6 +46,7 @@
 class AnchorTest {
 
     private lateinit var xrResourcesManager: XrResourcesManager
+    private lateinit var session: Session
 
     @get:Rule
     val grantPermissionRule = GrantPermissionRule.grant("android.permission.SCENE_UNDERSTANDING")
@@ -121,68 +121,70 @@
             .isEqualTo(RuntimeAnchor.PersistenceState.Persisted)
     }
 
-    @Ignore("Flaky test, see b/379198572")
     @Test
-    fun getPersistedAnchorUuids_previouslyPersistedAnchor_returnsPersistedAnchorUuid() = runTest {
-        val session = createTestSession()
-        val runtimeAnchor =
-            FakeRuntimeAnchor(Pose(), session.runtime.perceptionManager as FakePerceptionManager)
-        val underTest = Anchor(runtimeAnchor, xrResourcesManager)
-        var uuid: UUID? = null
-        val persistJob = launch { uuid = underTest.persist() }
-        val updateJob = launch { underTest.update() }
-        updateJob.join()
-        persistJob.join()
+    fun getPersistedAnchorUuids_previouslyPersistedAnchor_returnsPersistedAnchorUuid() =
+        createTestSessionAndRunTest {
+            runTest {
+                val runtimeAnchor =
+                    FakeRuntimeAnchor(
+                        Pose(),
+                        session.runtime.perceptionManager as FakePerceptionManager
+                    )
+                val underTest = Anchor(runtimeAnchor, xrResourcesManager)
+                var uuid: UUID? = null
+                val persistJob = launch { uuid = underTest.persist() }
+                val updateJob = launch { underTest.update() }
+                updateJob.join()
+                persistJob.join()
 
-        assertThat(Anchor.getPersistedAnchorUuids(session)).containsExactly(uuid)
+                assertThat(Anchor.getPersistedAnchorUuids(session)).containsExactly(uuid)
+            }
+        }
+
+    @Test
+    fun getPersistedAnchorUuids_noPreviouslyPersistedAnchors_returnsEmptyList() =
+        createTestSessionAndRunTest {
+            assertThat(Anchor.getPersistedAnchorUuids(session)).isEmpty()
+        }
+
+    @Test
+    fun load_previouslyPersistedAnchor_returnsAnchorCreateSuccess() = createTestSessionAndRunTest {
+        runTest {
+            val runtimeAnchor =
+                FakeRuntimeAnchor(
+                    Pose(),
+                    session.runtime.perceptionManager as FakePerceptionManager
+                )
+            val underTest = Anchor(runtimeAnchor, xrResourcesManager)
+            var uuid: UUID? = null
+            val persistJob = launch { uuid = underTest.persist() }
+            val updateJob = launch { underTest.update() }
+            updateJob.join()
+            persistJob.join()
+
+            assertThat(Anchor.load(session, uuid!!)).isInstanceOf(AnchorCreateSuccess::class.java)
+        }
     }
 
     @Test
-    @Ignore("Flaky test, see b/380269912")
-    fun getPersistedAnchorUuids_noPreviouslyPersistedAnchors_returnsEmptyList() = runTest {
-        val session = createTestSession()
+    fun unpersist_removesAnchorFromStorage() = createTestSessionAndRunTest {
+        runTest {
+            val runtimeAnchor =
+                FakeRuntimeAnchor(
+                    Pose(),
+                    session.runtime.perceptionManager as FakePerceptionManager
+                )
+            val underTest = Anchor(runtimeAnchor, xrResourcesManager)
+            var uuid: UUID? = null
+            val persistJob = launch { uuid = underTest.persist() }
+            val updateJob = launch { underTest.update() }
+            updateJob.join()
+            persistJob.join()
 
-        assertThat(Anchor.getPersistedAnchorUuids(session)).isEmpty()
-    }
+            Anchor.unpersist(session, uuid!!)
 
-    @Test
-    fun load_previouslyPersistedAnchor_returnsAnchorCreateSuccess() = runTest {
-        val session = createTestSession()
-        val runtimeAnchor =
-            FakeRuntimeAnchor(Pose(), session.runtime.perceptionManager as FakePerceptionManager)
-        val underTest = Anchor(runtimeAnchor, xrResourcesManager)
-        var uuid: UUID? = null
-        val persistJob = launch { uuid = underTest.persist() }
-        val updateJob = launch { underTest.update() }
-        updateJob.join()
-        persistJob.join()
-
-        assertThat(Anchor.load(session, uuid!!)).isInstanceOf(AnchorCreateSuccess::class.java)
-    }
-
-    @Ignore("Flaky test, see b/384999184")
-    @Test
-    fun loadFromNativePointer_returnsAnchorCreateSuccess() = runTest {
-        val session = createTestSession()
-
-        assertThat(Anchor.loadFromNativePointer(session, 123L)).isNotNull()
-    }
-
-    @Test
-    fun unpersist_removesAnchorFromStorage() = runTest {
-        val session = createTestSession()
-        val runtimeAnchor =
-            FakeRuntimeAnchor(Pose(), session.runtime.perceptionManager as FakePerceptionManager)
-        val underTest = Anchor(runtimeAnchor, xrResourcesManager)
-        var uuid: UUID? = null
-        val persistJob = launch { uuid = underTest.persist() }
-        val updateJob = launch { underTest.update() }
-        updateJob.join()
-        persistJob.join()
-
-        Anchor.unpersist(session, uuid!!)
-
-        assertThat(Anchor.getPersistedAnchorUuids(session)).doesNotContain(uuid)
+            assertThat(Anchor.getPersistedAnchorUuids(session)).doesNotContain(uuid)
+        }
     }
 
     @Test
@@ -241,15 +243,15 @@
         assertThat(underTest1.hashCode()).isNotEqualTo(underTest2.hashCode())
     }
 
-    private fun createTestSession(): Session {
-        var session: Session? = null
+    private fun createTestSessionAndRunTest(testBody: () -> Unit) {
         ActivityScenario.launch(Activity::class.java).use {
             it.onActivity { activity ->
                 session =
                     (Session.create(activity, StandardTestDispatcher()) as SessionCreateSuccess)
                         .session
+
+                testBody()
             }
         }
-        return checkNotNull(session) { "Session must not be null." }
     }
 }
diff --git a/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/InteractionTest.kt b/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/InteractionTest.kt
index 8a91c6c..b3b6d63 100644
--- a/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/InteractionTest.kt
+++ b/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/InteractionTest.kt
@@ -35,7 +35,6 @@
 import kotlin.time.TestTimeSource
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.runTest
-import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -52,50 +51,47 @@
     @get:Rule
     val grantPermissionRule = GrantPermissionRule.grant("android.permission.SCENE_UNDERSTANDING")
 
-    @Before
-    fun setUp() {
-        session = createTestSession()
-        timeSource = (session.runtime as FakeRuntime).lifecycleManager.timeSource
-        perceptionStateExtender =
-            session.stateExtenders.filterIsInstance<PerceptionStateExtender>().first()
-        perceptionManager = perceptionStateExtender.perceptionManager as FakePerceptionManager
-    }
-
     @Test
-    fun hitTest_successWithOneHitResult() = runTest {
-        val runtimePlane = FakeRuntimePlane()
-        perceptionManager.addTrackable(runtimePlane)
-        // Mock the behavior of session update.
-        val timeMark = timeSource.markNow()
-        val state = CoreState(timeMark)
-        perceptionStateExtender.extend(state)
-        check(state.perceptionState?.trackables?.size == 1)
-        val expectedTrackable = state.perceptionState?.trackables?.first()
-        val runtimeHitResult: RuntimeHitResult =
-            RuntimeHitResult(
-                distance = 1f,
-                hitPose = Pose(Vector3(1f, 2f, 3f), Quaternion(4f, 5f, 6f, 7f)),
-                trackable = runtimePlane,
-            )
-        perceptionManager.addHitResult(runtimeHitResult)
+    fun hitTest_successWithOneHitResult() = createTestSessionAndRunTest {
+        runTest {
+            timeSource = (session.runtime as FakeRuntime).lifecycleManager.timeSource
+            perceptionStateExtender =
+                session.stateExtenders.filterIsInstance<PerceptionStateExtender>().first()
+            perceptionManager = perceptionStateExtender.perceptionManager as FakePerceptionManager
+            val runtimePlane = FakeRuntimePlane()
+            perceptionManager.addTrackable(runtimePlane)
+            // Mock the behavior of session update.
+            val timeMark = timeSource.markNow()
+            val state = CoreState(timeMark)
+            perceptionStateExtender.extend(state)
+            check(state.perceptionState?.trackables?.size == 1)
+            val expectedTrackable = state.perceptionState?.trackables?.first()
+            val runtimeHitResult: RuntimeHitResult =
+                RuntimeHitResult(
+                    distance = 1f,
+                    hitPose = Pose(Vector3(1f, 2f, 3f), Quaternion(4f, 5f, 6f, 7f)),
+                    trackable = runtimePlane,
+                )
+            perceptionManager.addHitResult(runtimeHitResult)
 
-        val hitResults = hitTest(session, Ray(Vector3(0f, 0f, 0f), Vector3(0f, 0f, 1f)))
+            val hitResults = hitTest(session, Ray(Vector3(0f, 0f, 0f), Vector3(0f, 0f, 1f)))
 
-        assertThat(hitResults.size).isEqualTo(1)
-        assertThat(hitResults[0].distance).isEqualTo(runtimeHitResult.distance)
-        assertThat(hitResults[0].hitPose).isEqualTo(runtimeHitResult.hitPose)
-        assertThat(hitResults[0].trackable).isEqualTo(expectedTrackable)
+            assertThat(hitResults.size).isEqualTo(1)
+            assertThat(hitResults[0].distance).isEqualTo(runtimeHitResult.distance)
+            assertThat(hitResults[0].hitPose).isEqualTo(runtimeHitResult.hitPose)
+            assertThat(hitResults[0].trackable).isEqualTo(expectedTrackable)
+        }
     }
 
-    private fun createTestSession(): Session {
-        var session: Session? = null
+    private fun createTestSessionAndRunTest(testBody: () -> Unit) {
         ActivityScenario.launch(Activity::class.java).use {
             it.onActivity { activity ->
                 session =
                     (Session.create(activity, StandardTestDispatcher()) as SessionCreateSuccess)
                         .session
+
+                testBody()
             }
         }
-        return checkNotNull(session) { "Session must not be null." }
     }
 }
diff --git a/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/PlaneTest.kt b/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/PlaneTest.kt
index cf0a7bc..0a4c952 100644
--- a/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/PlaneTest.kt
+++ b/xr/arcore/arcore/src/test/kotlin/androidx/xr/arcore/PlaneTest.kt
@@ -53,6 +53,7 @@
     private lateinit var xrResourcesManager: XrResourcesManager
     private lateinit var testDispatcher: TestDispatcher
     private lateinit var testScope: TestScope
+    private lateinit var session: Session
 
     @get:Rule
     val grantPermissionRule = GrantPermissionRule.grant("android.permission.SCENE_UNDERSTANDING")
@@ -105,20 +106,21 @@
 
     @Test
     fun subscribe_collectReturnsPlane() =
-        runTest(testDispatcher) {
-            val session = createTestSession(testDispatcher)
-            val perceptionManager = session.runtime.perceptionManager as FakePerceptionManager
-            val runtimePlane = FakeRuntimePlane()
-            perceptionManager.addTrackable(runtimePlane)
-            awaitNewCoreState(session, testScope)
+        createTestSessionAndRunTest(testDispatcher) {
+            runTest(testDispatcher) {
+                val perceptionManager = session.runtime.perceptionManager as FakePerceptionManager
+                val runtimePlane = FakeRuntimePlane()
+                perceptionManager.addTrackable(runtimePlane)
+                awaitNewCoreState(session, testScope)
 
-            var underTest = emptyList<Plane>()
-            testScope.backgroundScope.launch(start = CoroutineStart.UNDISPATCHED) {
-                underTest = Plane.subscribe(session).first().toList()
+                var underTest = emptyList<Plane>()
+                testScope.backgroundScope.launch(start = CoroutineStart.UNDISPATCHED) {
+                    underTest = Plane.subscribe(session).first().toList()
+                }
+
+                assertThat(underTest.size).isEqualTo(1)
+                assertThat(underTest.first().runtimePlane).isEqualTo(runtimePlane)
             }
-
-            assertThat(underTest.size).isEqualTo(1)
-            assertThat(underTest.first().runtimePlane).isEqualTo(runtimePlane)
         }
 
     @Test
@@ -245,17 +247,18 @@
         assertThat(Plane.Type.Vertical.toString()).isEqualTo("Vertical")
     }
 
-    private fun createTestSession(
-        coroutineDispatcher: CoroutineDispatcher = StandardTestDispatcher()
-    ): Session {
-        var session: Session? = null
+    private fun createTestSessionAndRunTest(
+        coroutineDispatcher: CoroutineDispatcher = StandardTestDispatcher(),
+        testBody: () -> Unit,
+    ) {
         ActivityScenario.launch(Activity::class.java).use {
             it.onActivity { activity ->
                 session =
                     (Session.create(activity, coroutineDispatcher) as SessionCreateSuccess).session
+
+                testBody()
             }
         }
-        return checkNotNull(session) { "Session must not be null." }
     }
 
     /** Resumes and pauses the session just enough to emit a new CoreState. */
diff --git a/xr/compose/compose-testing/src/main/kotlin/androidx/xr/compose/testing/TestSetup.kt b/xr/compose/compose-testing/src/main/kotlin/androidx/xr/compose/testing/TestSetup.kt
index 6a7737a..41f87da 100644
--- a/xr/compose/compose-testing/src/main/kotlin/androidx/xr/compose/testing/TestSetup.kt
+++ b/xr/compose/compose-testing/src/main/kotlin/androidx/xr/compose/testing/TestSetup.kt
@@ -28,6 +28,7 @@
 import androidx.xr.compose.platform.LocalSession
 import androidx.xr.scenecore.JxrPlatformAdapter
 import androidx.xr.scenecore.Session
+import androidx.xr.scenecore.SpatialEnvironment
 import org.mockito.kotlin.any
 import org.mockito.kotlin.doAnswer
 import org.mockito.kotlin.doReturn
@@ -52,9 +53,9 @@
         if (isXrEnabled) {
             createFakeSession(activity, runtime).apply {
                 if (isFullSpace) {
-                    requestFullSpaceMode()
+                    spatialEnvironment.requestFullSpaceMode()
                 } else {
-                    requestHomeSpaceMode()
+                    spatialEnvironment.requestHomeSpaceMode()
                 }
             }
         } else {
diff --git a/xr/compose/compose/api/current.txt b/xr/compose/compose/api/current.txt
index c1c118f..631122e 100644
--- a/xr/compose/compose/api/current.txt
+++ b/xr/compose/compose/api/current.txt
@@ -6,9 +6,9 @@
     method public float getDepth();
     method public float getHeight();
     method public float getWidth();
-    property public float depth;
-    property public float height;
-    property public float width;
+    property public final float depth;
+    property public final float height;
+    property public final float width;
     field public static final androidx.xr.compose.unit.DpVolumeSize.Companion Companion;
   }
 
@@ -59,28 +59,28 @@
 
   public static final class Meter.Companion {
     method public inline float fromPixel(float px, androidx.compose.ui.unit.Density density);
-    method public float getCentimeters();
-    method public float getCentimeters();
-    method public float getCentimeters();
+    method public float getCentimeters(double);
+    method public float getCentimeters(float);
+    method public float getCentimeters(int);
     method public float getInfinity();
-    method public float getMeters();
-    method public float getMeters();
-    method public float getMeters();
-    method public float getMillimeters();
-    method public float getMillimeters();
-    method public float getMillimeters();
+    method public float getMeters(double);
+    method public float getMeters(float);
+    method public float getMeters(int);
+    method public float getMillimeters(double);
+    method public float getMillimeters(float);
+    method public float getMillimeters(int);
     method public float getNaN();
-    property public float Infinity;
-    property public float NaN;
-    property public float centimeters;
-    property public float centimeters;
-    property public float centimeters;
-    property public float meters;
-    property public float meters;
-    property public float meters;
-    property public float millimeters;
-    property public float millimeters;
-    property public float millimeters;
+    property public final float Infinity;
+    property public final float NaN;
+    property public final float centimeters;
+    property public final float centimeters;
+    property public final float centimeters;
+    property public final float meters;
+    property public final float meters;
+    property public final float meters;
+    property public final float millimeters;
+    property public final float millimeters;
+    property public final float millimeters;
   }
 
   public final class MeterKt {
diff --git a/xr/compose/compose/api/restricted_current.txt b/xr/compose/compose/api/restricted_current.txt
index cfbdcd2..d92a33f 100644
--- a/xr/compose/compose/api/restricted_current.txt
+++ b/xr/compose/compose/api/restricted_current.txt
@@ -53,10 +53,10 @@
     method public int getHome();
     method public int getNotApplicable();
     method public int getUnspecified();
-    property public int Full;
-    property public int Home;
-    property public int NotApplicable;
-    property public int Unspecified;
+    property public final int Full;
+    property public final int Home;
+    property public final int NotApplicable;
+    property public final int Unspecified;
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface SpatialCapabilities {
@@ -113,14 +113,14 @@
     method public float getAmount();
     method public int getType();
     property public final float amount;
-    property public int type;
+    property public final int type;
     field public static final androidx.xr.compose.spatial.EdgeOffset.Companion Companion;
   }
 
   public static final class EdgeOffset.Companion {
-    method @androidx.compose.runtime.Composable public androidx.xr.compose.spatial.EdgeOffset inner(float offset);
-    method @androidx.compose.runtime.Composable public androidx.xr.compose.spatial.EdgeOffset outer(float offset);
-    method @androidx.compose.runtime.Composable public androidx.xr.compose.spatial.EdgeOffset overlap(float offset);
+    method public androidx.xr.compose.spatial.EdgeOffset inner(float offset);
+    method public androidx.xr.compose.spatial.EdgeOffset outer(float offset);
+    method public androidx.xr.compose.spatial.EdgeOffset overlap(float offset);
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class OrbiterDefaults {
@@ -140,10 +140,10 @@
     method public int getEnd();
     method public int getStart();
     method public int getTop();
-    property public int Bottom;
-    property public int End;
-    property public int Start;
-    property public int Top;
+    property public final int Bottom;
+    property public final int End;
+    property public final int Start;
+    property public final int Top;
   }
 
   @kotlin.jvm.JvmInline public static final value class OrbiterEdge.Horizontal implements androidx.xr.compose.spatial.OrbiterEdge {
@@ -153,8 +153,8 @@
   public static final class OrbiterEdge.Horizontal.Companion {
     method public int getBottom();
     method public int getTop();
-    property public int Bottom;
-    property public int Top;
+    property public final int Bottom;
+    property public final int Top;
   }
 
   @kotlin.jvm.JvmInline public static final value class OrbiterEdge.Vertical implements androidx.xr.compose.spatial.OrbiterEdge {
@@ -164,8 +164,8 @@
   public static final class OrbiterEdge.Vertical.Companion {
     method public int getEnd();
     method public int getStart();
-    property public int End;
-    property public int Start;
+    property public final int End;
+    property public final int Start;
   }
 
   public final class OrbiterKt {
@@ -182,15 +182,15 @@
   public static final class OrbiterOffsetType.Companion {
     method public int getInnerEdge();
     method public int getOuterEdge();
-    property public int InnerEdge;
-    property public int OuterEdge;
+    property public final int InnerEdge;
+    property public final int OuterEdge;
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class OrbiterSettings {
     ctor public OrbiterSettings();
     ctor public OrbiterSettings(optional boolean shouldRenderInNonSpatial);
     method public androidx.xr.compose.spatial.OrbiterSettings copy(optional boolean shouldRenderInNonSpatial);
-    method public boolean shouldRenderInNonSpatial();
+    method public boolean getShouldRenderInNonSpatial();
     property public final boolean shouldRenderInNonSpatial;
   }
 
@@ -200,7 +200,7 @@
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class SpatialDialogProperties {
     ctor public SpatialDialogProperties();
-    ctor public SpatialDialogProperties(optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional boolean usePlatformDefaultWidth, optional androidx.compose.animation.core.FiniteAnimationSpec<java.lang.Float> restingLevelAnimationSpec, optional androidx.xr.compose.spatial.SpatialElevationLevel spatialElevationLevel);
+    ctor public SpatialDialogProperties(optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional boolean usePlatformDefaultWidth, optional androidx.compose.animation.core.FiniteAnimationSpec<java.lang.Float> restingLevelAnimationSpec, optional float spatialElevationLevel);
     method public androidx.xr.compose.spatial.SpatialDialogProperties copy(optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional boolean usePlatformDefaultWidth, optional androidx.compose.animation.core.FiniteAnimationSpec<java.lang.Float> restingLevelAnimationSpec, optional float spatialElevationLevel);
     method public boolean getDismissOnBackPress();
     method public boolean getDismissOnClickOutside();
@@ -210,7 +210,7 @@
     property public final boolean dismissOnBackPress;
     property public final boolean dismissOnClickOutside;
     property public final androidx.compose.animation.core.FiniteAnimationSpec<java.lang.Float> restingLevelAnimationSpec;
-    property public float spatialElevationLevel;
+    property public final float spatialElevationLevel;
     property public final boolean usePlatformDefaultWidth;
   }
 
@@ -231,12 +231,12 @@
     method public float getLevel3();
     method public float getLevel4();
     method public float getLevel5();
-    property public float Level0;
-    property public float Level1;
-    property public float Level2;
-    property public float Level3;
-    property public float Level4;
-    property public float Level5;
+    property public final float Level0;
+    property public final float Level1;
+    property public final float Level2;
+    property public final float Level3;
+    property public final float Level4;
+    property public final float Level5;
   }
 
   public final class SpatialPopupKt {
@@ -257,7 +257,7 @@
     property public final boolean dismissOnBackPress;
     property public final boolean dismissOnClickOutside;
     property public final boolean focusable;
-    property public float spatialElevationLevel;
+    property public final float spatialElevationLevel;
   }
 
   public final class SubspaceKt {
@@ -376,13 +376,6 @@
     method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.xr.compose.subspace.layout.SubspaceModifier onGloballyPositioned(androidx.xr.compose.subspace.layout.SubspaceModifier, kotlin.jvm.functions.Function1<? super androidx.xr.compose.subspace.layout.SubspaceLayoutCoordinates,kotlin.Unit> onGloballyPositioned);
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class OnGloballyPositionedNode extends androidx.xr.compose.subspace.layout.SubspaceModifier.Node {
-    ctor public OnGloballyPositionedNode(kotlin.jvm.functions.Function1<? super androidx.xr.compose.subspace.layout.SubspaceLayoutCoordinates,kotlin.Unit> callback);
-    method public kotlin.jvm.functions.Function1<androidx.xr.compose.subspace.layout.SubspaceLayoutCoordinates,kotlin.Unit> getCallback();
-    method public void setCallback(kotlin.jvm.functions.Function1<? super androidx.xr.compose.subspace.layout.SubspaceLayoutCoordinates,kotlin.Unit>);
-    property public final kotlin.jvm.functions.Function1<androidx.xr.compose.subspace.layout.SubspaceLayoutCoordinates,kotlin.Unit> callback;
-  }
-
   public final class PaddingKt {
     method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.xr.compose.subspace.layout.SubspaceModifier padding(androidx.xr.compose.subspace.layout.SubspaceModifier, float all);
     method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.xr.compose.subspace.layout.SubspaceModifier padding(androidx.xr.compose.subspace.layout.SubspaceModifier, optional float horizontal, optional float vertical, optional float depth);
@@ -427,14 +420,6 @@
     method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.xr.compose.subspace.layout.SubspaceModifier rotate(androidx.xr.compose.subspace.layout.SubspaceModifier, float pitch, float yaw, float roll);
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class RotationNode extends androidx.xr.compose.subspace.layout.SubspaceModifier.Node implements androidx.xr.compose.subspace.node.SubspaceLayoutModifierNode {
-    ctor public RotationNode(androidx.xr.runtime.math.Quaternion quaternion);
-    method public androidx.xr.runtime.math.Quaternion getQuaternion();
-    method public androidx.xr.compose.subspace.layout.MeasureResult measure(androidx.xr.compose.subspace.layout.MeasureScope, androidx.xr.compose.subspace.layout.Measurable measurable, androidx.xr.compose.unit.VolumeConstraints constraints);
-    method public void setQuaternion(androidx.xr.runtime.math.Quaternion);
-    property public final androidx.xr.runtime.math.Quaternion quaternion;
-  }
-
   public final class ScaleKt {
     method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static androidx.xr.compose.subspace.layout.SubspaceModifier scale(androidx.xr.compose.subspace.layout.SubspaceModifier, float scale);
   }
@@ -713,9 +698,9 @@
     method public float getDepth();
     method public float getHeight();
     method public float getWidth();
-    property public float depth;
-    property public float height;
-    property public float width;
+    property public final float depth;
+    property public final float height;
+    property public final float width;
     field public static final androidx.xr.compose.unit.DpVolumeSize.Companion Companion;
   }
 
@@ -767,29 +752,29 @@
 
   public static final class Meter.Companion {
     method public inline float fromPixel(float px, androidx.compose.ui.unit.Density density);
-    method public float getCentimeters();
-    method public float getCentimeters();
-    method public float getCentimeters();
+    method public float getCentimeters(double);
+    method public float getCentimeters(float);
+    method public float getCentimeters(int);
     method public float getInfinity();
-    method public float getMeters();
-    method public float getMeters();
-    method public float getMeters();
-    method public float getMillimeters();
-    method public float getMillimeters();
-    method public float getMillimeters();
+    method public float getMeters(double);
+    method public float getMeters(float);
+    method public float getMeters(int);
+    method public float getMillimeters(double);
+    method public float getMillimeters(float);
+    method public float getMillimeters(int);
     method public float getNaN();
     property @kotlin.PublishedApi internal final float DP_PER_METER;
-    property public float Infinity;
-    property public float NaN;
-    property public float centimeters;
-    property public float centimeters;
-    property public float centimeters;
-    property public float meters;
-    property public float meters;
-    property public float meters;
-    property public float millimeters;
-    property public float millimeters;
-    property public float millimeters;
+    property public final float Infinity;
+    property public final float NaN;
+    property public final float centimeters;
+    property public final float centimeters;
+    property public final float centimeters;
+    property public final float meters;
+    property public final float meters;
+    property public final float meters;
+    property public final float millimeters;
+    property public final float millimeters;
+    property public final float millimeters;
   }
 
   public final class MeterKt {
diff --git a/xr/compose/compose/build.gradle b/xr/compose/compose/build.gradle
index 5fc0532..570cd7a 100644
--- a/xr/compose/compose/build.gradle
+++ b/xr/compose/compose/build.gradle
@@ -79,4 +79,6 @@
     kotlinTarget = KotlinTarget.KOTLIN_1_9
     // TODO: b/326456246
     optOutJSpecify = true
+    // b/384785925
+    metalavaK2UastEnabled = false
 }
diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/platform/SpatialConfiguration.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/platform/SpatialConfiguration.kt
index 3e7f1d6..cd20120 100644
--- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/platform/SpatialConfiguration.kt
+++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/platform/SpatialConfiguration.kt
@@ -165,10 +165,10 @@
         get() = boundsState.toDpVolumeSize()
 
     override fun requestHomeSpaceMode() {
-        session.requestHomeSpaceMode()
+        session.spatialEnvironment.requestHomeSpaceMode()
     }
 
     override fun requestFullSpaceMode() {
-        session.requestFullSpaceMode()
+        session.spatialEnvironment.requestFullSpaceMode()
     }
 }
diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/spatial/ElevatedPanel.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/spatial/ElevatedPanel.kt
index ea0180f..43fc6dd 100644
--- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/spatial/ElevatedPanel.kt
+++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/spatial/ElevatedPanel.kt
@@ -28,7 +28,6 @@
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.compositionLocalOf
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
@@ -58,14 +57,8 @@
 }
 
 /**
- * Defines the "root view" of this ElevatedPanel such that nested ElevatedPanels can all reference
- * the root view that they are attached to.
- */
-internal val LocalRootView = compositionLocalOf<View?> { null }
-
-/**
- * This is the base panel underlying the implementations of ElevatedSurface, ElevatedPopup, and
- * ElevatedDialog. It allows creating a panel at a specific size and offset.
+ * This is the base panel underlying the implementations of SpatialElevation, SpatialPopup, and
+ * SpatialDialog. It allows creating a panel at a specific size and offset.
  */
 @Composable
 internal fun ElevatedPanel(
@@ -81,7 +74,7 @@
         },
     content: @Composable () -> Unit,
 ) {
-    val parentView = LocalRootView.current ?: LocalView.current
+    val parentView = LocalView.current
     val zDepth by
         updateTransition(targetState = spatialElevationLevel, label = "restingLevelTransition")
             .animateFloat(transitionSpec = transitionSpec, label = "zDepth") { state ->
@@ -107,8 +100,8 @@
 }
 
 /**
- * This is the base panel underlying the implementations of ElevatedSurface, ElevatedPopup, and
- * ElevatedDialog. It allows creating a panel at a specific size and [Pose].
+ * This is the base panel underlying the implementations of SpatialElevation, SpatialPopup, and
+ * SpatialDialog. It allows creating a panel at a specific size and [Pose].
  */
 @Composable
 internal fun ElevatedPanel(
@@ -117,7 +110,6 @@
     pose: Pose? = null,
     content: @Composable () -> Unit,
 ) {
-    val parentView = LocalRootView.current ?: LocalView.current
     val session = checkNotNull(LocalSession.current) { "session must be initialized" }
     val parentPanelEntity = LocalPanelEntity.current ?: session.mainPanelEntity
     val density = LocalDensity.current
@@ -125,10 +117,7 @@
     val meterSize = contentSize.toMeterSize(density)
 
     val view = rememberComposeView {
-        CompositionLocalProvider(
-            LocalRootView provides parentView,
-            LocalPanelEntity provides panelEntity,
-        ) {
+        CompositionLocalProvider(LocalPanelEntity provides panelEntity) {
             Box(Modifier.alpha(if (pose == null) 0.0f else 1.0f)) { content() }
         }
     }
@@ -139,7 +128,7 @@
                 view = view,
                 surfaceDimensionsPx = meterSize.toCorePixelDimensions(density),
                 dimensions = meterSize.toCoreMeterDimensions(),
-                name = "ElevatedSurface:${view.id}",
+                name = "ElevatedPanel:${view.id}",
             )
         onDispose {
             panelEntity?.dispose()
diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/spatial/Orbiter.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/spatial/Orbiter.kt
index 3c24d7a..be0bf9f 100644
--- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/spatial/Orbiter.kt
+++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/spatial/Orbiter.kt
@@ -38,6 +38,7 @@
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalView
 import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.LayoutDirection
@@ -141,8 +142,8 @@
  * @param position The edge of the orbiter. Use [OrbiterEdge.Top] or [OrbiterEdge.Bottom].
  * @param offset The offset of the orbiter based on the inner or outer edge of the orbiter. Use
  *   [EdgeOffset.outer] to create an [EdgeOffset] aligned to the outer edge of the orbiter or
- *   [innerEdge] or [EdgeOffset.overlap] to create an [EdgeOffset] aligned to the inner edge of the
- *   orbiter.
+ *   [EdgeOffset.inner] or [EdgeOffset.overlap] to create an [EdgeOffset] aligned to the inner edge
+ *   of the orbiter.
  * @param alignment The alignment of the orbiter. Use [Alignment.CenterHorizontally] or
  *   [Alignment.Start] or [Alignment.End].
  * @param settings The settings for the orbiter.
@@ -224,8 +225,8 @@
  * @param position The edge of the orbiter. Use [OrbiterEdge.Start] or [OrbiterEdge.End].
  * @param offset The offset of the orbiter based on the inner or outer edge of the orbiter. Use
  *   [EdgeOffset.outer] to create an [EdgeOffset] aligned to the outer edge of the orbiter or
- *   [innerEdge] or [EdgeOffset.overlap] to create an [EdgeOffset] aligned to the inner edge of the
- *   orbiter.
+ *   [EdgeOffset.inner] or [EdgeOffset.overlap] to create an [EdgeOffset] aligned to the inner edge
+ *   of the orbiter.
  * @param alignment The alignment of the orbiter. Use [Alignment.CenterVertically] or
  *   [Alignment.Top] or [Alignment.Bottom].
  * @param settings The settings for the orbiter.
@@ -278,6 +279,7 @@
     var panelSize by remember { mutableStateOf(panelEntity.getPixelDimensions()) }
     var contentSize: IntSize? by remember { mutableStateOf(null) }
     val dialogManager = LocalDialogManager.current
+    val density = LocalDensity.current
 
     DisposableEffect(view) {
         val listener =
@@ -291,7 +293,7 @@
     ElevatedPanel(
         spatialElevationLevel = SpatialElevationLevel.Level1,
         contentSize = contentSize ?: IntSize.Zero,
-        contentOffset = contentSize?.let { data.calculateOffset(panelSize, it) },
+        contentOffset = contentSize?.let { data.calculateOffset(panelSize, it, density) },
         shape = data.shape,
     ) {
         Box(
@@ -366,13 +368,13 @@
 /**
  * Represents the offset of an orbiter from the main panel.
  *
- * @property amount the magnitude of the offset in pixels.
+ * @property amount the magnitude of the offset in Dp.
  * @property type the type of offset ([OrbiterOffsetType.OuterEdge] or
  *   [OrbiterOffsetType.InnerEdge]).
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 public class EdgeOffset
-internal constructor(public val amount: Float, public val type: OrbiterOffsetType) {
+internal constructor(public val amount: Dp, public val type: OrbiterOffsetType) {
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (other !is EdgeOffset) return false
@@ -393,7 +395,7 @@
         return "EdgeOffset(amount=$amount, type=$type)"
     }
 
-    public fun copy(amount: Float = this.amount, type: OrbiterOffsetType = this.type): EdgeOffset =
+    public fun copy(amount: Dp = this.amount, type: OrbiterOffsetType = this.type): EdgeOffset =
         EdgeOffset(amount = amount, type = type)
 
     public companion object {
@@ -407,9 +409,7 @@
          * @param offset the offset value in [Dp].
          * @return an [EdgeOffset] with the specified offset and type [OrbiterOffsetType.OuterEdge].
          */
-        @Composable
-        public fun outer(offset: Dp): EdgeOffset =
-            with(LocalDensity.current) { EdgeOffset(offset.toPx(), OrbiterOffsetType.OuterEdge) }
+        public fun outer(offset: Dp): EdgeOffset = EdgeOffset(offset, OrbiterOffsetType.OuterEdge)
 
         /**
          * Creates an [EdgeOffset] representing an offset from the inner edge of an orbiter.
@@ -421,9 +421,7 @@
          * @param offset the offset value in [Dp].
          * @return an [EdgeOffset] with the specified offset and type [OrbiterOffsetType.InnerEdge].
          */
-        @Composable
-        public fun inner(offset: Dp): EdgeOffset =
-            with(LocalDensity.current) { EdgeOffset(offset.toPx(), OrbiterOffsetType.InnerEdge) }
+        public fun inner(offset: Dp): EdgeOffset = EdgeOffset(offset, OrbiterOffsetType.InnerEdge)
 
         /**
          * Creates an [EdgeOffset] representing an overlap of an orbiter into the main panel
@@ -436,9 +434,8 @@
          * @return an [EdgeOffset] with the [offset]'s pixel value and
          *   [OrbiterOffsetType.InnerEdge].
          */
-        @Composable
         public fun overlap(offset: Dp): EdgeOffset =
-            with(LocalDensity.current) { EdgeOffset(-offset.toPx(), OrbiterOffsetType.InnerEdge) }
+            EdgeOffset(-offset, OrbiterOffsetType.InnerEdge)
     }
 }
 
@@ -454,20 +451,25 @@
 
 /**
  * Calculates the offset that should be applied to the orbiter given its settings, the panel size,
- * and the size of the orbiter content.
+ * and the size of the orbiter content, using the specified density to convert Dp to pixels.
  */
-private fun OrbiterData.calculateOffset(viewSize: PixelDimensions, contentSize: IntSize): Offset {
+private fun OrbiterData.calculateOffset(
+    viewSize: PixelDimensions,
+    contentSize: IntSize,
+    density: Density,
+): Offset {
+
     if (position is OrbiterEdge.Vertical) {
         val y = verticalAlignment.align(contentSize.height, viewSize.height)
 
-        val xOffset =
+        val xOffset: Float =
             when (offset.type) {
-                OrbiterOffsetType.OuterEdge -> -offset.amount
-                OrbiterOffsetType.InnerEdge -> -contentSize.width - offset.amount
+                OrbiterOffsetType.OuterEdge -> -offset.amount.toPx(density)
+                OrbiterOffsetType.InnerEdge -> -contentSize.width - offset.amount.toPx(density)
                 else -> error("Unexpected OrbiterOffsetType: ${offset.type}")
             }
 
-        val x =
+        val x: Float =
             when (position) {
                 OrbiterEdge.Start -> xOffset
                 OrbiterEdge.End -> viewSize.width - contentSize.width - xOffset
@@ -479,14 +481,14 @@
         // adjust
         val x = horizontalAlignment.align(contentSize.width, viewSize.width, LayoutDirection.Ltr)
 
-        val yOffset =
+        val yOffset: Float =
             when (offset.type) {
-                OrbiterOffsetType.OuterEdge -> -offset.amount
-                OrbiterOffsetType.InnerEdge -> -contentSize.height - offset.amount
+                OrbiterOffsetType.OuterEdge -> -offset.amount.toPx(density)
+                OrbiterOffsetType.InnerEdge -> -contentSize.height - offset.amount.toPx(density)
                 else -> error("Unexpected OrbiterOffsetType: ${offset.type}")
             }
 
-        val y =
+        val y: Float =
             when (position) {
                 OrbiterEdge.Top -> yOffset
                 OrbiterEdge.Bottom -> viewSize.height - contentSize.height - yOffset
@@ -495,3 +497,5 @@
         return Offset(x.toFloat(), y)
     }
 }
+
+private fun Dp.toPx(density: Density): Float = with(density) { toPx() }
diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/spatial/SpatialDialog.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/spatial/SpatialDialog.kt
index d62b0e0..a7256d0 100644
--- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/spatial/SpatialDialog.kt
+++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/spatial/SpatialDialog.kt
@@ -152,7 +152,7 @@
     properties: SpatialDialogProperties = SpatialDialogProperties(),
     content: @Composable () -> Unit,
 ) {
-    val view = LocalRootView.current ?: LocalView.current
+    val view = LocalView.current
     val scope = rememberCoroutineScope()
     val session = checkNotNull(LocalSession.current) { "session must be initialized" }
     // Start elevation at Level0 to prevent effects where the dialog flashes behind its parent.
diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/RememberComposeView.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/RememberComposeView.kt
index 81dd734..9658041 100644
--- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/RememberComposeView.kt
+++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/RememberComposeView.kt
@@ -56,7 +56,7 @@
                 setParentCompositionContext(compositionContext)
                 // Set unique id for AbstractComposeView. This allows state restoration for the
                 // state
-                // defined inside the ElevatedSurface via rememberSaveable()
+                // defined inside the SpatialElevation via rememberSaveable()
                 setTag(
                     androidx.compose.ui.R.id.compose_view_saveable_id_tag,
                     "ComposeView:$localId"
diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/SpatialPanel.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/SpatialPanel.kt
index 298715c..5fba56c 100644
--- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/SpatialPanel.kt
+++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/SpatialPanel.kt
@@ -23,6 +23,10 @@
 import android.view.ViewGroup
 import android.widget.FrameLayout
 import androidx.annotation.RestrictTo
+import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.detectTapGestures
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.shape.CornerSize
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
@@ -32,7 +36,10 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
 import androidx.compose.ui.UiComposable
+import androidx.compose.ui.graphics.Color as UiColor
+import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.unit.dp
 import androidx.xr.compose.platform.LocalDialogManager
@@ -44,7 +51,9 @@
 import androidx.xr.compose.subspace.layout.SubspaceLayout
 import androidx.xr.compose.subspace.layout.SubspaceModifier
 import androidx.xr.compose.unit.IntVolumeSize
+import androidx.xr.compose.unit.Meter.Companion.millimeters
 import androidx.xr.runtime.math.Pose
+import androidx.xr.runtime.math.Vector3
 import androidx.xr.scenecore.Dimensions
 import androidx.xr.scenecore.PanelEntity
 
@@ -168,15 +177,64 @@
     name: String = "ActivityPanel-${intent.action}",
     shape: SpatialShape = SpatialPanelDefaults.shape,
 ) {
-    LayoutPanelEntity(
-        rememberCorePanelEntity {
-            val rect = Rect(0, 0, DEFAULT_SIZE_PX, DEFAULT_SIZE_PX)
-            createActivityPanelEntity(rect, name).also { it.launchActivity(intent) }
-        },
-        name,
-        shape,
-        modifier,
-    )
+
+    val session = checkNotNull(LocalSession.current) { "session must be initialized" }
+    val dialogManager = LocalDialogManager.current
+
+    val minimumPanelDimension = Dimensions(10f, 10f, 10f)
+    val rect = Rect(0, 0, DEFAULT_SIZE_PX, DEFAULT_SIZE_PX)
+    val activityPanelEntity = rememberCorePanelEntity {
+        session.createActivityPanelEntity(rect, name).also { it.launchActivity(intent) }
+    }
+
+    SpatialBox {
+        LayoutPanelEntity(activityPanelEntity, name, shape, modifier)
+
+        if (dialogManager.isSpatialDialogActive.value) {
+            val scrimView = rememberComposeView {
+                Box(
+                    modifier =
+                        Modifier.fillMaxSize()
+                            .background(UiColor.Black.copy(alpha = 0.5f))
+                            .pointerInput(Unit) {
+                                detectTapGestures {
+                                    dialogManager.isSpatialDialogActive.value = false
+                                }
+                            }
+                ) {}
+            }
+
+            val scrimPanelEntity = rememberCorePanelEntity {
+                createPanelEntity(
+                        view = scrimView,
+                        surfaceDimensionsPx = minimumPanelDimension,
+                        dimensions = minimumPanelDimension,
+                        name = "scrim view",
+                        pose = Pose.Identity,
+                    )
+                    .also {
+                        it.setParent(activityPanelEntity.entity)
+                        it.setPose(Pose(translation = Vector3(0f, 0f, 3.millimeters.toM())))
+                    }
+            }
+
+            val density = LocalDensity.current
+            LaunchedEffect(activityPanelEntity.size) {
+                val size = activityPanelEntity.size
+                scrimPanelEntity.size = size
+                if (shape is SpatialRoundedCornerShape) {
+                    scrimPanelEntity.setCornerRadius(
+                        shape.computeCornerRadius(
+                            size.width.toFloat(),
+                            size.height.toFloat(),
+                            density
+                        ),
+                        density,
+                    )
+                }
+            }
+        }
+    }
 }
 
 /**
diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/CoreEntity.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/CoreEntity.kt
index 34e33d00..e6a61b6 100644
--- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/CoreEntity.kt
+++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/CoreEntity.kt
@@ -18,6 +18,7 @@
 
 import android.content.res.Resources
 import android.util.Log
+import androidx.compose.runtime.mutableStateOf
 import androidx.compose.ui.unit.Density
 import androidx.xr.compose.subspace.node.SubspaceLayoutModifierNode
 import androidx.xr.compose.subspace.node.SubspaceLayoutNode
@@ -99,15 +100,18 @@
                 ?.findInstance<SubspaceLayoutModifierNode>()
                 ?.coordinator ?: layout?.parentCoordinatesInParentEntity
 
-    override var size: IntVolumeSize = IntVolumeSize.Zero
+    private val _size = mutableStateOf(IntVolumeSize.Zero)
+
+    override var size: IntVolumeSize
+        get() = _size.value
         set(value) {
             val proposedSize = resizable?.userSize ?: value
-            if (field == proposedSize) {
+            if (_size.value == proposedSize) {
                 return
             }
 
             setEntitySize(proposedSize)
-            field = proposedSize
+            _size.value = proposedSize
 
             movable?.setComponentSize(proposedSize)
             resizable?.setComponentSize(proposedSize)
@@ -229,7 +233,7 @@
             // Here we create the component and pass in false to systemMovable since Compose is
             // going to
             // handle the move events.
-            session.createMovableComponent(systemMovable = false)
+            MovableComponent.create(session, systemMovable = false)
         }
 
         /**
@@ -403,7 +407,7 @@
         private var isAttached: Boolean = false
 
         private val component: ResizableComponent by lazy {
-            session.createResizableComponent().apply {
+            ResizableComponent.create(session).apply {
                 addResizeListener(
                     LocalExecutor,
                     object : ResizeListener {
diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/OnGloballyPositionedModifier.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/OnGloballyPositionedModifier.kt
index 1756b4d..13deb234 100644
--- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/OnGloballyPositionedModifier.kt
+++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/OnGloballyPositionedModifier.kt
@@ -60,6 +60,5 @@
 }
 
 /** Node associated with [onGloballyPositioned]. */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
-public class OnGloballyPositionedNode(public var callback: (SubspaceLayoutCoordinates) -> Unit) :
+internal class OnGloballyPositionedNode(public var callback: (SubspaceLayoutCoordinates) -> Unit) :
     SubspaceModifier.Node()
diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/Rotate.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/Rotate.kt
index d5ce88a..c6925d7 100644
--- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/Rotate.kt
+++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/Rotate.kt
@@ -89,8 +89,7 @@
     }
 }
 
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
-public class RotationNode(public var quaternion: Quaternion) :
+internal class RotationNode(public var quaternion: Quaternion) :
     SubspaceLayoutModifierNode, SubspaceModifier.Node() {
     override fun MeasureScope.measure(
         measurable: Measurable,
diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/unit/Meter.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/unit/Meter.kt
index 008ea95..377c402 100644
--- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/unit/Meter.kt
+++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/unit/Meter.kt
@@ -194,7 +194,7 @@
          */
         @PublishedApi
         internal val DP_PER_METER: Float =
-            tryGetXrExtensions()?.config?.defaultPixelsPerMeter(1.0f) ?: DP_PER_METER_FALLBACK
+            getXrExtensions()?.config?.defaultPixelsPerMeter(1.0f) ?: DP_PER_METER_FALLBACK
 
         /** Represents an infinite distance in meters. */
         public val Infinity: Meter = Meter(Float.POSITIVE_INFINITY)
@@ -207,14 +207,7 @@
          *
          * @return an instance of [XrExtensions] if available, or [null] otherwise.
          */
-        private fun tryGetXrExtensions(): XrExtensions? =
-            try {
-                XrExtensionsProvider.getXrExtensions()
-            } catch (e: Exception) {
-                null
-            } catch (e: Error) {
-                null
-            }
+        private fun getXrExtensions(): XrExtensions? = XrExtensionsProvider.getXrExtensions()
 
         /**
          * Creates a [Meter] value from a given number of pixels.
diff --git a/xr/compose/compose/src/test/kotlin/androidx/xr/compose/platform/SpatialCapabilitiesTest.kt b/xr/compose/compose/src/test/kotlin/androidx/xr/compose/platform/SpatialCapabilitiesTest.kt
index 62fd4bb..718d684 100644
--- a/xr/compose/compose/src/test/kotlin/androidx/xr/compose/platform/SpatialCapabilitiesTest.kt
+++ b/xr/compose/compose/src/test/kotlin/androidx/xr/compose/platform/SpatialCapabilitiesTest.kt
@@ -151,7 +151,7 @@
         composeTestRule.setContent {
             TestSetup(isFullSpace = false) {
                 Text("${LocalSpatialCapabilities.current.isSpatialUiEnabled}")
-                requestFullSpaceMode()
+                this.spatialEnvironment.requestFullSpaceMode()
             }
         }
 
@@ -163,7 +163,7 @@
         composeTestRule.setContent {
             TestSetup(isFullSpace = true) {
                 Text("${LocalSpatialCapabilities.current.isSpatialUiEnabled}")
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
             }
         }
 
@@ -174,7 +174,7 @@
     fun isContent3dEnabled_homeSpaceMode_returnsFalse() {
         composeTestRule.setContent {
             TestSetup {
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
                 Text("${LocalSpatialCapabilities.current.isContent3dEnabled}")
             }
         }
@@ -187,7 +187,7 @@
         composeTestRule.setContent {
             TestSetup(isFullSpace = false) {
                 Text("${LocalSpatialCapabilities.current.isContent3dEnabled}")
-                requestFullSpaceMode()
+                this.spatialEnvironment.requestFullSpaceMode()
             }
         }
 
@@ -199,7 +199,7 @@
         composeTestRule.setContent {
             TestSetup(isFullSpace = true) {
                 Text("${LocalSpatialCapabilities.current.isContent3dEnabled}")
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
             }
         }
 
@@ -210,7 +210,7 @@
     fun isAppEnvironmentEnabled_homeSpaceMode_returnsFalse() {
         composeTestRule.setContent {
             TestSetup {
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
                 Text(text = "${LocalSpatialCapabilities.current.isAppEnvironmentEnabled}")
             }
         }
@@ -223,7 +223,7 @@
         composeTestRule.setContent {
             TestSetup(isFullSpace = false) {
                 Text(text = "${LocalSpatialCapabilities.current.isAppEnvironmentEnabled}")
-                requestFullSpaceMode()
+                this.spatialEnvironment.requestFullSpaceMode()
             }
         }
 
@@ -235,7 +235,7 @@
         composeTestRule.setContent {
             TestSetup(isFullSpace = true) {
                 Text(text = "${LocalSpatialCapabilities.current.isAppEnvironmentEnabled}")
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
             }
         }
 
@@ -246,7 +246,7 @@
     fun isPassthroughControlEnabled_homeSpaceMode_returnsFalse() {
         composeTestRule.setContent {
             TestSetup {
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
                 Text(text = "${LocalSpatialCapabilities.current.isPassthroughControlEnabled}")
             }
         }
@@ -259,7 +259,7 @@
         composeTestRule.setContent {
             TestSetup(isFullSpace = false) {
                 Text(text = "${LocalSpatialCapabilities.current.isPassthroughControlEnabled}")
-                requestFullSpaceMode()
+                this.spatialEnvironment.requestFullSpaceMode()
             }
         }
 
@@ -271,7 +271,7 @@
         composeTestRule.setContent {
             TestSetup(isFullSpace = true) {
                 Text(text = "${LocalSpatialCapabilities.current.isPassthroughControlEnabled}")
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
             }
         }
 
@@ -282,7 +282,7 @@
     fun isSpatialAudioEnabled_homeSpaceMode_returnsFalse() {
         composeTestRule.setContent {
             TestSetup {
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
                 Text(text = "${LocalSpatialCapabilities.current.isSpatialAudioEnabled}")
             }
         }
@@ -295,7 +295,7 @@
         composeTestRule.setContent {
             TestSetup(isFullSpace = false) {
                 Text(text = "${LocalSpatialCapabilities.current.isSpatialAudioEnabled}")
-                requestFullSpaceMode()
+                this.spatialEnvironment.requestFullSpaceMode()
             }
         }
 
@@ -307,7 +307,7 @@
         composeTestRule.setContent {
             TestSetup(isFullSpace = true) {
                 Text(text = "${LocalSpatialCapabilities.current.isSpatialAudioEnabled}")
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
             }
         }
 
diff --git a/xr/compose/compose/src/test/kotlin/androidx/xr/compose/spatial/OrbiterTest.kt b/xr/compose/compose/src/test/kotlin/androidx/xr/compose/spatial/OrbiterTest.kt
index 61eb28b..74f79e3 100644
--- a/xr/compose/compose/src/test/kotlin/androidx/xr/compose/spatial/OrbiterTest.kt
+++ b/xr/compose/compose/src/test/kotlin/androidx/xr/compose/spatial/OrbiterTest.kt
@@ -69,7 +69,7 @@
     fun orbiter_homeSpaceMode_contentIsInline() {
         composeTestRule.setContent {
             TestSetup {
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
                 Parent { Orbiter(OrbiterEdge.Top) { Text("Main Content") } }
             }
         }
@@ -81,7 +81,7 @@
     fun orbiter_nonSpatial_doesNotRenderContent() {
         composeTestRule.setContent {
             TestSetup {
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
                 Parent {
                     Orbiter(
                         OrbiterEdge.Top,
@@ -116,9 +116,9 @@
     fun orbiter_afterSwitchToFullSpaceMode_isSpatial() {
         composeTestRule.setContent {
             TestSetup {
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
                 Parent { Orbiter(position = OrbiterEdge.Bottom) { Text("Bottom") } }
-                requestFullSpaceMode()
+                this.spatialEnvironment.requestFullSpaceMode()
             }
         }
 
@@ -169,7 +169,7 @@
     fun orbiter_orbiterRendered() {
         composeTestRule.setContent {
             TestSetup {
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
                 Box {
                     Text("Main Content")
                     Orbiter(OrbiterEdge.Start) { Text("Orbiter Content") }
@@ -187,7 +187,7 @@
 
         composeTestRule.setContent {
             TestSetup {
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
                 Box(modifier = Modifier.size(100.dp)) {
                     Text("Main Content")
                     if (showOrbiter) {
@@ -210,9 +210,9 @@
             TestSetup {
                 LaunchedEffect(isFullSpaceMode) {
                     if (isFullSpaceMode) {
-                        requestFullSpaceMode()
+                        [email protected]()
                     } else {
-                        requestHomeSpaceMode()
+                        [email protected]()
                     }
                 }
 
diff --git a/xr/compose/compose/src/test/kotlin/androidx/xr/compose/spatial/SpatialElevationTest.kt b/xr/compose/compose/src/test/kotlin/androidx/xr/compose/spatial/SpatialElevationTest.kt
index 97b741d..60a8bc3 100644
--- a/xr/compose/compose/src/test/kotlin/androidx/xr/compose/spatial/SpatialElevationTest.kt
+++ b/xr/compose/compose/src/test/kotlin/androidx/xr/compose/spatial/SpatialElevationTest.kt
@@ -88,7 +88,7 @@
     fun spatialElevation_homeSpaceMode_doesNotElevate() {
         composeTestRule.setContent {
             TestSetup {
-                requestHomeSpaceMode()
+                this.spatialEnvironment.requestHomeSpaceMode()
                 Parent { SpatialElevation { Text("Main Content") } }
             }
         }
@@ -100,7 +100,7 @@
     fun spatialElevation_fullSpaceMode_doesElevate() {
         composeTestRule.setContent {
             TestSetup {
-                requestFullSpaceMode()
+                this.spatialEnvironment.requestFullSpaceMode()
                 Parent { SpatialElevation { Text("Main Content") } }
             }
         }
diff --git a/xr/compose/material3/integration-tests/testapp/src/main/java/androidx/xr/compose/material3/integration/testapp/MainActivity.kt b/xr/compose/material3/integration-tests/testapp/src/main/java/androidx/xr/compose/material3/integration/testapp/MainActivity.kt
index 44b8d83..1643303 100644
--- a/xr/compose/material3/integration-tests/testapp/src/main/java/androidx/xr/compose/material3/integration/testapp/MainActivity.kt
+++ b/xr/compose/material3/integration-tests/testapp/src/main/java/androidx/xr/compose/material3/integration/testapp/MainActivity.kt
@@ -19,7 +19,7 @@
 @file:OptIn(
     ExperimentalMaterial3AdaptiveApi::class,
     ExperimentalMaterial3Api::class,
-    ExperimentalMaterial3XrApi::class
+    ExperimentalMaterial3XrApi::class,
 )
 
 package androidx.xr.compose.material3.integration.testapp
@@ -33,6 +33,7 @@
 import androidx.compose.material3.Icon
 import androidx.compose.material3.Text
 import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
+import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
 import androidx.compose.material3.adaptive.layout.AnimatedPane
 import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold
 import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
@@ -40,14 +41,21 @@
 import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator
 import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
 import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold
+import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffoldDefaults
 import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteType
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
+import androidx.xr.compose.material3.DefaultNavigationBarOrbiterProperties
+import androidx.xr.compose.material3.DefaultNavigationRailOrbiterProperties
 import androidx.xr.compose.material3.EnableXrComponentOverrides
 import androidx.xr.compose.material3.ExperimentalMaterial3XrApi
+import androidx.xr.compose.material3.LocalNavigationBarOrbiterProperties
+import androidx.xr.compose.material3.LocalNavigationRailOrbiterProperties
+import androidx.xr.compose.spatial.EdgeOffset
 
 class MainActivity : ComponentActivity() {
     override fun onCreate(savedInstanceState: Bundle?) {
@@ -57,31 +65,46 @@
     }
 }
 
-private val navSuiteType = mutableStateOf(NavigationSuiteType.NavigationRail)
-
 @Composable
 private fun Content() {
+    var navSuiteType: NavigationSuiteType? by remember { mutableStateOf(null) }
+    var edgeOffset: EdgeOffset? by remember { mutableStateOf(null) }
+
     var navSuiteSelectedItem by remember { mutableStateOf(NavSuiteItem.HOME) }
 
-    NavigationSuiteScaffold(
-        navigationSuiteItems = {
-            NavSuiteItem.values().forEach { item ->
-                item(
-                    selected = navSuiteSelectedItem == item,
-                    onClick = { navSuiteSelectedItem = item },
-                    icon = { Icon(item.icon, contentDescription = item.label) },
-                    label = { Text(item.label) },
-                )
-            }
-        },
-        layoutType = navSuiteType.value
+    CompositionLocalProvider(
+        LocalNavigationBarOrbiterProperties provides
+            DefaultNavigationBarOrbiterProperties.copy(offset = edgeOffset),
+        LocalNavigationRailOrbiterProperties provides
+            DefaultNavigationRailOrbiterProperties.copy(offset = edgeOffset),
     ) {
-        when (navSuiteSelectedItem) {
-            NavSuiteItem.HOME -> {
-                Home()
-            }
-            NavSuiteItem.SETTINGS -> {
-                XrSettingsPane(navSuiteType)
+        NavigationSuiteScaffold(
+            navigationSuiteItems = {
+                NavSuiteItem.values().forEach { item ->
+                    item(
+                        selected = navSuiteSelectedItem == item,
+                        onClick = { navSuiteSelectedItem = item },
+                        icon = { Icon(item.icon, contentDescription = item.label) },
+                        label = { Text(item.label) },
+                    )
+                }
+            },
+            layoutType =
+                navSuiteType
+                    ?: NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(
+                        currentWindowAdaptiveInfo()
+                    ),
+        ) {
+            when (navSuiteSelectedItem) {
+                NavSuiteItem.HOME -> {
+                    Home()
+                }
+                NavSuiteItem.SETTINGS -> {
+                    XrSettingsPane(
+                        onNavSuiteTypeChanged = { navSuiteType = it },
+                        onOrbiterEdgeOffsetChanged = { edgeOffset = it },
+                    )
+                }
             }
         }
     }
diff --git a/xr/compose/material3/integration-tests/testapp/src/main/java/androidx/xr/compose/material3/integration/testapp/XrSettingsPane.kt b/xr/compose/material3/integration-tests/testapp/src/main/java/androidx/xr/compose/material3/integration/testapp/XrSettingsPane.kt
index e1faf48..da67718 100644
--- a/xr/compose/material3/integration-tests/testapp/src/main/java/androidx/xr/compose/material3/integration/testapp/XrSettingsPane.kt
+++ b/xr/compose/material3/integration-tests/testapp/src/main/java/androidx/xr/compose/material3/integration/testapp/XrSettingsPane.kt
@@ -21,28 +21,48 @@
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.text.input.TextFieldLineLimits
+import androidx.compose.foundation.text.input.rememberTextFieldState
+import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd
 import androidx.compose.material3.Button
+import androidx.compose.material3.DropdownMenuItem
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.ExposedDropdownMenuAnchorType
+import androidx.compose.material3.ExposedDropdownMenuBox
+import androidx.compose.material3.ExposedDropdownMenuDefaults
 import androidx.compose.material3.ListItem
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Scaffold
 import androidx.compose.material3.Text
+import androidx.compose.material3.TextField
 import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteType
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.unit.dp
+import androidx.xr.compose.material3.ExperimentalMaterial3XrApi
 import androidx.xr.compose.platform.LocalSession
 import androidx.xr.compose.platform.LocalSpatialCapabilities
+import androidx.xr.compose.spatial.EdgeOffset
 
+@OptIn(ExperimentalMaterial3XrApi::class)
 @Composable
-internal fun XrSettingsPane(navSuiteType: MutableState<NavigationSuiteType>) {
+internal fun XrSettingsPane(
+    onNavSuiteTypeChanged: (NavigationSuiteType?) -> Unit,
+    onOrbiterEdgeOffsetChanged: (EdgeOffset?) -> Unit,
+) {
     Scaffold { innerPadding ->
         Column(
             modifier = Modifier.padding(innerPadding),
-            verticalArrangement = Arrangement.spacedBy(16.dp)
+            verticalArrangement = Arrangement.spacedBy(16.dp),
         ) {
             ListItem(headlineContent = { XrModeButton() })
-            ListItem(headlineContent = { NavigationSuiteTypeButton(navSuiteType) })
+            ListItem(headlineContent = { NavigationSuiteTypeButton(onNavSuiteTypeChanged) })
+            ListItem(
+                headlineContent = { XrNavigationOrbiterEdgeOffset(onOrbiterEdgeOffsetChanged) }
+            )
         }
     }
 }
@@ -58,11 +78,11 @@
         enabled = isDeviceXr,
         onClick = {
             if (isFullSpaceMode) {
-                session?.requestHomeSpaceMode()
+                session?.spatialEnvironment?.requestHomeSpaceMode()
             } else {
-                session?.requestFullSpaceMode()
+                session?.spatialEnvironment?.requestFullSpaceMode()
             }
-        }
+        },
     ) {
         Text(
             text = if (isDeviceXr) "Toggle FullSpace/HomeSpace Mode" else "XR unsupported",
@@ -72,17 +92,97 @@
 }
 
 @Composable
-private fun NavigationSuiteTypeButton(navSuiteType: MutableState<NavigationSuiteType>) {
-    Button(
-        modifier = Modifier.fillMaxWidth().height(56.dp).padding(horizontal = 16.dp),
-        onClick = {
-            if (navSuiteType.value == NavigationSuiteType.NavigationRail) {
-                navSuiteType.value = NavigationSuiteType.NavigationBar
-            } else {
-                navSuiteType.value = NavigationSuiteType.NavigationRail
+private fun NavigationSuiteTypeButton(onNavSuiteTypeChanged: (NavigationSuiteType?) -> Unit) {
+    var navSuiteType: MutableState<NavigationSuiteType?> = remember { mutableStateOf(null) }
+    var expanded = remember { mutableStateOf(false) }
+    SimpleDropdown(
+        dropdownLabel = "NavigationSuiteType",
+        items = listOf(null, NavigationSuiteType.NavigationRail, NavigationSuiteType.NavigationBar),
+        selectedItem = navSuiteType,
+        expanded = expanded,
+        itemLabel = { it?.toString() ?: "Default" },
+        onSelectedChange = onNavSuiteTypeChanged,
+    )
+}
+
+private enum class OrbiterEdgeOffsetChoices {
+    /** The default Orbiter EdgeOffset, as defined in the implementation. */
+    Default,
+    /** An inner Orbiter EdgeOffset. */
+    Inner,
+    /** An overlapping inner Orbiter EdgeOffset. */
+    Overlap,
+}
+
+@OptIn(ExperimentalMaterial3XrApi::class)
+@Composable
+private fun XrNavigationOrbiterEdgeOffset(onOrbiterEdgeOffsetChanged: (EdgeOffset?) -> Unit) {
+    val selectedItem = remember { mutableStateOf(OrbiterEdgeOffsetChoices.Default) }
+    val expanded = remember { mutableStateOf(false) }
+
+    val selectedEdgeOffset =
+        when (selectedItem.value) {
+            OrbiterEdgeOffsetChoices.Default -> EdgeOffset.outer(24.dp)
+            OrbiterEdgeOffsetChoices.Inner -> EdgeOffset.inner(24.dp)
+            OrbiterEdgeOffsetChoices.Overlap -> EdgeOffset.overlap(24.dp)
+        }
+
+    SimpleDropdown(
+        dropdownLabel = "NavigationRail Orbiter EdgeOffset",
+        items = OrbiterEdgeOffsetChoices.values().asList(),
+        selectedItem = selectedItem,
+        expanded = expanded,
+        itemLabel = { it.name },
+        onSelectedChange = { onOrbiterEdgeOffsetChanged(selectedEdgeOffset) },
+    )
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+private fun <T> SimpleDropdown(
+    dropdownLabel: String,
+    items: List<T>,
+    selectedItem: MutableState<T>,
+    expanded: MutableState<Boolean>,
+    itemLabel: (T) -> String,
+    onSelectedChange: (T) -> Unit,
+) {
+    var state = rememberTextFieldState(itemLabel(selectedItem.value))
+    Column {
+        Text(text = dropdownLabel, style = MaterialTheme.typography.labelMedium)
+        ExposedDropdownMenuBox(
+            expanded = expanded.value,
+            onExpandedChange = { expanded.value = it },
+        ) {
+            TextField(
+                modifier = Modifier.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable),
+                state = state,
+                readOnly = true,
+                lineLimits = TextFieldLineLimits.SingleLine,
+                label = { itemLabel(selectedItem.value) },
+                trailingIcon = {
+                    ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded.value)
+                },
+                colors = ExposedDropdownMenuDefaults.textFieldColors(),
+            )
+
+            ExposedDropdownMenu(
+                expanded = expanded.value,
+                onDismissRequest = { expanded.value = false },
+            ) {
+                for (item in items) {
+                    DropdownMenuItem(
+                        text = { Text(itemLabel(item)) },
+                        onClick = {
+                            selectedItem.value = item
+                            state.setTextAndPlaceCursorAtEnd(itemLabel(item))
+                            onSelectedChange(item)
+                            expanded.value = false
+                        },
+                        contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding,
+                    )
+                }
             }
         }
-    ) {
-        Text(text = "Toggle NavRail/NavBar", style = MaterialTheme.typography.bodyLarge)
     }
 }
diff --git a/xr/compose/material3/material3/api/current.txt b/xr/compose/material3/material3/api/current.txt
index 5b8e8d1..98fb6c4 100644
--- a/xr/compose/material3/material3/api/current.txt
+++ b/xr/compose/material3/material3/api/current.txt
@@ -8,12 +8,50 @@
   @SuppressCompatibility @kotlin.RequiresOptIn(message="This material XR API is experimental and is likely to change or to be removed in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMaterial3XrApi {
   }
 
+  @SuppressCompatibility @androidx.compose.runtime.Immutable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public final class HorizontalOrbiterProperties {
+    ctor public HorizontalOrbiterProperties(androidx.xr.compose.spatial.EdgeOffset offset, int position, androidx.compose.ui.Alignment.Horizontal alignment, androidx.xr.compose.spatial.OrbiterSettings settings, androidx.xr.compose.subspace.layout.SpatialShape shape);
+    method public androidx.xr.compose.material3.HorizontalOrbiterProperties copy(optional androidx.xr.compose.spatial.EdgeOffset? offset, optional androidx.xr.compose.spatial.OrbiterEdge.Horizontal? position, optional androidx.compose.ui.Alignment.Horizontal? alignment, optional androidx.xr.compose.spatial.OrbiterSettings? settings, optional androidx.xr.compose.subspace.layout.SpatialShape? shape);
+    method public androidx.compose.ui.Alignment.Horizontal getAlignment();
+    method public androidx.xr.compose.spatial.EdgeOffset getOffset();
+    method public int getPosition();
+    method public androidx.xr.compose.spatial.OrbiterSettings getSettings();
+    method public androidx.xr.compose.subspace.layout.SpatialShape getShape();
+    property public final androidx.compose.ui.Alignment.Horizontal alignment;
+    property public final androidx.xr.compose.spatial.EdgeOffset offset;
+    property public int position;
+    property public final androidx.xr.compose.spatial.OrbiterSettings settings;
+    property public final androidx.xr.compose.subspace.layout.SpatialShape shape;
+  }
+
   public final class NavigationBarKt {
     method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static void NavigationBar(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional float tonalElevation, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static androidx.xr.compose.material3.HorizontalOrbiterProperties getDefaultNavigationBarOrbiterProperties();
+    method @SuppressCompatibility @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.xr.compose.material3.HorizontalOrbiterProperties?> getLocalNavigationBarOrbiterProperties();
+    property @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static final androidx.xr.compose.material3.HorizontalOrbiterProperties DefaultNavigationBarOrbiterProperties;
+    property @SuppressCompatibility @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.xr.compose.material3.HorizontalOrbiterProperties?> LocalNavigationBarOrbiterProperties;
   }
 
   public final class NavigationRailKt {
     method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static void NavigationRail(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>? header, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static androidx.xr.compose.material3.VerticalOrbiterProperties getDefaultNavigationRailOrbiterProperties();
+    method @SuppressCompatibility @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.xr.compose.material3.VerticalOrbiterProperties?> getLocalNavigationRailOrbiterProperties();
+    property @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static final androidx.xr.compose.material3.VerticalOrbiterProperties DefaultNavigationRailOrbiterProperties;
+    property @SuppressCompatibility @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.xr.compose.material3.VerticalOrbiterProperties?> LocalNavigationRailOrbiterProperties;
+  }
+
+  @SuppressCompatibility @androidx.compose.runtime.Immutable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public final class VerticalOrbiterProperties {
+    ctor public VerticalOrbiterProperties(androidx.xr.compose.spatial.EdgeOffset offset, int position, androidx.compose.ui.Alignment.Vertical alignment, androidx.xr.compose.spatial.OrbiterSettings settings, androidx.xr.compose.subspace.layout.SpatialShape shape);
+    method public androidx.xr.compose.material3.VerticalOrbiterProperties copy(optional androidx.xr.compose.spatial.EdgeOffset? offset, optional androidx.xr.compose.spatial.OrbiterEdge.Vertical? position, optional androidx.compose.ui.Alignment.Vertical? alignment, optional androidx.xr.compose.spatial.OrbiterSettings? settings, optional androidx.xr.compose.subspace.layout.SpatialShape? shape);
+    method public androidx.compose.ui.Alignment.Vertical getAlignment();
+    method public androidx.xr.compose.spatial.EdgeOffset getOffset();
+    method public int getPosition();
+    method public androidx.xr.compose.spatial.OrbiterSettings getSettings();
+    method public androidx.xr.compose.subspace.layout.SpatialShape getShape();
+    property public final androidx.compose.ui.Alignment.Vertical alignment;
+    property public final androidx.xr.compose.spatial.EdgeOffset offset;
+    property public int position;
+    property public final androidx.xr.compose.spatial.OrbiterSettings settings;
+    property public final androidx.xr.compose.subspace.layout.SpatialShape shape;
   }
 
   @SuppressCompatibility @androidx.xr.compose.material3.ExperimentalMaterial3XrApi @kotlin.jvm.JvmInline public final value class XrComponentOverride {
diff --git a/xr/compose/material3/material3/api/restricted_current.txt b/xr/compose/material3/material3/api/restricted_current.txt
index 5b8e8d1..98fb6c4 100644
--- a/xr/compose/material3/material3/api/restricted_current.txt
+++ b/xr/compose/material3/material3/api/restricted_current.txt
@@ -8,12 +8,50 @@
   @SuppressCompatibility @kotlin.RequiresOptIn(message="This material XR API is experimental and is likely to change or to be removed in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMaterial3XrApi {
   }
 
+  @SuppressCompatibility @androidx.compose.runtime.Immutable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public final class HorizontalOrbiterProperties {
+    ctor public HorizontalOrbiterProperties(androidx.xr.compose.spatial.EdgeOffset offset, int position, androidx.compose.ui.Alignment.Horizontal alignment, androidx.xr.compose.spatial.OrbiterSettings settings, androidx.xr.compose.subspace.layout.SpatialShape shape);
+    method public androidx.xr.compose.material3.HorizontalOrbiterProperties copy(optional androidx.xr.compose.spatial.EdgeOffset? offset, optional androidx.xr.compose.spatial.OrbiterEdge.Horizontal? position, optional androidx.compose.ui.Alignment.Horizontal? alignment, optional androidx.xr.compose.spatial.OrbiterSettings? settings, optional androidx.xr.compose.subspace.layout.SpatialShape? shape);
+    method public androidx.compose.ui.Alignment.Horizontal getAlignment();
+    method public androidx.xr.compose.spatial.EdgeOffset getOffset();
+    method public int getPosition();
+    method public androidx.xr.compose.spatial.OrbiterSettings getSettings();
+    method public androidx.xr.compose.subspace.layout.SpatialShape getShape();
+    property public final androidx.compose.ui.Alignment.Horizontal alignment;
+    property public final androidx.xr.compose.spatial.EdgeOffset offset;
+    property public int position;
+    property public final androidx.xr.compose.spatial.OrbiterSettings settings;
+    property public final androidx.xr.compose.subspace.layout.SpatialShape shape;
+  }
+
   public final class NavigationBarKt {
     method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static void NavigationBar(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional float tonalElevation, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static androidx.xr.compose.material3.HorizontalOrbiterProperties getDefaultNavigationBarOrbiterProperties();
+    method @SuppressCompatibility @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.xr.compose.material3.HorizontalOrbiterProperties?> getLocalNavigationBarOrbiterProperties();
+    property @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static final androidx.xr.compose.material3.HorizontalOrbiterProperties DefaultNavigationBarOrbiterProperties;
+    property @SuppressCompatibility @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.xr.compose.material3.HorizontalOrbiterProperties?> LocalNavigationBarOrbiterProperties;
   }
 
   public final class NavigationRailKt {
     method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static void NavigationRail(optional androidx.compose.ui.Modifier modifier, optional long containerColor, optional long contentColor, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit>? header, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.ColumnScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static androidx.xr.compose.material3.VerticalOrbiterProperties getDefaultNavigationRailOrbiterProperties();
+    method @SuppressCompatibility @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.xr.compose.material3.VerticalOrbiterProperties?> getLocalNavigationRailOrbiterProperties();
+    property @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static final androidx.xr.compose.material3.VerticalOrbiterProperties DefaultNavigationRailOrbiterProperties;
+    property @SuppressCompatibility @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public static final androidx.compose.runtime.ProvidableCompositionLocal<androidx.xr.compose.material3.VerticalOrbiterProperties?> LocalNavigationRailOrbiterProperties;
+  }
+
+  @SuppressCompatibility @androidx.compose.runtime.Immutable @androidx.xr.compose.material3.ExperimentalMaterial3XrApi public final class VerticalOrbiterProperties {
+    ctor public VerticalOrbiterProperties(androidx.xr.compose.spatial.EdgeOffset offset, int position, androidx.compose.ui.Alignment.Vertical alignment, androidx.xr.compose.spatial.OrbiterSettings settings, androidx.xr.compose.subspace.layout.SpatialShape shape);
+    method public androidx.xr.compose.material3.VerticalOrbiterProperties copy(optional androidx.xr.compose.spatial.EdgeOffset? offset, optional androidx.xr.compose.spatial.OrbiterEdge.Vertical? position, optional androidx.compose.ui.Alignment.Vertical? alignment, optional androidx.xr.compose.spatial.OrbiterSettings? settings, optional androidx.xr.compose.subspace.layout.SpatialShape? shape);
+    method public androidx.compose.ui.Alignment.Vertical getAlignment();
+    method public androidx.xr.compose.spatial.EdgeOffset getOffset();
+    method public int getPosition();
+    method public androidx.xr.compose.spatial.OrbiterSettings getSettings();
+    method public androidx.xr.compose.subspace.layout.SpatialShape getShape();
+    property public final androidx.compose.ui.Alignment.Vertical alignment;
+    property public final androidx.xr.compose.spatial.EdgeOffset offset;
+    property public int position;
+    property public final androidx.xr.compose.spatial.OrbiterSettings settings;
+    property public final androidx.xr.compose.subspace.layout.SpatialShape shape;
   }
 
   @SuppressCompatibility @androidx.xr.compose.material3.ExperimentalMaterial3XrApi @kotlin.jvm.JvmInline public final value class XrComponentOverride {
diff --git a/xr/compose/material3/material3/src/main/java/androidx/xr/compose/material3/NavigationBar.kt b/xr/compose/material3/material3/src/main/java/androidx/xr/compose/material3/NavigationBar.kt
index 4018da4..899df3e 100644
--- a/xr/compose/material3/material3/src/main/java/androidx/xr/compose/material3/NavigationBar.kt
+++ b/xr/compose/material3/material3/src/main/java/androidx/xr/compose/material3/NavigationBar.kt
@@ -35,13 +35,17 @@
 import androidx.compose.material3.Surface
 import androidx.compose.material3.contentColorFor
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ProvidableCompositionLocal
+import androidx.compose.runtime.compositionLocalOf
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
+import androidx.xr.compose.material3.XrNavigationBarComponentOverride.NavigationBar
 import androidx.xr.compose.spatial.EdgeOffset
 import androidx.xr.compose.spatial.Orbiter
+import androidx.xr.compose.spatial.OrbiterDefaults
 import androidx.xr.compose.spatial.OrbiterEdge
 
 /**
@@ -81,7 +85,9 @@
     tonalElevation: Dp = NavigationBarDefaults.Elevation,
     content: @Composable RowScope.() -> Unit
 ) {
-    Orbiter(position = OrbiterEdge.Bottom, offset = XrNavigationBarTokens.OrbiterEdgeOffset) {
+    val orbiterProperties =
+        LocalNavigationBarOrbiterProperties.current ?: DefaultNavigationBarOrbiterProperties
+    HorizontalOrbiter(orbiterProperties) {
         Surface(
             shape = CircleShape,
             color = containerColor,
@@ -130,3 +136,37 @@
         )
     }
 }
+
+/**
+ * The default [HorizontalOrbiterProperties] used by [NavigationBar] if none is specified in
+ * [LocalNavigationBarOrbiterProperties].
+ */
+@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+@get:ExperimentalMaterial3XrApi
+@ExperimentalMaterial3XrApi
+public val DefaultNavigationBarOrbiterProperties: HorizontalOrbiterProperties
+    @Composable
+    get() =
+        HorizontalOrbiterProperties(
+            position = OrbiterEdge.Horizontal.Bottom,
+            offset = XrNavigationBarTokens.OrbiterEdgeOffset,
+            alignment = Alignment.CenterHorizontally,
+            settings = OrbiterDefaults.orbiterSettings,
+            shape = OrbiterDefaults.shape,
+        )
+
+/**
+ * The [HorizontalOrbiterProperties] used by [NavigationBar].
+ *
+ * If `null`, [DefaultNavigationBarOrbiterProperties] will be used.
+ *
+ * TODO(b/387339197): Make this non-null and default to DefaultNavigationBarXrProperties
+ */
+@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+@get:ExperimentalMaterial3XrApi
+@ExperimentalMaterial3XrApi
+public val LocalNavigationBarOrbiterProperties:
+    ProvidableCompositionLocal<HorizontalOrbiterProperties?> =
+    compositionLocalOf {
+        null
+    }
diff --git a/xr/compose/material3/material3/src/main/java/androidx/xr/compose/material3/NavigationRail.kt b/xr/compose/material3/material3/src/main/java/androidx/xr/compose/material3/NavigationRail.kt
index 65cba21..799398b 100644
--- a/xr/compose/material3/material3/src/main/java/androidx/xr/compose/material3/NavigationRail.kt
+++ b/xr/compose/material3/material3/src/main/java/androidx/xr/compose/material3/NavigationRail.kt
@@ -33,13 +33,17 @@
 import androidx.compose.material3.Surface
 import androidx.compose.material3.contentColorFor
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ProvidableCompositionLocal
+import androidx.compose.runtime.compositionLocalOf
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
+import androidx.xr.compose.material3.XrNavigationRailComponentOverride.NavigationRail
 import androidx.xr.compose.spatial.EdgeOffset
 import androidx.xr.compose.spatial.Orbiter
+import androidx.xr.compose.spatial.OrbiterDefaults
 import androidx.xr.compose.spatial.OrbiterEdge
 
 /**
@@ -81,11 +85,9 @@
     header: @Composable (ColumnScope.() -> Unit)? = null,
     content: @Composable ColumnScope.() -> Unit,
 ) {
-    Orbiter(
-        position = OrbiterEdge.Start,
-        alignment = Alignment.CenterVertically,
-        offset = XrNavigationRailTokens.OrbiterEdgeOffset,
-    ) {
+    val orbiterProperties =
+        LocalNavigationRailOrbiterProperties.current ?: DefaultNavigationRailOrbiterProperties
+    VerticalOrbiter(orbiterProperties) {
         Surface(
             shape = CircleShape,
             color = containerColor,
@@ -104,14 +106,10 @@
             )
         }
     }
-    // Header goes inside a separate Orbiter without an outline shape, as this is generally
-    // a FAB.
+    // Header goes inside a separate top-aligned Orbiter without an outline shape, as this is
+    // generally a FAB.
     if (header != null) {
-        Orbiter(
-            position = OrbiterEdge.Start,
-            alignment = Alignment.Top,
-            offset = XrNavigationRailTokens.OrbiterEdgeOffset,
-        ) {
+        VerticalOrbiter(orbiterProperties.copy(alignment = Alignment.Top)) {
             Column(
                 horizontalAlignment = Alignment.CenterHorizontally,
                 verticalArrangement = Arrangement.spacedBy(XrNavigationRailTokens.VerticalPadding),
@@ -152,3 +150,35 @@
         )
     }
 }
+
+/**
+ * The default [VerticalOrbiterProperties] used by [NavigationRail] if none is specified in
+ * [LocalNavigationRailOrbiterProperties].
+ */
+@ExperimentalMaterial3XrApi
+public val DefaultNavigationRailOrbiterProperties: VerticalOrbiterProperties
+    @Composable
+    get() =
+        VerticalOrbiterProperties(
+            position = OrbiterEdge.Vertical.Start,
+            offset = XrNavigationRailTokens.OrbiterEdgeOffset,
+            alignment = Alignment.CenterVertically,
+            settings = OrbiterDefaults.orbiterSettings,
+            shape = OrbiterDefaults.shape,
+        )
+
+/**
+ * The [VerticalOrbiterProperties] used by [NavigationRail].
+ *
+ * If `null`, [DefaultNavigationRailOrbiterProperties] will be used.
+ *
+ * TODO(b/387339197): Make this non-null and default to DefaultNavigationRailXrProperties
+ */
+@Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+@get:ExperimentalMaterial3XrApi
+@ExperimentalMaterial3XrApi
+public val LocalNavigationRailOrbiterProperties:
+    ProvidableCompositionLocal<VerticalOrbiterProperties?> =
+    compositionLocalOf {
+        null
+    }
diff --git a/xr/compose/material3/material3/src/main/java/androidx/xr/compose/material3/OrbiterProperties.kt b/xr/compose/material3/material3/src/main/java/androidx/xr/compose/material3/OrbiterProperties.kt
new file mode 100644
index 0000000..80c6b76
--- /dev/null
+++ b/xr/compose/material3/material3/src/main/java/androidx/xr/compose/material3/OrbiterProperties.kt
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2025 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.xr.compose.material3
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+import androidx.compose.ui.Alignment
+import androidx.xr.compose.spatial.EdgeOffset
+import androidx.xr.compose.spatial.Orbiter
+import androidx.xr.compose.spatial.OrbiterEdge
+import androidx.xr.compose.spatial.OrbiterSettings
+import androidx.xr.compose.subspace.layout.SpatialShape
+
+/**
+ * XR-specific properties for components that use horizontally-aligned [Orbiter]s.
+ *
+ * These properties should be provided via a `CompositionLocal` for the given component.
+ *
+ * The component should also define a publicly-visible default instance of
+ * [HorizontalOrbiterProperties] and use it if the `CompositionLocal` is not set.
+ */
+@ExperimentalMaterial3XrApi
+@Immutable
+public class HorizontalOrbiterProperties(
+    public val offset: EdgeOffset,
+    public val position: OrbiterEdge.Horizontal,
+    public val alignment: Alignment.Horizontal,
+    public val settings: OrbiterSettings,
+    public val shape: SpatialShape,
+) {
+    /**
+     * Returns a new [HorizontalOrbiterProperties] with one or more properties changed.
+     *
+     * If `null` is provided for any value, the existing value will be used.
+     */
+    public fun copy(
+        offset: EdgeOffset? = null,
+        position: OrbiterEdge.Horizontal? = null,
+        alignment: Alignment.Horizontal? = null,
+        settings: OrbiterSettings? = null,
+        shape: SpatialShape? = null,
+    ): HorizontalOrbiterProperties =
+        HorizontalOrbiterProperties(
+            offset = offset ?: this.offset,
+            position = position ?: this.position,
+            alignment = alignment ?: this.alignment,
+            settings = settings ?: this.settings,
+            shape = shape ?: this.shape,
+        )
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is HorizontalOrbiterProperties) return false
+
+        if (offset != other.offset) return false
+        if (position != other.position) return false
+        if (alignment != other.alignment) return false
+        if (settings != other.settings) return false
+        if (shape != other.shape) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = offset.hashCode()
+        result = 31 * result + position.hashCode()
+        result = 31 * result + alignment.hashCode()
+        result = 31 * result + settings.hashCode()
+        result = 31 * result + shape.hashCode()
+        return result
+    }
+
+    override fun toString(): String {
+        return "HorizontalOrbiterProperties(" +
+            "offset=$offset, " +
+            "position=$position, " +
+            "alignment=$alignment, " +
+            "settings=$settings, " +
+            "shape=$shape" +
+            ")"
+    }
+}
+
+/**
+ * XR-specific properties for components that use vertically-aligned [Orbiter]s.
+ *
+ * These properties should be provided via a `CompositionLocal` for the given component.
+ *
+ * The component should also define a publicly-visible default instance of
+ * [VerticalOrbiterProperties] and use it if the `CompositionLocal` is not set.
+ */
+@ExperimentalMaterial3XrApi
+@Immutable
+public class VerticalOrbiterProperties(
+    public val offset: EdgeOffset,
+    public val position: OrbiterEdge.Vertical,
+    public val alignment: Alignment.Vertical,
+    public val settings: OrbiterSettings,
+    public val shape: SpatialShape,
+) {
+    /**
+     * Returns a new [VerticalOrbiterProperties] with one or more properties changed.
+     *
+     * If `null` is provided for any value, the existing value will be used.
+     */
+    public fun copy(
+        offset: EdgeOffset? = null,
+        position: OrbiterEdge.Vertical? = null,
+        alignment: Alignment.Vertical? = null,
+        settings: OrbiterSettings? = null,
+        shape: SpatialShape? = null,
+    ): VerticalOrbiterProperties =
+        VerticalOrbiterProperties(
+            offset = offset ?: this.offset,
+            position = position ?: this.position,
+            alignment = alignment ?: this.alignment,
+            settings = settings ?: this.settings,
+            shape = shape ?: this.shape,
+        )
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is VerticalOrbiterProperties) return false
+
+        if (offset != other.offset) return false
+        if (position != other.position) return false
+        if (alignment != other.alignment) return false
+        if (settings != other.settings) return false
+        if (shape != other.shape) return false
+
+        return true
+    }
+
+    override fun hashCode(): Int {
+        var result = offset.hashCode()
+        result = 31 * result + position.hashCode()
+        result = 31 * result + alignment.hashCode()
+        result = 31 * result + settings.hashCode()
+        result = 31 * result + shape.hashCode()
+        return result
+    }
+
+    override fun toString(): String {
+        return "VerticalOrbiterProperties(" +
+            "offset=$offset, " +
+            "position=$position, " +
+            "alignment=$alignment, " +
+            "settings=$settings, " +
+            "shape=$shape" +
+            ")"
+    }
+}
+
+@OptIn(ExperimentalMaterial3XrApi::class)
+@Composable
+internal fun VerticalOrbiter(
+    properties: VerticalOrbiterProperties,
+    content: @Composable () -> Unit
+) {
+    Orbiter(
+        position = properties.position,
+        offset = properties.offset,
+        alignment = properties.alignment,
+        settings = properties.settings,
+        shape = properties.shape,
+        content = content,
+    )
+}
+
+@OptIn(ExperimentalMaterial3XrApi::class)
+@Composable
+internal fun HorizontalOrbiter(
+    properties: HorizontalOrbiterProperties,
+    content: @Composable () -> Unit
+) {
+    Orbiter(
+        position = properties.position,
+        offset = properties.offset,
+        alignment = properties.alignment,
+        settings = properties.settings,
+        shape = properties.shape,
+        content = content,
+    )
+}
diff --git a/xr/scenecore/scenecore-testing/api/restricted_current.txt b/xr/scenecore/scenecore-testing/api/restricted_current.txt
index 9af083e..b983b022 100644
--- a/xr/scenecore/scenecore-testing/api/restricted_current.txt
+++ b/xr/scenecore/scenecore-testing/api/restricted_current.txt
@@ -262,6 +262,7 @@
     method public void setProposedOrientation(androidx.xr.extensions.node.Quatf);
     method public void setProposedPosition(androidx.xr.extensions.node.Vec3);
     method public void setProposedScale(androidx.xr.extensions.node.Vec3);
+    method public void setProposedSize(androidx.xr.extensions.node.Vec3);
     method public void setState(int);
     method public void setType(int);
   }
diff --git a/xr/scenecore/scenecore-testing/src/main/java/androidx/xr/scenecore/testing/FakeImpressApi.java b/xr/scenecore/scenecore-testing/src/main/java/androidx/xr/scenecore/testing/FakeImpressApi.java
index adf600a6..a793545 100644
--- a/xr/scenecore/scenecore-testing/src/main/java/androidx/xr/scenecore/testing/FakeImpressApi.java
+++ b/xr/scenecore/scenecore-testing/src/main/java/androidx/xr/scenecore/testing/FakeImpressApi.java
@@ -49,18 +49,18 @@
     }
 
     // Map of model tokens to the list of impress nodes that are instances of that model.
-    private final Map<Long, List<Integer>> gltfModels = new HashMap<>();
+    private final Map<Long, List<Integer>> mGltfModels = new HashMap<>();
     // Map of impress nodes to their parent impress nodes.
-    private final Map<Integer, Integer> impressNodes = new HashMap<>();
+    private final Map<Integer, Integer> mImpressNodes = new HashMap<>();
 
     // Map of impress nodes and animations that are currently playing (non looping)
-    final Map<Integer, AnimationInProgress> impressAnimatedNodes = new HashMap<>();
+    final Map<Integer, AnimationInProgress> mImpressAnimatedNodes = new HashMap<>();
 
     // Map of impress nodes and animations that are currently playing (looping)
-    final Map<Integer, AnimationInProgress> impressLoopAnimatedNodes = new HashMap<>();
+    final Map<Integer, AnimationInProgress> mImpressLoopAnimatedNodes = new HashMap<>();
 
-    private int nextModelId = 1;
-    private int nextNodeId = 1;
+    private int mNextModelId = 1;
+    private int mNextNodeId = 1;
 
     @Override
     public void setup(@NonNull View view) {}
@@ -75,8 +75,8 @@
     @NonNull
     @SuppressWarnings({"RestrictTo", "AsyncSuffixFuture"})
     public ListenableFuture<Long> loadGltfModel(@NonNull String name) {
-        long modelToken = nextModelId++;
-        gltfModels.put(modelToken, new ArrayList<>());
+        long modelToken = mNextModelId++;
+        mGltfModels.put(modelToken, new ArrayList<>());
         // TODO(b/352827267): Enforce minSDK API strategy - go/androidx-api-guidelines#compat-newapi
         ResolvableFuture<Long> ret = ResolvableFuture.create();
         ret.set(modelToken);
@@ -86,10 +86,10 @@
 
     @Override
     public void releaseGltfModel(long modelToken) {
-        if (!gltfModels.containsKey(modelToken)) {
+        if (!mGltfModels.containsKey(modelToken)) {
             throw new IllegalArgumentException("Model token not found");
         }
-        gltfModels.remove(modelToken);
+        mGltfModels.remove(modelToken);
     }
 
     @Override
@@ -99,12 +99,12 @@
 
     @Override
     public int instanceGltfModel(long modelToken, boolean enableCollider) {
-        if (!gltfModels.containsKey(modelToken)) {
+        if (!mGltfModels.containsKey(modelToken)) {
             throw new IllegalArgumentException("Model token not found");
         }
-        int entityId = nextNodeId++;
-        gltfModels.get(modelToken).add(entityId);
-        impressNodes.put(entityId, null);
+        int entityId = mNextNodeId++;
+        mGltfModels.get(modelToken).add(entityId);
+        mImpressNodes.put(entityId, null);
         return entityId;
     }
 
@@ -119,7 +119,7 @@
     public ListenableFuture<Void> animateGltfModel(
             int impressNode, @Nullable String animationName, boolean loop) {
         ResolvableFuture<Void> future = ResolvableFuture.create();
-        if (impressNodes.get(impressNode) == null) {
+        if (mImpressNodes.get(impressNode) == null) {
             future.setException(new IllegalArgumentException("Impress node not found"));
             return future;
         }
@@ -128,81 +128,85 @@
         animationInProgress.name = animationName;
         animationInProgress.fireOnDone = future;
         if (loop) {
-            impressLoopAnimatedNodes.put(impressNode, animationInProgress);
+            mImpressLoopAnimatedNodes.put(impressNode, animationInProgress);
         } else {
-            impressAnimatedNodes.put(impressNode, animationInProgress);
+            mImpressAnimatedNodes.put(impressNode, animationInProgress);
         }
         return future;
     }
 
     @Override
     public void stopGltfModelAnimation(int impressNode) {
-        if (impressNodes.get(impressNode) == null) {
+        if (mImpressNodes.get(impressNode) == null) {
             throw new IllegalArgumentException("Impress node not found");
-        } else if (!impressAnimatedNodes.containsKey(impressNode)
-                && !impressLoopAnimatedNodes.containsKey(impressNode)) {
+        } else if (!mImpressAnimatedNodes.containsKey(impressNode)
+                && !mImpressLoopAnimatedNodes.containsKey(impressNode)) {
             throw new IllegalArgumentException("Impress node is not animating");
-        } else if (impressAnimatedNodes.containsKey(impressNode)) {
-            impressAnimatedNodes.remove(impressNode);
-        } else if (impressLoopAnimatedNodes.containsKey(impressNode)) {
-            impressLoopAnimatedNodes.remove(impressNode);
+        } else if (mImpressAnimatedNodes.containsKey(impressNode)) {
+            mImpressAnimatedNodes.remove(impressNode);
+        } else if (mImpressLoopAnimatedNodes.containsKey(impressNode)) {
+            mImpressLoopAnimatedNodes.remove(impressNode);
         }
     }
 
     @Override
     public int createImpressNode() {
-        int entityId = nextNodeId++;
-        impressNodes.put(entityId, null);
+        int entityId = mNextNodeId++;
+        mImpressNodes.put(entityId, null);
         return entityId;
     }
 
     @Override
     public void destroyImpressNode(int impressNode) {
-        if (!impressNodes.containsKey(impressNode)) {
+        if (!mImpressNodes.containsKey(impressNode)) {
             throw new IllegalArgumentException("Impress node not found");
         }
-        for (Map.Entry<Long, List<Integer>> pair : gltfModels.entrySet()) {
+        for (Map.Entry<Long, List<Integer>> pair : mGltfModels.entrySet()) {
             if (pair.getValue().contains(impressNode)) {
-                pair.getValue().remove(impressNode);
+                pair.getValue().remove(Integer.valueOf(impressNode));
             }
         }
-        for (Map.Entry<Integer, Integer> pair : impressNodes.entrySet()) {
+        for (Map.Entry<Integer, Integer> pair : mImpressNodes.entrySet()) {
             if (pair.getValue() != null && pair.getValue().equals((Integer) impressNode)) {
                 pair.setValue(null);
             }
         }
-        impressNodes.remove(impressNode);
+        mImpressNodes.remove(impressNode);
     }
 
     @Override
     public void setImpressNodeParent(int impressNodeChild, int impressNodeParent) {
-        if (!impressNodes.containsKey(impressNodeChild)
-                || !impressNodes.containsKey(impressNodeParent)) {
+        if (!mImpressNodes.containsKey(impressNodeChild)
+                || !mImpressNodes.containsKey(impressNodeParent)) {
             throw new IllegalArgumentException("Impress node(s) not found");
         }
-        impressNodes.put(impressNodeChild, impressNodeParent);
+        mImpressNodes.put(impressNodeChild, impressNodeParent);
     }
 
+    /** Gets the impress nodes for glTF models that match the given token. */
     @NonNull
     public List<Integer> getImpressNodesForToken(long modelToken) {
-        return gltfModels.get(modelToken);
+        return mGltfModels.get(modelToken);
     }
 
+    /** Returns true if the given impress node has a parent. */
     public boolean impressNodeHasParent(int impressNode) {
-        return impressNodes.containsKey(impressNode) && impressNodes.get(impressNode) != null;
+        return mImpressNodes.containsKey(impressNode) && mImpressNodes.get(impressNode) != null;
     }
 
+    /** Returns the number of impress nodes that are currently animating. */
     public int impressNodeAnimatingSize() {
-        return impressAnimatedNodes.size();
+        return mImpressAnimatedNodes.size();
     }
 
+    /** Returns the number of impress nodes that looping animations. */
     public int impressNodeLoopAnimatingSize() {
-        return impressLoopAnimatedNodes.size();
+        return mImpressLoopAnimatedNodes.size();
     }
 
     @Override
     public int createStereoSurface(@StereoMode int mode) {
-        return nextNodeId++;
+        return mNextNodeId++;
     }
 
     @Override
diff --git a/xr/scenecore/scenecore-testing/src/main/java/androidx/xr/scenecore/testing/FakeScheduledExecutorService.java b/xr/scenecore/scenecore-testing/src/main/java/androidx/xr/scenecore/testing/FakeScheduledExecutorService.java
index 802791d..2b5f97e4 100644
--- a/xr/scenecore/scenecore-testing/src/main/java/androidx/xr/scenecore/testing/FakeScheduledExecutorService.java
+++ b/xr/scenecore/scenecore-testing/src/main/java/androidx/xr/scenecore/testing/FakeScheduledExecutorService.java
@@ -66,21 +66,21 @@
         return Duration.ofMillis(durationClockUnit);
     }
 
-    private final Clock clock;
-    private final Queue<Runnable> executeQueue = new ConcurrentLinkedQueue<>();
-    private final PriorityBlockingQueue<DelayedFuture<?>> scheduledQueue =
+    private final Clock mClock;
+    private final Queue<Runnable> mExecuteQueue = new ConcurrentLinkedQueue<>();
+    private final PriorityBlockingQueue<DelayedFuture<?>> mScheduledQueue =
             new PriorityBlockingQueue<>();
 
-    private final AtomicLong nextSequenceId = new AtomicLong(0);
-    private volatile boolean running = true;
+    private final AtomicLong mNextSequenceId = new AtomicLong(0);
+    private volatile boolean mRunning = true;
 
     public FakeScheduledExecutorService() {
-        this.clock = new Clock();
+        mClock = new Clock();
     }
 
     @Override
     public boolean isShutdown() {
-        return !running;
+        return !mRunning;
     }
 
     @Override
@@ -90,7 +90,7 @@
 
     @Override
     public void shutdown() {
-        running = false;
+        mRunning = false;
     }
 
     @Override
@@ -101,19 +101,19 @@
     @Override
     @NonNull
     public List<Runnable> shutdownNow() {
-        running = false;
+        mRunning = false;
         List<Runnable> commands = Lists.newArrayList();
-        commands.addAll(executeQueue);
-        commands.addAll(scheduledQueue);
-        executeQueue.clear();
-        scheduledQueue.clear();
+        commands.addAll(mExecuteQueue);
+        commands.addAll(mScheduledQueue);
+        mExecuteQueue.clear();
+        mScheduledQueue.clear();
         return commands;
     }
 
     @Override
     public boolean awaitTermination(long timeout, @Nullable TimeUnit unit) {
-        checkState(!running);
-        while (!executeQueue.isEmpty()) {
+        checkState(!mRunning);
+        while (!mExecuteQueue.isEmpty()) {
             runNext();
         }
         simulateSleepExecutingAllTasks(durationFromClockUnit(timeout));
@@ -123,11 +123,11 @@
     @Override
     public void execute(@Nullable Runnable command) {
         assertRunning();
-        executeQueue.add(command);
+        mExecuteQueue.add(command);
     }
 
     private void assertRunning() {
-        if (!running) {
+        if (!mRunning) {
             throw new RejectedExecutionException();
         }
     }
@@ -138,7 +138,7 @@
             @Nullable Runnable command, long delay, @Nullable TimeUnit unit) {
         assertRunning();
         DelayedFuture<?> future = new DelayedFuture<>(command, delay, unit);
-        scheduledQueue.add(future);
+        mScheduledQueue.add(future);
         return future;
     }
 
@@ -148,7 +148,7 @@
             @Nullable Callable<V> callable, long delay, @Nullable TimeUnit unit) {
         assertRunning();
         DelayedFuture<V> future = new DelayedCallable<V>(callable, delay, unit);
-        scheduledQueue.add(future);
+        mScheduledQueue.add(future);
         return future;
     }
 
@@ -168,13 +168,13 @@
 
     /** Returns true if the {@link #execute} queue contains at least one runnable. */
     public boolean hasNext() {
-        return !executeQueue.isEmpty();
+        return !mExecuteQueue.isEmpty();
     }
 
     /** Runs the next runnable in the {@link #execute} queue. */
     public void runNext() {
-        checkState(!executeQueue.isEmpty(), "execute queue must not be empty");
-        Runnable runnable = executeQueue.remove();
+        checkState(!mExecuteQueue.isEmpty(), "execute queue must not be empty");
+        Runnable runnable = mExecuteQueue.remove();
         runTaskWithInterruptIsolation(runnable);
     }
 
@@ -188,7 +188,7 @@
     /** Returns whether any runnable is in the {@link #execute} or {@link #schedule} queue. */
     @CheckReturnValue
     public boolean isEmpty() {
-        return executeQueue.isEmpty() && scheduledQueue.isEmpty();
+        return mExecuteQueue.isEmpty() && mScheduledQueue.isEmpty();
     }
 
     /**
@@ -199,11 +199,11 @@
         long timeout = toClockUnit(duration);
         checkArgument(timeout >= 0, "timeout (%s) cannot be negative", timeout);
 
-        long stopTime = clock.currentTimeMillis() + CLOCK_UNIT.toMillis(timeout);
+        long stopTime = mClock.currentTimeMillis() + CLOCK_UNIT.toMillis(timeout);
         boolean done = false;
 
         while (!done) {
-            long delay = (stopTime - clock.currentTimeMillis());
+            long delay = (stopTime - mClock.currentTimeMillis());
             if (delay >= 0 && simulateSleepExecutingAtMostOneTask(durationFromClockUnit(delay))) {
                 continue;
             } else {
@@ -219,20 +219,20 @@
     public boolean simulateSleepExecutingAtMostOneTask(@NonNull Duration duration) {
         long timeout = toClockUnit(duration);
         checkArgument(timeout >= 0, "timeout (%s) cannot be negative", timeout);
-        if (scheduledQueue.isEmpty()) {
-            clock.advanceBy(duration);
+        if (mScheduledQueue.isEmpty()) {
+            mClock.advanceBy(duration);
             return false;
         }
 
-        DelayedFuture<?> future = scheduledQueue.peek();
+        DelayedFuture<?> future = mScheduledQueue.peek();
         long delay = future.getDelay(CLOCK_UNIT);
         if (delay > timeout) {
             // Next event is too far in the future; delay the entire time
-            clock.advanceBy(duration);
+            mClock.advanceBy(duration);
             return false;
         }
 
-        scheduledQueue.poll();
+        mScheduledQueue.poll();
         runTaskWithInterruptIsolation(future);
 
         return true;
@@ -243,63 +243,63 @@
      * nothing if the {@link #schedule} queue is empty.
      */
     public boolean simulateSleepExecutingAtMostOneTask() {
-        if (scheduledQueue.isEmpty()) {
+        if (mScheduledQueue.isEmpty()) {
             return false;
         }
 
-        DelayedFuture<?> future = scheduledQueue.poll();
+        DelayedFuture<?> future = mScheduledQueue.poll();
         runTaskWithInterruptIsolation(future);
         return true;
     }
 
     private class DelayedFuture<T> implements ScheduledFuture<T>, Runnable {
-        protected final long timeToRun;
-        private final long sequenceId;
-        private final Runnable command;
-        private boolean cancelled;
-        private boolean done;
+        protected final long mTimeToRun;
+        private final long mSequenceId;
+        private final Runnable mCommand;
+        private boolean mCancelled;
+        private boolean mDone;
 
-        public DelayedFuture(Runnable command, long delay, TimeUnit unit) {
+        DelayedFuture(Runnable command, long delay, TimeUnit unit) {
             checkArgument(delay >= 0, "delay (%s) cannot be negative", delay);
 
-            this.command = command;
-            timeToRun = clock.currentTimeMillis() + unit.toMillis(delay);
-            sequenceId = nextSequenceId.getAndIncrement();
+            mCommand = command;
+            mTimeToRun = mClock.currentTimeMillis() + unit.toMillis(delay);
+            mSequenceId = mNextSequenceId.getAndIncrement();
         }
 
         @Override
         public long getDelay(TimeUnit unit) {
-            return unit.convert(timeToRun - clock.currentTimeMillis(), MILLISECONDS);
+            return unit.convert(mTimeToRun - mClock.currentTimeMillis(), MILLISECONDS);
         }
 
         protected void maybeReschedule() {
-            done = true;
+            mDone = true;
         }
 
         @Override
         public void run() {
-            if (clock.currentTimeMillis() < timeToRun) {
-                clock.advanceBy(durationFromClockUnit(timeToRun - clock.currentTimeMillis()));
+            if (mClock.currentTimeMillis() < mTimeToRun) {
+                mClock.advanceBy(durationFromClockUnit(mTimeToRun - mClock.currentTimeMillis()));
             }
-            command.run();
+            mCommand.run();
             maybeReschedule();
         }
 
         @Override
         public boolean cancel(boolean mayInterruptIfRunning) {
-            cancelled = true;
-            done = true;
-            return scheduledQueue.remove(this);
+            mCancelled = true;
+            mDone = true;
+            return mScheduledQueue.remove(this);
         }
 
         @Override
         public boolean isCancelled() {
-            return cancelled;
+            return mCancelled;
         }
 
         @Override
         public boolean isDone() {
-            return done;
+            return mDone;
         }
 
         @Override
@@ -319,12 +319,12 @@
                 return 0;
             }
             DelayedFuture<?> that = (DelayedFuture<?>) other;
-            long diff = timeToRun - that.timeToRun;
+            long diff = mTimeToRun - that.mTimeToRun;
             if (diff < 0) {
                 return -1;
             } else if (diff > 0) {
                 return 1;
-            } else if (sequenceId < that.sequenceId) {
+            } else if (mSequenceId < that.mSequenceId) {
                 return -1;
             } else {
                 return 1;
@@ -333,52 +333,52 @@
     }
 
     private class DelayedCallable<T> extends DelayedFuture<T> {
-        private final FutureTask<T> task;
+        private final FutureTask<T> mTask;
 
         private DelayedCallable(FutureTask<T> task, long delay, TimeUnit unit) {
             super(task, delay, unit);
-            this.task = task;
+            mTask = task;
         }
 
-        public DelayedCallable(Callable<T> callable, long delay, TimeUnit unit) {
+        DelayedCallable(Callable<T> callable, long delay, TimeUnit unit) {
             this(new FutureTask<T>(callable), delay, unit);
         }
 
         @Override
         public boolean cancel(boolean mayInterruptIfRunning) {
-            task.cancel(mayInterruptIfRunning);
+            mTask.cancel(mayInterruptIfRunning);
             return super.cancel(mayInterruptIfRunning);
         }
 
         @Override
         public T get() throws InterruptedException, ExecutionException {
-            return task.get();
+            return mTask.get();
         }
 
         @Override
         public T get(long timeout, TimeUnit unit)
                 throws InterruptedException, ExecutionException, TimeoutException {
-            return task.get(timeout, unit);
+            return mTask.get(timeout, unit);
         }
     }
 
     private static class Clock {
-        private final AtomicReference<Instant> nowReference = new AtomicReference<>();
+        private final AtomicReference<Instant> mNowReference = new AtomicReference<>();
 
-        public Clock() {
+        Clock() {
             setTo(Instant.EPOCH);
         }
 
         public long currentTimeMillis() {
-            return nowReference.get().toEpochMilli();
+            return mNowReference.get().toEpochMilli();
         }
 
         public void advanceBy(Duration duration) {
-            nowReference.getAndUpdate(now -> now.plus(duration));
+            mNowReference.getAndUpdate(now -> now.plus(duration));
         }
 
         public void setTo(Instant instant) {
-            nowReference.set(instant);
+            mNowReference.set(instant);
         }
     }
 
diff --git a/xr/scenecore/scenecore-testing/src/main/java/androidx/xr/scenecore/testing/FakeXrExtensions.java b/xr/scenecore/scenecore-testing/src/main/java/androidx/xr/scenecore/testing/FakeXrExtensions.java
index 843fd12..4bcbd05 100644
--- a/xr/scenecore/scenecore-testing/src/main/java/androidx/xr/scenecore/testing/FakeXrExtensions.java
+++ b/xr/scenecore/scenecore-testing/src/main/java/androidx/xr/scenecore/testing/FakeXrExtensions.java
@@ -98,9 +98,9 @@
 
     @NonNull public final Map<Activity, FakeActivityPanel> activityPanelMap = new HashMap<>();
 
-    FakeNode fakeTaskNode = null;
-    FakeNode fakeEnvironmentNode = null;
-    FakeNode fakeNodeForMainWindow = null;
+    FakeNode mFakeTaskNode = null;
+    FakeNode mFakeEnvironmentNode = null;
+    FakeNode mFakeNodeForMainWindow = null;
 
     // TODO: b/370033054 - fakeSpatialState should be updated according to some fake extensions
     // calls
@@ -109,16 +109,16 @@
 
     // Technically this could be set per-activity, but we're assuming that there's a single activity
     // associated with each JXRCore session, so we're only tracking it once for now.
-    SpaceMode spaceMode = SpaceMode.NONE;
+    SpaceMode mSpaceMode = SpaceMode.NONE;
 
-    int mainWindowWidth = 0;
-    int mainWindowHeight = 0;
+    int mMainWindowWidth = 0;
+    int mMainWindowHeight = 0;
 
-    Consumer<SpatialState> spatialStateCallback = null;
+    Consumer<SpatialState> mSpatialStateCallback = null;
 
-    float preferredAspectRatioHsm = 0.0f;
-    int openXrWorldSpaceType = 0;
-    FakeNodeTransaction lastFakeNodeTransaction = null;
+    float mPreferredAspectRatioHsm = 0.0f;
+    int mOpenXrWorldSpaceType = 0;
+    FakeNodeTransaction mLastFakeNodeTransaction = null;
 
     @NonNull
     public final FakeSpatialAudioExtensions fakeSpatialAudioExtensions =
@@ -126,12 +126,12 @@
 
     @Nullable
     public FakeNode getFakeEnvironmentNode() {
-        return fakeEnvironmentNode;
+        return mFakeEnvironmentNode;
     }
 
     @Nullable
     public FakeNode getFakeNodeForMainWindow() {
-        return fakeNodeForMainWindow;
+        return mFakeNodeForMainWindow;
     }
 
     @Override
@@ -151,8 +151,8 @@
     @Override
     @NonNull
     public NodeTransaction createNodeTransaction() {
-        lastFakeNodeTransaction = new FakeNodeTransaction();
-        return lastFakeNodeTransaction;
+        mLastFakeNodeTransaction = new FakeNodeTransaction();
+        return mLastFakeNodeTransaction;
     }
 
     @Override
@@ -179,7 +179,7 @@
 
     @NonNull
     public SpaceMode getSpaceMode() {
-        return spaceMode;
+        return mSpaceMode;
     }
 
     /**
@@ -198,8 +198,8 @@
             int height,
             @NonNull Consumer<XrExtensionResult> callback,
             @NonNull Executor executor) {
-        mainWindowWidth = width;
-        mainWindowHeight = height;
+        mMainWindowWidth = width;
+        mMainWindowHeight = height;
         executor.execute(() -> callback.accept(createAsyncResult()));
     }
 
@@ -213,11 +213,11 @@
     }
 
     public int getMainWindowWidth() {
-        return mainWindowWidth;
+        return mMainWindowWidth;
     }
 
     public int getMainWindowHeight() {
-        return mainWindowHeight;
+        return mMainWindowHeight;
     }
 
     @Override
@@ -226,7 +226,7 @@
             @NonNull Consumer<Bounds> callback,
             @NonNull Executor executor) {
         callback.accept(
-                (spaceMode == SpaceMode.FULL_SPACE
+                (mSpaceMode == SpaceMode.FULL_SPACE
                         ? new Bounds(
                                 Float.POSITIVE_INFINITY,
                                 Float.POSITIVE_INFINITY,
@@ -282,16 +282,16 @@
             @NonNull Consumer<XrExtensionResult> callback,
             @NonNull Executor executor) {
         FakeSpatialState spatialState = new FakeSpatialState();
-        spatialState.bounds =
+        spatialState.mBounds =
                 requestEnter
                         ? new Bounds(
                                 Float.POSITIVE_INFINITY,
                                 Float.POSITIVE_INFINITY,
                                 Float.POSITIVE_INFINITY)
                         : new Bounds(10f, 10f, 10f);
-        spatialState.capabilities = getCapabilities(requestEnter);
+        spatialState.mCapabilities = getCapabilities(requestEnter);
         sendSpatialState(spatialState);
-        spaceMode = requestEnter ? SpaceMode.FULL_SPACE : SpaceMode.HOME_SPACE;
+        mSpaceMode = requestEnter ? SpaceMode.FULL_SPACE : SpaceMode.HOME_SPACE;
 
         executor.execute(() -> callback.accept(createAsyncResult()));
     }
@@ -325,25 +325,27 @@
             @NonNull Executor executor) {
         // note that we assume this is only called for the (single) primary activity associated with
         // the JXRCore session and we also don't honor the executor here
-        spatialStateCallback = callback;
+        mSpatialStateCallback = callback;
     }
 
     @Override
     public void clearSpatialStateCallback(@NonNull Activity activity) {
-        spatialStateCallback = null;
+        mSpatialStateCallback = null;
     }
 
-    // Method for tests to call to trigger the spatial state callback.
-    // This should probably be called on the provided executor.
+    /**
+     * Tests can use this method to trigger the spatial state callback. It is invoked on the calling
+     * thread.
+     */
     public void sendSpatialState(@NonNull SpatialState spatialState) {
-        if (spatialStateCallback != null) {
-            spatialStateCallback.accept(spatialState);
+        if (mSpatialStateCallback != null) {
+            mSpatialStateCallback.accept(spatialState);
         }
     }
 
     @Nullable
     public Consumer<SpatialState> getSpatialStateCallback() {
-        return spatialStateCallback;
+        return mSpatialStateCallback;
     }
 
     private XrExtensionResult createAsyncResult() {
@@ -372,11 +374,11 @@
             @NonNull Node windowNode,
             @NonNull Consumer<XrExtensionResult> callback,
             @NonNull Executor executor) {
-        fakeTaskNode = (FakeNode) sceneNode;
-        fakeTaskNode.name = "taskNode";
+        mFakeTaskNode = (FakeNode) sceneNode;
+        mFakeTaskNode.mName = "taskNode";
 
-        fakeNodeForMainWindow = (FakeNode) windowNode;
-        fakeNodeForMainWindow.name = "nodeForMainWindow";
+        mFakeNodeForMainWindow = (FakeNode) windowNode;
+        mFakeNodeForMainWindow.mName = "nodeForMainWindow";
 
         executor.execute(() -> callback.accept(createAsyncResult()));
     }
@@ -395,15 +397,15 @@
             @NonNull Activity activity,
             @NonNull Consumer<XrExtensionResult> callback,
             @NonNull Executor executor) {
-        fakeTaskNode = null;
-        fakeNodeForMainWindow = null;
+        mFakeTaskNode = null;
+        mFakeNodeForMainWindow = null;
 
         executor.execute(() -> callback.accept(createAsyncResult()));
     }
 
     @Nullable
     public FakeNode getFakeTaskNode() {
-        return fakeTaskNode;
+        return mFakeTaskNode;
     }
 
     /**
@@ -422,8 +424,8 @@
             @NonNull Node environmentNode,
             @NonNull Consumer<XrExtensionResult> callback,
             @NonNull Executor executor) {
-        fakeEnvironmentNode = (FakeNode) environmentNode;
-        fakeEnvironmentNode.name = "environmentNode";
+        mFakeEnvironmentNode = (FakeNode) environmentNode;
+        mFakeEnvironmentNode.mName = "environmentNode";
 
         executor.execute(() -> callback.accept(createAsyncResult()));
     }
@@ -442,7 +444,7 @@
             @NonNull Activity activity,
             @NonNull Consumer<XrExtensionResult> callback,
             @NonNull Executor executor) {
-        fakeEnvironmentNode = null;
+        mFakeEnvironmentNode = null;
 
         executor.execute(() -> callback.accept(createAsyncResult()));
     }
@@ -490,7 +492,7 @@
     @Override
     @NonNull
     @Deprecated
-    //  public ListenableFuture</* @Nullable */ androidx.xr.extensions.asset.EnvironmentToken>
+    //  public ListenableFuture</* @Nullable */ EnvironmentToken>
     // loadEnvironment(
     public CompletableFuture</* @Nullable */ androidx.xr.extensions.asset.EnvironmentToken>
             loadEnvironment(
@@ -554,7 +556,7 @@
     public FakeNode testGetNodeWithGltfToken(
             @NonNull androidx.xr.extensions.asset.GltfModelToken token) {
         for (FakeNode node : createdNodes) {
-            if (node.gltfModel != null && node.gltfModel.equals(token)) {
+            if (node.mGltfModel != null && node.mGltfModel.equals(token)) {
                 return node;
             }
         }
@@ -571,7 +573,7 @@
     public FakeNode testGetNodeWithEnvironmentToken(
             @NonNull androidx.xr.extensions.asset.EnvironmentToken token) {
         for (FakeNode node : createdNodes) {
-            if (node.environment != null && node.environment.equals(token)) {
+            if (node.mEnvironment != null && node.mEnvironment.equals(token)) {
                 return node;
             }
         }
@@ -587,6 +589,7 @@
         return fakeActivityPanel;
     }
 
+    /** Returns the FakeActivityPanel for the given Activity. */
     @NonNull
     public FakeActivityPanel getActivityPanelForHost(@NonNull Activity host) {
         return activityPanelMap.get(host);
@@ -622,16 +625,17 @@
             @NonNull Vec3 direction,
             @NonNull Consumer<HitTestResult> callback,
             @NonNull Executor executor) {
-        throw new UnsupportedOperationException(NOT_IMPLEMENTED_IN_FAKE);
+        HitTestResult fakeHitTestResult = new HitTestResult();
+        executor.execute(() -> callback.accept(fakeHitTestResult));
     }
 
     @Override
     public int getOpenXrWorldSpaceType() {
-        return openXrWorldSpaceType;
+        return mOpenXrWorldSpaceType;
     }
 
     public void setOpenXrWorldSpaceType(int openXrWorldSpaceType) {
-        this.openXrWorldSpaceType = openXrWorldSpaceType;
+        mOpenXrWorldSpaceType = openXrWorldSpaceType;
     }
 
     @Override
@@ -657,13 +661,13 @@
             float preferredRatio,
             @NonNull Consumer<XrExtensionResult> callback,
             @NonNull Executor executor) {
-        preferredAspectRatioHsm = preferredRatio;
+        mPreferredAspectRatioHsm = preferredRatio;
 
         executor.execute(() -> callback.accept(createAsyncResult()));
     }
 
     public float getPreferredAspectRatio() {
-        return preferredAspectRatioHsm;
+        return mPreferredAspectRatioHsm;
     }
 
     @NonNull
@@ -692,63 +696,63 @@
     /** A fake implementation of Closeable. */
     @SuppressWarnings("NotCloseable")
     public static class FakeCloseable implements Closeable {
-        boolean closed = false;
+        boolean mClosed = false;
 
         @Override
         public void close() {
-            closed = true;
+            mClosed = true;
         }
 
         public boolean isClosed() {
-            return closed;
+            return mClosed;
         }
     }
 
     /** A fake implementation of the XR extensions Node. */
     @SuppressWarnings("ParcelCreator")
     public static final class FakeNode implements Node {
-        FakeNode parent = null;
-        float xPosition = 0.0f;
-        float yPosition = 0.0f;
-        float zPosition = 0.0f;
-        float xOrientation = 0.0f;
-        float yOrientation = 0.0f;
-        float zOrientation = 0.0f;
-        float wOrientation = 1.0f;
-        float xScale = 1.0f;
-        float yScale = 1.0f;
-        float zScale = 1.0f;
-        float cornerRadius = 0.0f;
-        boolean isVisible = false;
-        float alpha = 1.0f;
-        androidx.xr.extensions.asset.GltfModelToken gltfModel = null;
-        IBinder anchorId = null;
-        String name = null;
-        float passthroughOpacity = 1.0f;
-        @PassthroughState.Mode int passthroughMode = 0;
-        SurfaceControlViewHost.SurfacePackage surfacePackage = null;
-        androidx.xr.extensions.asset.EnvironmentToken environment = null;
-        Consumer<InputEvent> listener = null;
-        Consumer<NodeTransform> transformListener = null;
-        Consumer<Integer> pointerCaptureStateCallback = null;
+        FakeNode mParent = null;
+        float mXPosition = 0.0f;
+        float mYPosition = 0.0f;
+        float mZPosition = 0.0f;
+        float mXOrientation = 0.0f;
+        float mYOrientation = 0.0f;
+        float mZOrientation = 0.0f;
+        float mWOrientation = 1.0f;
+        float mXScale = 1.0f;
+        float mYScale = 1.0f;
+        float mZScale = 1.0f;
+        float mCornerRadius = 0.0f;
+        boolean mIsVisible = false;
+        float mAlpha = 1.0f;
+        androidx.xr.extensions.asset.GltfModelToken mGltfModel = null;
+        IBinder mAnchorId = null;
+        String mName = null;
+        float mPassthroughOpacity = 1.0f;
+        @PassthroughState.Mode int mPassthroughMode = 0;
+        SurfaceControlViewHost.SurfacePackage mSurfacePackage = null;
+        androidx.xr.extensions.asset.EnvironmentToken mEnvironment = null;
+        Consumer<InputEvent> mListener = null;
+        Consumer<NodeTransform> mTransformListener = null;
+        Consumer<Integer> mPointerCaptureStateCallback = null;
 
-        Executor executor = null;
-        ReformOptions reformOptions;
-        Executor transformExecutor = null;
+        Executor mExecutor = null;
+        ReformOptions mReformOptions;
+        Executor mTransformExecutor = null;
 
         private FakeNode() {}
 
         @Override
         public void listenForInput(
                 @NonNull Consumer<InputEvent> listener, @NonNull Executor executor) {
-            this.listener = listener;
-            this.executor = executor;
+            mListener = listener;
+            mExecutor = executor;
         }
 
         @Override
         public void stopListeningForInput() {
-            listener = null;
-            executor = null;
+            mListener = null;
+            mExecutor = null;
         }
 
         @Override
@@ -757,39 +761,47 @@
         @Override
         public void requestPointerCapture(
                 @NonNull Consumer<Integer> stateCallback, @NonNull Executor executor) {
-            pointerCaptureStateCallback = stateCallback;
+            mPointerCaptureStateCallback = stateCallback;
         }
 
         @Override
         public void stopPointerCapture() {
-            pointerCaptureStateCallback = null;
+            mPointerCaptureStateCallback = null;
         }
 
+        /**
+         * Fires the InputEvent callback with the given event. It is invoked on the executor
+         * provided in listenForInput.
+         */
         public void sendInputEvent(@NonNull InputEvent event) {
-            executor.execute(() -> listener.accept(event));
+            mExecutor.execute(() -> mListener.accept(event));
         }
 
+        /**
+         * Fires the nodeTransform callback with the given transform. It is invoked on the executor
+         * provided in listenForInput.
+         */
         public void sendTransformEvent(@NonNull FakeNodeTransform nodeTransform) {
-            transformExecutor.execute(() -> transformListener.accept(nodeTransform));
+            mTransformExecutor.execute(() -> mTransformListener.accept(nodeTransform));
         }
 
         @Override
         @NonNull
         public Closeable subscribeToTransform(
                 @NonNull Consumer<NodeTransform> transformCallback, @NonNull Executor executor) {
-            this.transformListener = transformCallback;
-            this.transformExecutor = executor;
+            mTransformListener = transformCallback;
+            mTransformExecutor = executor;
             return new FakeCloseable();
         }
 
         @Nullable
         public Consumer<NodeTransform> getTransformListener() {
-            return transformListener;
+            return mTransformListener;
         }
 
         @Nullable
         public Executor getTransformExecutor() {
-            return transformExecutor;
+            return mTransformExecutor;
         }
 
         @Override
@@ -802,43 +814,43 @@
 
         @Nullable
         public FakeNode getParent() {
-            return parent;
+            return mParent;
         }
 
         public float getXPosition() {
-            return xPosition;
+            return mXPosition;
         }
 
         public float getYPosition() {
-            return yPosition;
+            return mYPosition;
         }
 
         public float getZPosition() {
-            return zPosition;
+            return mZPosition;
         }
 
         public float getXOrientation() {
-            return xOrientation;
+            return mXOrientation;
         }
 
         public float getYOrientation() {
-            return yOrientation;
+            return mYOrientation;
         }
 
         public float getZOrientation() {
-            return zOrientation;
+            return mZOrientation;
         }
 
         public float getWOrientation() {
-            return wOrientation;
+            return mWOrientation;
         }
 
         public boolean isVisible() {
-            return isVisible;
+            return mIsVisible;
         }
 
         public float getAlpha() {
-            return alpha;
+            return mAlpha;
         }
 
         /**
@@ -847,22 +859,22 @@
         @Nullable
         @Deprecated
         public androidx.xr.extensions.asset.GltfModelToken getGltfModel() {
-            return gltfModel;
+            return mGltfModel;
         }
 
         @Nullable
         public IBinder getAnchorId() {
-            return anchorId;
+            return mAnchorId;
         }
 
         @Nullable
         public String getName() {
-            return name;
+            return mName;
         }
 
         @Nullable
         public SurfaceControlViewHost.SurfacePackage getSurfacePackage() {
-            return surfacePackage;
+            return mSurfacePackage;
         }
 
         /**
@@ -871,27 +883,27 @@
         @Nullable
         @Deprecated
         public androidx.xr.extensions.asset.EnvironmentToken getEnvironment() {
-            return environment;
+            return mEnvironment;
         }
 
         @Nullable
         public Consumer<InputEvent> getListener() {
-            return listener;
+            return mListener;
         }
 
         @Nullable
         public Consumer<Integer> getPointerCaptureStateCallback() {
-            return pointerCaptureStateCallback;
+            return mPointerCaptureStateCallback;
         }
 
         @Nullable
         public Executor getExecutor() {
-            return executor;
+            return mExecutor;
         }
 
         @Nullable
         public ReformOptions getReformOptions() {
-            return reformOptions;
+            return mReformOptions;
         }
     }
 
@@ -902,16 +914,16 @@
      */
     @SuppressWarnings("NotCloseable")
     public static class FakeNodeTransaction implements NodeTransaction {
-        FakeNode lastFakeNode = null;
-        boolean applied = false;
+        FakeNode mLastFakeNode = null;
+        boolean mApplied = false;
 
         private FakeNodeTransaction() {}
 
         @Override
         @NonNull
         public NodeTransaction setParent(@NonNull Node node, @Nullable Node parent) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).parent = (FakeNode) parent;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mParent = (FakeNode) parent;
             return this;
         }
 
@@ -923,18 +935,18 @@
         @Deprecated
         public NodeTransaction setEnvironment(
                 @NonNull Node node, @Nullable androidx.xr.extensions.asset.EnvironmentToken token) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).environment = token;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mEnvironment = token;
             return this;
         }
 
         @Override
         @NonNull
         public NodeTransaction setPosition(@NonNull Node node, float x, float y, float z) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).xPosition = x;
-            ((FakeNode) node).yPosition = y;
-            ((FakeNode) node).zPosition = z;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mXPosition = x;
+            ((FakeNode) node).mYPosition = y;
+            ((FakeNode) node).mZPosition = z;
             return this;
         }
 
@@ -942,11 +954,11 @@
         @NonNull
         public NodeTransaction setOrientation(
                 @NonNull Node node, float x, float y, float z, float w) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).xOrientation = x;
-            ((FakeNode) node).yOrientation = y;
-            ((FakeNode) node).zOrientation = z;
-            ((FakeNode) node).wOrientation = w;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mXOrientation = x;
+            ((FakeNode) node).mYOrientation = y;
+            ((FakeNode) node).mZOrientation = z;
+            ((FakeNode) node).mWOrientation = w;
             return this;
         }
 
@@ -954,26 +966,26 @@
         @NonNull
         // TODO(b/354731545): Cover this with an AndroidXREntity test
         public NodeTransaction setScale(@NonNull Node node, float sx, float sy, float sz) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).xScale = sx;
-            ((FakeNode) node).yScale = sy;
-            ((FakeNode) node).zScale = sz;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mXScale = sx;
+            ((FakeNode) node).mYScale = sy;
+            ((FakeNode) node).mZScale = sz;
             return this;
         }
 
         @Override
         @NonNull
         public NodeTransaction setVisibility(@NonNull Node node, boolean isVisible) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).isVisible = isVisible;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mIsVisible = isVisible;
             return this;
         }
 
         @Override
         @NonNull
         public NodeTransaction setAlpha(@NonNull Node node, float value) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).alpha = value;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mAlpha = value;
             return this;
         }
 
@@ -986,16 +998,16 @@
         public NodeTransaction setGltfModel(
                 @NonNull Node node,
                 @NonNull androidx.xr.extensions.asset.GltfModelToken gltfModelToken) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).gltfModel = gltfModelToken;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mGltfModel = gltfModelToken;
             return this;
         }
 
         @Override
         @NonNull
         public NodeTransaction setName(@NonNull Node node, @NonNull String name) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).name = name;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mName = name;
             return this;
         }
 
@@ -1005,9 +1017,9 @@
                 @NonNull Node node,
                 float passthroughOpacity,
                 @PassthroughState.Mode int passthroughMode) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).passthroughOpacity = passthroughOpacity;
-            ((FakeNode) node).passthroughMode = passthroughMode;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mPassthroughOpacity = passthroughOpacity;
+            ((FakeNode) node).mPassthroughMode = passthroughMode;
             return this;
         }
 
@@ -1016,8 +1028,8 @@
         public NodeTransaction setSurfacePackage(
                 @Nullable Node node,
                 @NonNull SurfaceControlViewHost.SurfacePackage surfacePackage) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).surfacePackage = surfacePackage;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mSurfacePackage = surfacePackage;
             return this;
         }
 
@@ -1033,47 +1045,47 @@
         @Override
         @NonNull
         public NodeTransaction setAnchorId(@NonNull Node node, @Nullable IBinder anchorId) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).anchorId = anchorId;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mAnchorId = anchorId;
             return this;
         }
 
         @Override
         @NonNull
         public NodeTransaction enableReform(@NonNull Node node, @NonNull ReformOptions options) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).reformOptions = options;
-            ((FakeReformOptions) options).optionsApplied = true;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mReformOptions = options;
+            ((FakeReformOptions) options).mOptionsApplied = true;
             return this;
         }
 
         @Override
         @NonNull
         public NodeTransaction setReformSize(@NonNull Node node, @NonNull Vec3 reformSize) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).reformOptions.setCurrentSize(reformSize);
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mReformOptions.setCurrentSize(reformSize);
             return this;
         }
 
         @Override
         @NonNull
         public NodeTransaction disableReform(@NonNull Node node) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).reformOptions = new FakeReformOptions(null, null);
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mReformOptions = new FakeReformOptions(null, null);
             return this;
         }
 
         @Override
         @NonNull
         public NodeTransaction setCornerRadius(@NonNull Node node, float cornerRadius) {
-            lastFakeNode = (FakeNode) node;
-            ((FakeNode) node).cornerRadius = cornerRadius;
+            mLastFakeNode = (FakeNode) node;
+            ((FakeNode) node).mCornerRadius = cornerRadius;
             return this;
         }
 
         @Override
         public void apply() {
-            applied = true;
+            mApplied = true;
         }
 
         @Override
@@ -1082,16 +1094,16 @@
 
     /** A fake implementation of the XR extensions NodeTransform. */
     public static class FakeNodeTransform implements NodeTransform {
-        Mat4f transform;
+        Mat4f mTransform;
 
         public FakeNodeTransform(@NonNull Mat4f transform) {
-            this.transform = transform;
+            mTransform = transform;
         }
 
         @Override
         @NonNull
         public Mat4f getTransform() {
-            return transform;
+            return mTransform;
         }
 
         @Override
@@ -1102,261 +1114,261 @@
 
     /** A fake implementation of the XR extensions GltfModelToken. */
     public static class FakeGltfModelToken implements androidx.xr.extensions.asset.GltfModelToken {
-        String url;
+        String mUrl;
 
         public FakeGltfModelToken(@NonNull String url) {
-            this.url = url;
+            mUrl = url;
         }
 
         @NonNull
         public String getUrl() {
-            return url;
+            return mUrl;
         }
     }
 
     /** A fake implementation of the XR extensions EnvironmentToken. */
     public static class FakeEnvironmentToken
             implements androidx.xr.extensions.asset.EnvironmentToken {
-        String url;
+        String mUrl;
 
         private FakeEnvironmentToken(@NonNull String url) {
-            this.url = url;
+            this.mUrl = url;
         }
 
         @NonNull
         public String getUrl() {
-            return url;
+            return mUrl;
         }
     }
 
     /** A fake implementation of the XR extensions EnvironmentVisibilityState. */
     public static class FakeEnvironmentVisibilityState implements EnvironmentVisibilityState {
-        @EnvironmentVisibilityState.State int state;
+        @EnvironmentVisibilityState.State int mState;
 
         public FakeEnvironmentVisibilityState(@EnvironmentVisibilityState.State int state) {
-            this.state = state;
+            this.mState = state;
         }
 
         @Override
         @EnvironmentVisibilityState.State
         public int getCurrentState() {
-            return state;
+            return mState;
         }
     }
 
     /** A fake implementation of the XR extensions EnvironmentVisibilityState. */
     public static class FakePassthroughVisibilityState implements PassthroughVisibilityState {
-        @PassthroughVisibilityState.State int state;
-        float opacity;
+        @PassthroughVisibilityState.State int mState;
+        float mOpacity;
 
         public FakePassthroughVisibilityState(
                 @PassthroughVisibilityState.State int state, float opacity) {
-            this.state = state;
-            this.opacity = opacity;
+            this.mState = state;
+            this.mOpacity = opacity;
         }
 
         @Override
         @PassthroughVisibilityState.State
         public int getCurrentState() {
-            return state;
+            return mState;
         }
 
         @Override
         public float getOpacity() {
-            return opacity;
+            return mOpacity;
         }
     }
 
     /** Creates fake activity panel. */
     public static class FakeActivityPanel implements ActivityPanel {
-        Intent launchIntent;
-        Bundle bundle;
-        Activity activity;
-        Rect bounds;
-        boolean isDeleted = false;
-        Node node;
+        Intent mLaunchIntent;
+        Bundle mBundle;
+        Activity mActivity;
+        Rect mBounds;
+        boolean mIsDeleted = false;
+        Node mNode;
 
         FakeActivityPanel(@NonNull Node node) {
-            this.node = node;
+            mNode = node;
         }
 
         @Override
         public void launchActivity(@NonNull Intent intent, @Nullable Bundle options) {
-            launchIntent = intent;
-            this.bundle = options;
+            mLaunchIntent = intent;
+            mBundle = options;
         }
 
         @Nullable
         public Intent getLaunchIntent() {
-            return launchIntent;
+            return mLaunchIntent;
         }
 
         @NonNull
         public Bundle getBundle() {
-            return bundle;
+            return mBundle;
         }
 
         @Override
         public void moveActivity(@NonNull Activity activity) {
-            this.activity = activity;
+            mActivity = activity;
         }
 
         @Nullable
         public Activity getActivity() {
-            return activity;
+            return mActivity;
         }
 
         @NonNull
         @Override
         public Node getNode() {
-            return node;
+            return mNode;
         }
 
         @Override
         public void setWindowBounds(@NonNull Rect windowBounds) {
-            bounds = windowBounds;
+            mBounds = windowBounds;
         }
 
         @Nullable
         public Rect getBounds() {
-            return bounds;
+            return mBounds;
         }
 
         @Override
         public void delete() {
-            isDeleted = true;
+            mIsDeleted = true;
         }
 
         public boolean isDeleted() {
-            return isDeleted;
+            return mIsDeleted;
         }
     }
 
     /** Fake input event. */
     public static class FakeInputEvent implements InputEvent {
-        int source;
-        int pointerType;
-        long timestamp;
-        Vec3 origin;
-        Vec3 direction;
-        FakeHitInfo hitInfo;
-        FakeHitInfo secondaryHitInfo;
-        int dispatchFlags;
-        int action;
+        int mSource;
+        int mPointerType;
+        long mTimestamp;
+        Vec3 mOrigin;
+        Vec3 mDirection;
+        FakeHitInfo mHitInfo;
+        FakeHitInfo mSecondaryHitInfo;
+        int mDispatchFlags;
+        int mAction;
 
         @Override
         public int getSource() {
-            return source;
+            return mSource;
         }
 
         @Override
         public int getPointerType() {
-            return pointerType;
+            return mPointerType;
         }
 
         @Override
         public long getTimestamp() {
-            return timestamp;
+            return mTimestamp;
         }
 
         @Override
         @NonNull
         public Vec3 getOrigin() {
-            return origin;
+            return mOrigin;
         }
 
         @Override
         @NonNull
         public Vec3 getDirection() {
-            return direction;
+            return mDirection;
         }
 
         @Override
         @Nullable
         public HitInfo getHitInfo() {
-            return hitInfo;
+            return mHitInfo;
         }
 
         @Override
         @Nullable
         public HitInfo getSecondaryHitInfo() {
-            return secondaryHitInfo;
+            return mSecondaryHitInfo;
         }
 
         @Override
         public int getDispatchFlags() {
-            return dispatchFlags;
+            return mDispatchFlags;
         }
 
         @Override
         public int getAction() {
-            return action;
+            return mAction;
         }
 
         public void setDispatchFlags(int dispatchFlags) {
-            this.dispatchFlags = dispatchFlags;
+            mDispatchFlags = dispatchFlags;
         }
 
         public void setOrigin(@NonNull Vec3 origin) {
-            this.origin = origin;
+            mOrigin = origin;
         }
 
         public void setDirection(@NonNull Vec3 direction) {
-            this.direction = direction;
+            mDirection = direction;
         }
 
         public void setFakeHitInfo(@NonNull FakeHitInfo hitInfo) {
-            this.hitInfo = hitInfo;
+            mHitInfo = hitInfo;
         }
 
         public void setTimestamp(long timestamp) {
-            this.timestamp = timestamp;
+            mTimestamp = timestamp;
         }
 
         /** Fake hit info. */
         public static class FakeHitInfo implements InputEvent.HitInfo {
-            int subspaceImpressNodeId;
-            Node inputNode;
-            Vec3 hitPosition;
-            Mat4f transform;
+            int mSubspaceImpressNodeId;
+            Node mInputNode;
+            Vec3 mHitPosition;
+            Mat4f mTransform;
 
             @Override
             public int getSubspaceImpressNodeId() {
-                return subspaceImpressNodeId;
+                return mSubspaceImpressNodeId;
             }
 
             @Override
             @NonNull
             public Node getInputNode() {
-                return inputNode;
+                return mInputNode;
             }
 
             @Override
             @Nullable
             public Vec3 getHitPosition() {
-                return hitPosition;
+                return mHitPosition;
             }
 
             @Override
             @NonNull
             public Mat4f getTransform() {
-                return transform;
+                return mTransform;
             }
 
             public void setSubspaceImpressNodeId(int subspaceImpressNodeId) {
-                this.subspaceImpressNodeId = subspaceImpressNodeId;
+                mSubspaceImpressNodeId = subspaceImpressNodeId;
             }
 
             public void setInputNode(@NonNull Node inputNode) {
-                this.inputNode = inputNode;
+                mInputNode = inputNode;
             }
 
             public void setHitPosition(@Nullable Vec3 hitPosition) {
-                this.hitPosition = hitPosition;
+                mHitPosition = hitPosition;
             }
 
             public void setTransform(@NonNull Mat4f transform) {
-                this.transform = transform;
+                mTransform = transform;
             }
         }
     }
@@ -1364,138 +1376,151 @@
     /** Fake ReformOptions. */
     public static class FakeReformOptions implements ReformOptions {
 
-        int enabledReforms;
-        int reformFlags;
-        int scaleWithDistanceMode = SCALE_WITH_DISTANCE_MODE_DEFAULT;
-        Vec3 currentSize;
-        Vec3 minimumSize;
-        Vec3 maximumSize;
-        float fixedAspectRatio;
-        Consumer<ReformEvent> consumer;
-        Executor executor;
+        int mEnabledReforms;
+        int mReformFlags;
+        int mScaleWithDistanceMode = SCALE_WITH_DISTANCE_MODE_DEFAULT;
+        Vec3 mCurrentSize;
+        Vec3 mMinimumSize;
+        Vec3 mMaximumSize;
+        float mFixedAspectRatio;
+        boolean mForceShowResizeOverlay;
+        Consumer<ReformEvent> mConsumer;
+        Executor mExecutor;
 
-        boolean optionsApplied = true;
+        boolean mOptionsApplied = true;
 
         FakeReformOptions(Consumer<ReformEvent> consumer, Executor executor) {
-            this.consumer = consumer;
-            this.executor = executor;
+            this.mConsumer = consumer;
+            this.mExecutor = executor;
         }
 
         @Override
         public int getEnabledReform() {
-            return enabledReforms;
+            return mEnabledReforms;
         }
 
         @Override
         @NonNull
         public ReformOptions setEnabledReform(int i) {
-            enabledReforms = i;
+            mEnabledReforms = i;
             return this;
         }
 
         @Override
         public int getFlags() {
-            return reformFlags;
+            return mReformFlags;
         }
 
         @Override
         @NonNull
         public ReformOptions setFlags(int i) {
-            optionsApplied = false;
-            reformFlags = i;
+            mOptionsApplied = false;
+            mReformFlags = i;
             return this;
         }
 
         @NonNull
         @Override
         public Vec3 getCurrentSize() {
-            return currentSize;
+            return mCurrentSize;
         }
 
         @Override
         @NonNull
         public ReformOptions setCurrentSize(@NonNull Vec3 vec3) {
-            optionsApplied = false;
-            currentSize = vec3;
+            mOptionsApplied = false;
+            mCurrentSize = vec3;
             return this;
         }
 
         @NonNull
         @Override
         public Vec3 getMinimumSize() {
-            return minimumSize;
+            return mMinimumSize;
         }
 
         @Override
         @NonNull
         public ReformOptions setMinimumSize(@NonNull Vec3 vec3) {
-            optionsApplied = false;
-            minimumSize = vec3;
+            mOptionsApplied = false;
+            mMinimumSize = vec3;
             return this;
         }
 
         @NonNull
         @Override
         public Vec3 getMaximumSize() {
-            return maximumSize;
+            return mMaximumSize;
         }
 
         @Override
         @NonNull
         public ReformOptions setMaximumSize(@NonNull Vec3 vec3) {
-            optionsApplied = false;
-            maximumSize = vec3;
+            mOptionsApplied = false;
+            mMaximumSize = vec3;
             return this;
         }
 
         @Override
         public float getFixedAspectRatio() {
-            return fixedAspectRatio;
+            return mFixedAspectRatio;
         }
 
         @Override
         @NonNull
         public ReformOptions setFixedAspectRatio(float fixedAspectRatio) {
-            this.fixedAspectRatio = fixedAspectRatio;
+            mFixedAspectRatio = fixedAspectRatio;
+            return this;
+        }
+
+        @Override
+        public boolean getForceShowResizeOverlay() {
+            return mForceShowResizeOverlay;
+        }
+
+        @Override
+        @NonNull
+        public ReformOptions setForceShowResizeOverlay(boolean show) {
+            mForceShowResizeOverlay = show;
             return this;
         }
 
         @NonNull
         @Override
         public Consumer<ReformEvent> getEventCallback() {
-            return consumer;
+            return mConsumer;
         }
 
         @Override
         @NonNull
         @SuppressLint("InvalidNullabilityOverride")
         public ReformOptions setEventCallback(@NonNull Consumer<ReformEvent> consumer) {
-            this.consumer = consumer;
+            mConsumer = consumer;
             return this;
         }
 
         @NonNull
         @Override
         public Executor getEventExecutor() {
-            return executor;
+            return mExecutor;
         }
 
         @Override
         @NonNull
         public ReformOptions setEventExecutor(@NonNull Executor executor) {
-            this.executor = executor;
+            mExecutor = executor;
             return this;
         }
 
         @Override
         public int getScaleWithDistanceMode() {
-            return scaleWithDistanceMode;
+            return mScaleWithDistanceMode;
         }
 
         @Override
         @NonNull
         public ReformOptions setScaleWithDistanceMode(int scaleWithDistanceMode) {
-            this.scaleWithDistanceMode = scaleWithDistanceMode;
+            mScaleWithDistanceMode = scaleWithDistanceMode;
             return this;
         }
     }
@@ -1503,174 +1528,178 @@
     /** Fake ReformEvent. */
     public static class FakeReformEvent implements ReformEvent {
 
-        int type;
-        int state;
-        int id;
-        Vec3 origin = new Vec3(0f, 0f, 0f);
-        Vec3 initialRayOrigin = origin;
-        Vec3 proposedPosition = origin;
-        Vec3 ones = new Vec3(1f, 1f, 1f);
-        Vec3 initialRayDirection = ones;
-        Vec3 proposedScale = ones;
-        Vec3 proposedSize = ones;
-        Vec3 twos = new Vec3(2f, 2f, 2f);
-        Vec3 currentRayOrigin = twos;
-        Vec3 threes = new Vec3(3f, 3f, 3f);
-        Vec3 currentRayDirection = threes;
-        Quatf identity = new Quatf(0f, 0f, 0f, 1f);
-        Quatf proposedOrientation = identity;
+        int mType;
+        int mState;
+        int mId;
+        Vec3 mOrigin = new Vec3(0f, 0f, 0f);
+        Vec3 mInitialRayOrigin = mOrigin;
+        Vec3 mProposedPosition = mOrigin;
+        Vec3 mOnes = new Vec3(1f, 1f, 1f);
+        Vec3 mInitialRayDirection = mOnes;
+        Vec3 mProposedScale = mOnes;
+        Vec3 mProposedSize = mOnes;
+        Vec3 mTwos = new Vec3(2f, 2f, 2f);
+        Vec3 mCurrentRayOrigin = mTwos;
+        Vec3 mThrees = new Vec3(3f, 3f, 3f);
+        Vec3 mCurrentRayDirection = mThrees;
+        Quatf mIdentity = new Quatf(0f, 0f, 0f, 1f);
+        Quatf mProposedOrientation = mIdentity;
 
         public void setType(int type) {
-            this.type = type;
+            mType = type;
         }
 
         public void setState(int state) {
-            this.state = state;
+            mState = state;
         }
 
         public void setProposedPosition(@NonNull Vec3 proposedPosition) {
-            this.proposedPosition = proposedPosition;
+            mProposedPosition = proposedPosition;
         }
 
         public void setProposedScale(@NonNull Vec3 proposedScale) {
-            this.proposedScale = proposedScale;
+            mProposedScale = proposedScale;
         }
 
         public void setProposedOrientation(@NonNull Quatf proposedOrientation) {
-            this.proposedOrientation = proposedOrientation;
+            mProposedOrientation = proposedOrientation;
+        }
+
+        public void setProposedSize(@NonNull Vec3 proposedSize) {
+            mProposedSize = proposedSize;
         }
 
         @Override
         public int getType() {
-            return type;
+            return mType;
         }
 
         @Override
         public int getState() {
-            return state;
+            return mState;
         }
 
         @Override
         public int getId() {
-            return id;
+            return mId;
         }
 
         @NonNull
         @Override
         public Vec3 getInitialRayOrigin() {
-            return initialRayOrigin;
+            return mInitialRayOrigin;
         }
 
         @NonNull
         @Override
         public Vec3 getInitialRayDirection() {
-            return initialRayDirection;
+            return mInitialRayDirection;
         }
 
         @NonNull
         @Override
         public Vec3 getCurrentRayOrigin() {
-            return currentRayOrigin;
+            return mCurrentRayOrigin;
         }
 
         @NonNull
         @Override
         public Vec3 getCurrentRayDirection() {
-            return currentRayDirection;
+            return mCurrentRayDirection;
         }
 
         @NonNull
         @Override
         public Vec3 getProposedPosition() {
-            return proposedPosition;
+            return mProposedPosition;
         }
 
         @NonNull
         @Override
         public Quatf getProposedOrientation() {
-            return proposedOrientation;
+            return mProposedOrientation;
         }
 
         @NonNull
         @Override
         public Vec3 getProposedScale() {
-            return proposedScale;
+            return mProposedScale;
         }
 
         @NonNull
         @Override
         public Vec3 getProposedSize() {
-            return proposedSize;
+            return mProposedSize;
         }
     }
 
     /** A fake implementation of the XR extensions SpatialState. */
     public static class FakeSpatialState implements SpatialState {
-        Bounds bounds;
-        SpatialCapabilities capabilities;
-        EnvironmentVisibilityState environmentVisibilityState;
-        PassthroughVisibilityState passthroughVisibilityState;
+        Bounds mBounds;
+        SpatialCapabilities mCapabilities;
+        EnvironmentVisibilityState mEnvironmentVisibilityState;
+        PassthroughVisibilityState mPassthroughVisibilityState;
 
         public FakeSpatialState() {
             // Initialize params to any non-null values
             // TODO: b/370033054 - Revisit the default values for the bounds and capabilities.
-            this.bounds =
+            mBounds =
                     new Bounds(
                             Float.POSITIVE_INFINITY,
                             Float.POSITIVE_INFINITY,
                             Float.POSITIVE_INFINITY);
             this.setAllSpatialCapabilities(true);
-            this.environmentVisibilityState =
+            mEnvironmentVisibilityState =
                     new FakeEnvironmentVisibilityState(EnvironmentVisibilityState.INVISIBLE);
-            this.passthroughVisibilityState =
+            mPassthroughVisibilityState =
                     new FakePassthroughVisibilityState(PassthroughVisibilityState.DISABLED, 0.0f);
         }
 
         @Override
         @NonNull
         public Bounds getBounds() {
-            return bounds;
+            return mBounds;
         }
 
         public void setBounds(@NonNull Bounds bounds) {
-            this.bounds = bounds;
+            mBounds = bounds;
         }
 
         @Override
         @NonNull
         public SpatialCapabilities getSpatialCapabilities() {
-            return capabilities;
+            return mCapabilities;
         }
 
         @Override
         @NonNull
         public EnvironmentVisibilityState getEnvironmentVisibility() {
-            return environmentVisibilityState;
+            return mEnvironmentVisibilityState;
         }
 
         public void setEnvironmentVisibility(
                 @NonNull EnvironmentVisibilityState environmentVisibilityState) {
-            this.environmentVisibilityState = environmentVisibilityState;
+            mEnvironmentVisibilityState = environmentVisibilityState;
         }
 
         @Override
         @NonNull
         public PassthroughVisibilityState getPassthroughVisibility() {
-            return passthroughVisibilityState;
+            return mPassthroughVisibilityState;
         }
 
         public void setPassthroughVisibility(
                 @NonNull PassthroughVisibilityState passthroughVisibilityState) {
-            this.passthroughVisibilityState = passthroughVisibilityState;
+            mPassthroughVisibilityState = passthroughVisibilityState;
         }
 
         // Methods for tests to set the capabilities.
         public void setSpatialCapabilities(@NonNull SpatialCapabilities capabilities) {
-            this.capabilities = capabilities;
+            mCapabilities = capabilities;
         }
 
         public void setAllSpatialCapabilities(boolean allowAll) {
-            this.capabilities =
+            mCapabilities =
                     new SpatialCapabilities() {
                         @Override
                         public boolean get(int capQuery) {
@@ -1686,7 +1715,7 @@
         @NonNull
         public final FakeSoundPoolExtensions soundPoolExtensions = new FakeSoundPoolExtensions();
 
-        FakeAudioTrackExtensions audioTrackExtensions = new FakeAudioTrackExtensions();
+        FakeAudioTrackExtensions mAudioTrackExtensions = new FakeAudioTrackExtensions();
 
         @NonNull
         public final FakeMediaPlayerExtensions mediaPlayerExtensions =
@@ -1701,12 +1730,12 @@
         @NonNull
         @Override
         public AudioTrackExtensions getAudioTrackExtensions() {
-            return audioTrackExtensions;
+            return mAudioTrackExtensions;
         }
 
         public void setFakeAudioTrackExtensions(
                 @NonNull FakeAudioTrackExtensions audioTrackExtensions) {
-            this.audioTrackExtensions = audioTrackExtensions;
+            mAudioTrackExtensions = audioTrackExtensions;
         }
 
         @NonNull
@@ -1719,20 +1748,20 @@
     /** Fake SoundPoolExtensions. */
     public static class FakeSoundPoolExtensions implements SoundPoolExtensions {
 
-        int playAsPointSourceResult = 0;
-        int playAsSoundFieldResult = 0;
-        int sourceType = SpatializerExtensions.SOURCE_TYPE_BYPASS;
+        int mPlayAsPointSourceResult = 0;
+        int mPlayAsSoundFieldResult = 0;
+        int mSourceType = SpatializerExtensions.SOURCE_TYPE_BYPASS;
 
         public void setPlayAsPointSourceResult(int result) {
-            playAsPointSourceResult = result;
+            mPlayAsPointSourceResult = result;
         }
 
         public void setPlayAsSoundFieldResult(int result) {
-            playAsSoundFieldResult = result;
+            mPlayAsSoundFieldResult = result;
         }
 
         public void setSourceType(@SpatializerExtensions.SourceType int sourceType) {
-            this.sourceType = sourceType;
+            mSourceType = sourceType;
         }
 
         @Override
@@ -1744,7 +1773,7 @@
                 int priority,
                 int loop,
                 float rate) {
-            return playAsPointSourceResult;
+            return mPlayAsPointSourceResult;
         }
 
         @Override
@@ -1756,37 +1785,37 @@
                 int priority,
                 int loop,
                 float rate) {
-            return playAsSoundFieldResult;
+            return mPlayAsSoundFieldResult;
         }
 
         @Override
         @SpatializerExtensions.SourceType
         public int getSpatialSourceType(@NonNull SoundPool soundPool, int streamID) {
-            return sourceType;
+            return mSourceType;
         }
     }
 
     /** Fake AudioTrackExtensions. */
     public static class FakeAudioTrackExtensions implements AudioTrackExtensions {
 
-        PointSourceAttributes pointSourceAttributes;
+        PointSourceAttributes mPointSourceAttributes;
 
-        SoundFieldAttributes soundFieldAttributes;
+        SoundFieldAttributes mSoundFieldAttributes;
 
-        @SpatializerExtensions.SourceType int sourceType;
+        @SpatializerExtensions.SourceType int mSourceType;
 
         @CanIgnoreReturnValue
         @Override
         @NonNull
         public AudioTrack.Builder setPointSourceAttributes(
                 @NonNull AudioTrack.Builder builder, @Nullable PointSourceAttributes attributes) {
-            this.pointSourceAttributes = attributes;
+            mPointSourceAttributes = attributes;
             return builder;
         }
 
         public void setPointSourceAttributes(
                 @Nullable PointSourceAttributes pointSourceAttributes) {
-            this.pointSourceAttributes = pointSourceAttributes;
+            mPointSourceAttributes = pointSourceAttributes;
         }
 
         @CanIgnoreReturnValue
@@ -1794,59 +1823,59 @@
         @NonNull
         public AudioTrack.Builder setSoundFieldAttributes(
                 @NonNull AudioTrack.Builder builder, @Nullable SoundFieldAttributes attributes) {
-            this.soundFieldAttributes = attributes;
+            mSoundFieldAttributes = attributes;
             return builder;
         }
 
         public void setSoundFieldAttributes(@Nullable SoundFieldAttributes soundFieldAttributes) {
-            this.soundFieldAttributes = soundFieldAttributes;
+            mSoundFieldAttributes = soundFieldAttributes;
         }
 
         @Override
         @Nullable
         public PointSourceAttributes getPointSourceAttributes(@NonNull AudioTrack track) {
-            return pointSourceAttributes;
+            return mPointSourceAttributes;
         }
 
         @Nullable
         public PointSourceAttributes getPointSourceAttributes() {
-            return pointSourceAttributes;
+            return mPointSourceAttributes;
         }
 
         @Override
         @Nullable
         public SoundFieldAttributes getSoundFieldAttributes(@NonNull AudioTrack track) {
-            return soundFieldAttributes;
+            return mSoundFieldAttributes;
         }
 
         @Nullable
         public SoundFieldAttributes getSoundFieldAttributes() {
-            return soundFieldAttributes;
+            return mSoundFieldAttributes;
         }
 
         @Override
         public int getSpatialSourceType(@NonNull AudioTrack track) {
-            return sourceType;
+            return mSourceType;
         }
 
         public void setSourceType(@SpatializerExtensions.SourceType int sourceType) {
-            this.sourceType = sourceType;
+            mSourceType = sourceType;
         }
     }
 
     /** Fake MediaPlayerExtensions. */
     public static class FakeMediaPlayerExtensions implements MediaPlayerExtensions {
 
-        PointSourceAttributes pointSourceAttributes;
+        PointSourceAttributes mPointSourceAttributes;
 
-        SoundFieldAttributes soundFieldAttributes;
+        SoundFieldAttributes mSoundFieldAttributes;
 
         @CanIgnoreReturnValue
         @Override
         @NonNull
         public MediaPlayer setPointSourceAttributes(
                 @NonNull MediaPlayer mediaPlayer, @Nullable PointSourceAttributes attributes) {
-            this.pointSourceAttributes = attributes;
+            mPointSourceAttributes = attributes;
             return mediaPlayer;
         }
 
@@ -1855,18 +1884,18 @@
         @NonNull
         public MediaPlayer setSoundFieldAttributes(
                 @NonNull MediaPlayer mediaPlayer, @Nullable SoundFieldAttributes attributes) {
-            this.soundFieldAttributes = attributes;
+            mSoundFieldAttributes = attributes;
             return mediaPlayer;
         }
 
         @Nullable
         public PointSourceAttributes getPointSourceAttributes() {
-            return pointSourceAttributes;
+            return mPointSourceAttributes;
         }
 
         @Nullable
         public SoundFieldAttributes getSoundFieldAttributes() {
-            return soundFieldAttributes;
+            return mSoundFieldAttributes;
         }
     }
 }
diff --git a/xr/scenecore/scenecore/api/restricted_current.txt b/xr/scenecore/scenecore/api/restricted_current.txt
index 762db0b..007d1ce 100644
--- a/xr/scenecore/scenecore/api/restricted_current.txt
+++ b/xr/scenecore/scenecore/api/restricted_current.txt
@@ -830,8 +830,14 @@
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class InteractableComponent implements androidx.xr.scenecore.Component {
+    method public static androidx.xr.scenecore.InteractableComponent create(androidx.xr.scenecore.Session session, java.util.concurrent.Executor executor, androidx.xr.scenecore.InputEventListener inputEventListener);
     method public boolean onAttach(androidx.xr.scenecore.Entity entity);
     method public void onDetach(androidx.xr.scenecore.Entity entity);
+    field public static final androidx.xr.scenecore.InteractableComponent.Companion Companion;
+  }
+
+  public static final class InteractableComponent.Companion {
+    method public androidx.xr.scenecore.InteractableComponent create(androidx.xr.scenecore.Session session, java.util.concurrent.Executor executor, androidx.xr.scenecore.InputEventListener inputEventListener);
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface JxrPlatformAdapter {
@@ -1142,7 +1148,10 @@
   public static interface JxrPlatformAdapter.ResizableComponent extends androidx.xr.scenecore.JxrPlatformAdapter.Component {
     method public void addResizeEventListener(java.util.concurrent.Executor, androidx.xr.scenecore.JxrPlatformAdapter.ResizeEventListener);
     method public void removeResizeEventListener(androidx.xr.scenecore.JxrPlatformAdapter.ResizeEventListener);
+    method public void setAutoHideContent(boolean);
+    method public void setAutoUpdateSize(boolean);
     method public void setFixedAspectRatio(float);
+    method public void setForceShowResizeOverlay(boolean);
     method public void setMaximumSize(androidx.xr.scenecore.JxrPlatformAdapter.Dimensions);
     method public void setMinimumSize(androidx.xr.scenecore.JxrPlatformAdapter.Dimensions);
     method public void setSize(androidx.xr.scenecore.JxrPlatformAdapter.Dimensions);
@@ -1246,13 +1255,28 @@
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class MovableComponent implements androidx.xr.scenecore.Component {
+    method public void addMoveListener(androidx.xr.scenecore.MoveListener moveListener);
     method public void addMoveListener(java.util.concurrent.Executor executor, androidx.xr.scenecore.MoveListener moveListener);
+    method public static androidx.xr.scenecore.MovableComponent create(androidx.xr.scenecore.Session session);
+    method public static androidx.xr.scenecore.MovableComponent create(androidx.xr.scenecore.Session session, optional boolean systemMovable);
+    method public static androidx.xr.scenecore.MovableComponent create(androidx.xr.scenecore.Session session, optional boolean systemMovable, optional boolean scaleInZ);
+    method public static androidx.xr.scenecore.MovableComponent create(androidx.xr.scenecore.Session session, optional boolean systemMovable, optional boolean scaleInZ, optional java.util.Set<androidx.xr.scenecore.AnchorPlacement> anchorPlacement);
+    method public static androidx.xr.scenecore.MovableComponent create(androidx.xr.scenecore.Session session, optional boolean systemMovable, optional boolean scaleInZ, optional java.util.Set<androidx.xr.scenecore.AnchorPlacement> anchorPlacement, optional boolean shouldDisposeParentAnchor);
     method public androidx.xr.scenecore.Dimensions getSize();
     method public boolean onAttach(androidx.xr.scenecore.Entity entity);
     method public void onDetach(androidx.xr.scenecore.Entity entity);
     method public void removeMoveListener(androidx.xr.scenecore.MoveListener moveListener);
     method public void setSize(androidx.xr.scenecore.Dimensions);
     property public final androidx.xr.scenecore.Dimensions size;
+    field public static final androidx.xr.scenecore.MovableComponent.Companion Companion;
+  }
+
+  public static final class MovableComponent.Companion {
+    method public androidx.xr.scenecore.MovableComponent create(androidx.xr.scenecore.Session session);
+    method public androidx.xr.scenecore.MovableComponent create(androidx.xr.scenecore.Session session, optional boolean systemMovable);
+    method public androidx.xr.scenecore.MovableComponent create(androidx.xr.scenecore.Session session, optional boolean systemMovable, optional boolean scaleInZ);
+    method public androidx.xr.scenecore.MovableComponent create(androidx.xr.scenecore.Session session, optional boolean systemMovable, optional boolean scaleInZ, optional java.util.Set<androidx.xr.scenecore.AnchorPlacement> anchorPlacement);
+    method public androidx.xr.scenecore.MovableComponent create(androidx.xr.scenecore.Session session, optional boolean systemMovable, optional boolean scaleInZ, optional java.util.Set<androidx.xr.scenecore.AnchorPlacement> anchorPlacement, optional boolean shouldDisposeParentAnchor);
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface MoveListener {
@@ -1357,22 +1381,42 @@
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class ResizableComponent implements androidx.xr.scenecore.Component {
+    method public void addResizeListener(androidx.xr.scenecore.ResizeListener resizeListener);
     method public void addResizeListener(java.util.concurrent.Executor executor, androidx.xr.scenecore.ResizeListener resizeListener);
+    method public static androidx.xr.scenecore.ResizableComponent create(androidx.xr.scenecore.Session session);
+    method public static androidx.xr.scenecore.ResizableComponent create(androidx.xr.scenecore.Session session, optional androidx.xr.scenecore.Dimensions minimumSize);
+    method public static androidx.xr.scenecore.ResizableComponent create(androidx.xr.scenecore.Session session, optional androidx.xr.scenecore.Dimensions minimumSize, optional androidx.xr.scenecore.Dimensions maximumSize);
+    method public boolean getAutoHideContent();
+    method public boolean getAutoUpdateSize();
     method public float getFixedAspectRatio();
+    method public boolean getForceShowResizeOverlay();
     method public androidx.xr.scenecore.Dimensions getMaximumSize();
     method public androidx.xr.scenecore.Dimensions getMinimumSize();
     method public androidx.xr.scenecore.Dimensions getSize();
     method public boolean onAttach(androidx.xr.scenecore.Entity entity);
     method public void onDetach(androidx.xr.scenecore.Entity entity);
     method public void removeResizeListener(androidx.xr.scenecore.ResizeListener resizeListener);
+    method public void setAutoHideContent(boolean);
+    method public void setAutoUpdateSize(boolean);
     method public void setFixedAspectRatio(float);
+    method public void setForceShowResizeOverlay(boolean);
     method public void setMaximumSize(androidx.xr.scenecore.Dimensions);
     method public void setMinimumSize(androidx.xr.scenecore.Dimensions);
     method public void setSize(androidx.xr.scenecore.Dimensions);
+    property public final boolean autoHideContent;
+    property public final boolean autoUpdateSize;
     property public final float fixedAspectRatio;
+    property public final boolean forceShowResizeOverlay;
     property public final androidx.xr.scenecore.Dimensions maximumSize;
     property public final androidx.xr.scenecore.Dimensions minimumSize;
     property public final androidx.xr.scenecore.Dimensions size;
+    field public static final androidx.xr.scenecore.ResizableComponent.Companion Companion;
+  }
+
+  public static final class ResizableComponent.Companion {
+    method public androidx.xr.scenecore.ResizableComponent create(androidx.xr.scenecore.Session session);
+    method public androidx.xr.scenecore.ResizableComponent create(androidx.xr.scenecore.Session session, optional androidx.xr.scenecore.Dimensions minimumSize);
+    method public androidx.xr.scenecore.ResizableComponent create(androidx.xr.scenecore.Session session, optional androidx.xr.scenecore.Dimensions minimumSize, optional androidx.xr.scenecore.Dimensions maximumSize);
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public interface ResizeListener {
@@ -1382,12 +1426,12 @@
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class Session {
-    ctor public Session(android.app.Activity activity, androidx.xr.scenecore.JxrPlatformAdapter runtime, androidx.xr.scenecore.SpatialEnvironment spatialEnvironment);
+    ctor public Session(android.app.Activity activity, androidx.xr.scenecore.JxrPlatformAdapter platformAdapter, androidx.xr.scenecore.SpatialEnvironment spatialEnvironment);
     method public void addSpatialCapabilitiesChangedListener(java.util.concurrent.Executor callbackExecutor, java.util.function.Consumer<androidx.xr.scenecore.SpatialCapabilities> listener);
     method public void addSpatialCapabilitiesChangedListener(java.util.function.Consumer<androidx.xr.scenecore.SpatialCapabilities> listener);
     method @Deprecated public boolean canEmbedActivityPanel(android.app.Activity activity);
     method public static androidx.xr.scenecore.Session create(android.app.Activity activity);
-    method public static androidx.xr.scenecore.Session create(android.app.Activity activity, optional androidx.xr.scenecore.JxrPlatformAdapter? runtime);
+    method public static androidx.xr.scenecore.Session create(android.app.Activity activity, optional androidx.xr.scenecore.JxrPlatformAdapter? platformAdapter);
     method public androidx.xr.scenecore.ActivityPanelEntity createActivityPanelEntity(android.graphics.Rect windowBoundsPx, String name);
     method public androidx.xr.scenecore.ActivityPanelEntity createActivityPanelEntity(android.graphics.Rect windowBoundsPx, String name, optional androidx.xr.runtime.math.Pose pose);
     method public androidx.xr.scenecore.AnchorEntity createAnchorEntity(androidx.xr.arcore.Anchor anchor);
@@ -1399,36 +1443,21 @@
     method @MainThread public androidx.xr.scenecore.GltfModelEntity createGltfEntity(androidx.xr.scenecore.GltfModel model);
     method @MainThread public androidx.xr.scenecore.GltfModelEntity createGltfEntity(androidx.xr.scenecore.GltfModel model, optional androidx.xr.runtime.math.Pose pose);
     method @MainThread public com.google.common.util.concurrent.ListenableFuture<androidx.xr.scenecore.GltfModel> createGltfResourceAsync(String name);
-    method public androidx.xr.scenecore.InteractableComponent createInteractableComponent(java.util.concurrent.Executor executor, androidx.xr.scenecore.InputEventListener inputEventListener);
-    method public androidx.xr.scenecore.MovableComponent createMovableComponent();
-    method public androidx.xr.scenecore.MovableComponent createMovableComponent(optional boolean systemMovable);
-    method public androidx.xr.scenecore.MovableComponent createMovableComponent(optional boolean systemMovable, optional boolean scaleInZ);
-    method public androidx.xr.scenecore.MovableComponent createMovableComponent(optional boolean systemMovable, optional boolean scaleInZ, optional java.util.Set<androidx.xr.scenecore.AnchorPlacement> anchorPlacement);
-    method public androidx.xr.scenecore.MovableComponent createMovableComponent(optional boolean systemMovable, optional boolean scaleInZ, optional java.util.Set<androidx.xr.scenecore.AnchorPlacement> anchorPlacement, optional boolean shouldDisposeParentAnchor);
     method public androidx.xr.scenecore.PanelEntity createPanelEntity(android.view.View view, androidx.xr.scenecore.Dimensions surfaceDimensionsPx, androidx.xr.scenecore.Dimensions dimensions, String name);
     method public androidx.xr.scenecore.PanelEntity createPanelEntity(android.view.View view, androidx.xr.scenecore.Dimensions surfaceDimensionsPx, androidx.xr.scenecore.Dimensions dimensions, String name, optional androidx.xr.runtime.math.Pose pose);
     method public androidx.xr.scenecore.AnchorEntity createPersistedAnchorEntity(java.util.UUID uuid);
-    method public androidx.xr.scenecore.ResizableComponent createResizableComponent();
-    method public androidx.xr.scenecore.ResizableComponent createResizableComponent(optional androidx.xr.scenecore.Dimensions minimumSize);
-    method public androidx.xr.scenecore.ResizableComponent createResizableComponent(optional androidx.xr.scenecore.Dimensions minimumSize, optional androidx.xr.scenecore.Dimensions maximumSize);
-    method @MainThread public androidx.xr.scenecore.StereoSurfaceEntity createStereoSurfaceEntity();
-    method @MainThread public androidx.xr.scenecore.StereoSurfaceEntity createStereoSurfaceEntity(optional int stereoMode);
-    method @MainThread public androidx.xr.scenecore.StereoSurfaceEntity createStereoSurfaceEntity(optional int stereoMode, optional androidx.xr.scenecore.Dimensions dimensions);
-    method @MainThread public androidx.xr.scenecore.StereoSurfaceEntity createStereoSurfaceEntity(optional int stereoMode, optional androidx.xr.scenecore.Dimensions dimensions, optional androidx.xr.runtime.math.Pose pose);
     method public android.app.Activity getActivity();
     method public androidx.xr.scenecore.ActivitySpace getActivitySpace();
     method public androidx.xr.scenecore.Entity getActivitySpaceRoot();
     method public <T extends androidx.xr.scenecore.Entity> java.util.List<T> getEntitiesOfType(Class<? extends T> type);
     method public androidx.xr.scenecore.PanelEntity getMainPanelEntity();
     method public androidx.xr.scenecore.PerceptionSpace getPerceptionSpace();
-    method public androidx.xr.scenecore.JxrPlatformAdapter getRuntime();
+    method public androidx.xr.scenecore.JxrPlatformAdapter getPlatformAdapter();
     method public androidx.xr.scenecore.SpatialCapabilities getSpatialCapabilities();
     method public androidx.xr.scenecore.SpatialEnvironment getSpatialEnvironment();
     method public androidx.xr.scenecore.SpatialUser getSpatialUser();
     method @Deprecated public boolean hasSpatialCapability(int capability);
     method public void removeSpatialCapabilitiesChangedListener(java.util.function.Consumer<androidx.xr.scenecore.SpatialCapabilities> listener);
-    method public void requestFullSpaceMode();
-    method public void requestHomeSpaceMode();
     method public android.os.Bundle setFullSpaceMode(android.os.Bundle bundle);
     method public android.os.Bundle setFullSpaceModeWithEnvironmentInherited(android.os.Bundle bundle);
     method public void setPreferredAspectRatio(android.app.Activity activity, float preferredRatio);
@@ -1438,7 +1467,7 @@
     property public final androidx.xr.scenecore.Entity activitySpaceRoot;
     property public final androidx.xr.scenecore.PanelEntity mainPanelEntity;
     property public final androidx.xr.scenecore.PerceptionSpace perceptionSpace;
-    property public final androidx.xr.scenecore.JxrPlatformAdapter runtime;
+    property public final androidx.xr.scenecore.JxrPlatformAdapter platformAdapter;
     property public final androidx.xr.scenecore.SpatialEnvironment spatialEnvironment;
     property public final androidx.xr.scenecore.SpatialUser spatialUser;
     field public static final androidx.xr.scenecore.Session.Companion Companion;
@@ -1446,7 +1475,7 @@
 
   public static final class Session.Companion {
     method public androidx.xr.scenecore.Session create(android.app.Activity activity);
-    method public androidx.xr.scenecore.Session create(android.app.Activity activity, optional androidx.xr.scenecore.JxrPlatformAdapter? runtime);
+    method public androidx.xr.scenecore.Session create(android.app.Activity activity, optional androidx.xr.scenecore.JxrPlatformAdapter? platformAdapter);
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class SoundFieldAttributes {
@@ -1514,6 +1543,8 @@
     method public boolean isSpatialEnvironmentPreferenceActive();
     method public void removeOnPassthroughOpacityChangedListener(java.util.function.Consumer<java.lang.Float> listener);
     method public void removeOnSpatialEnvironmentChangedListener(java.util.function.Consumer<java.lang.Boolean> listener);
+    method public void requestFullSpaceMode();
+    method public void requestHomeSpaceMode();
     method @Deprecated public void setGeometry(androidx.xr.scenecore.GltfModel? gltfModel);
     method @Deprecated public void setPassthrough(androidx.xr.scenecore.SpatialEnvironment.PassthroughMode passthroughMode);
     method @Deprecated public void setPassthroughOpacity(float passthroughOpacity);
@@ -1631,6 +1662,14 @@
     method @MainThread public android.view.Surface getSurface();
     method public void setDimensions(androidx.xr.scenecore.Dimensions);
     property public final androidx.xr.scenecore.Dimensions dimensions;
+    field public static final androidx.xr.scenecore.StereoSurfaceEntity.Companion Companion;
+  }
+
+  public static final class StereoSurfaceEntity.Companion {
+    method @MainThread public androidx.xr.scenecore.StereoSurfaceEntity create(androidx.xr.scenecore.Session session);
+    method @MainThread public androidx.xr.scenecore.StereoSurfaceEntity create(androidx.xr.scenecore.Session session, optional int stereoMode);
+    method @MainThread public androidx.xr.scenecore.StereoSurfaceEntity create(androidx.xr.scenecore.Session session, optional int stereoMode, optional androidx.xr.scenecore.Dimensions dimensions);
+    method @MainThread public androidx.xr.scenecore.StereoSurfaceEntity create(androidx.xr.scenecore.Session session, optional int stereoMode, optional androidx.xr.scenecore.Dimensions dimensions, optional androidx.xr.runtime.math.Pose pose);
   }
 
   public static final class StereoSurfaceEntity.StereoMode {
diff --git a/xr/scenecore/scenecore/build.gradle b/xr/scenecore/scenecore/build.gradle
index 187363e..daa6ded 100644
--- a/xr/scenecore/scenecore/build.gradle
+++ b/xr/scenecore/scenecore/build.gradle
@@ -22,6 +22,7 @@
  * modifying its settings.
  */
 
+import androidx.build.AndroidXConfig
 import androidx.build.LibraryType
 import androidx.build.KotlinTarget
 
@@ -59,6 +60,15 @@
     testImplementation(project(":xr:scenecore:scenecore-testing"))
     testImplementation(project(":xr:runtime:runtime-testing"))
 
+    androidTestImplementation(libs.junit)
+    androidTestImplementation(libs.testExtJunit)
+    androidTestImplementation(libs.testExtTruth)
+    androidTestImplementation(libs.testRunner)
+    androidTestImplementation(libs.truth)
+    androidTestImplementation(libs.mockitoAndroid5)
+    androidTestImplementation("androidx.appcompat:appcompat:1.2.0")
+    androidTestImplementation(project(":xr:scenecore:scenecore-testing"))
+
     // For androidx.xr.extensions.
     compileOnly(project(':xr:xr-stubs'))
     testImplementation(project(':xr:xr-stubs'))
@@ -77,6 +87,9 @@
                 srcDirs += ["src/test/java/androidx/xr/scenecore/impl/fake_assets"]
             }
         }
+        androidTest {
+            jniLibs.srcDirs += new File(AndroidXConfig.getPrebuiltsRoot(project), "androidx/xr/androidTest")
+        }
     }
     namespace = "androidx.xr.scenecore"
 }
diff --git a/xr/scenecore/scenecore/src/androidTest/AndroidManifest.xml b/xr/scenecore/scenecore/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000..5f3ccf2
--- /dev/null
+++ b/xr/scenecore/scenecore/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<!--
+  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>
+        <activity
+            android:name="android.app.Activity"
+            android:theme="@style/Theme.AppCompat"
+            android:exported="true"/>
+    </application>
+</manifest>
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/perception/FovTest.java b/xr/scenecore/scenecore/src/androidTest/java/androidx/xr/scenecore/impl/perception/FovTest.java
similarity index 100%
rename from xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/perception/FovTest.java
rename to xr/scenecore/scenecore/src/androidTest/java/androidx/xr/scenecore/impl/perception/FovTest.java
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/perception/PerceptionLibraryTestHelper.java b/xr/scenecore/scenecore/src/androidTest/java/androidx/xr/scenecore/impl/perception/PerceptionLibraryTestHelper.java
similarity index 97%
rename from xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/perception/PerceptionLibraryTestHelper.java
rename to xr/scenecore/scenecore/src/androidTest/java/androidx/xr/scenecore/impl/perception/PerceptionLibraryTestHelper.java
index ff32567..55a84aa 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/perception/PerceptionLibraryTestHelper.java
+++ b/xr/scenecore/scenecore/src/androidTest/java/androidx/xr/scenecore/impl/perception/PerceptionLibraryTestHelper.java
@@ -24,7 +24,7 @@
  */
 final class PerceptionLibraryTestHelper {
 
-    public PerceptionLibraryTestHelper() {}
+    PerceptionLibraryTestHelper() {}
 
     public native void reset();
 
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/perception/PoseTest.java b/xr/scenecore/scenecore/src/androidTest/java/androidx/xr/scenecore/impl/perception/PoseTest.java
similarity index 100%
rename from xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/perception/PoseTest.java
rename to xr/scenecore/scenecore/src/androidTest/java/androidx/xr/scenecore/impl/perception/PoseTest.java
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/perception/ViewProjectionTest.java b/xr/scenecore/scenecore/src/androidTest/java/androidx/xr/scenecore/impl/perception/ViewProjectionTest.java
similarity index 100%
rename from xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/perception/ViewProjectionTest.java
rename to xr/scenecore/scenecore/src/androidTest/java/androidx/xr/scenecore/impl/perception/ViewProjectionTest.java
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/ActivityPose.kt b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/ActivityPose.kt
index ec1e4e1..2c3b3a21 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/ActivityPose.kt
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/ActivityPose.kt
@@ -80,17 +80,17 @@
 ) : BaseActivityPose<JxrPlatformAdapter.CameraViewActivityPose>(rtCameraViewActivityPose) {
 
     internal companion object {
-        internal fun createLeft(runtime: JxrPlatformAdapter): CameraView? {
+        internal fun createLeft(platformAdapter: JxrPlatformAdapter): CameraView? {
             val cameraViewActivityPose =
-                runtime.getCameraViewActivityPose(
+                platformAdapter.getCameraViewActivityPose(
                     JxrPlatformAdapter.CameraViewActivityPose.CAMERA_TYPE_LEFT_EYE
                 )
             return cameraViewActivityPose?.let { CameraView(it) }
         }
 
-        internal fun createRight(runtime: JxrPlatformAdapter): CameraView? {
+        internal fun createRight(platformAdapter: JxrPlatformAdapter): CameraView? {
             val cameraViewActivityPose =
-                runtime.getCameraViewActivityPose(
+                platformAdapter.getCameraViewActivityPose(
                     JxrPlatformAdapter.CameraViewActivityPose.CAMERA_TYPE_RIGHT_EYE
                 )
             return cameraViewActivityPose?.let { CameraView(it) }
@@ -121,7 +121,7 @@
 
 /**
  * Head is a ActivityPose used to track the position of the user's head. If there is a left and
- * right camera it is calculated as the position bettween the two.
+ * right camera it is calculated as the position between the two.
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 public class Head private constructor(rtActivityPose: JxrPlatformAdapter.HeadActivityPose) :
@@ -130,8 +130,8 @@
     internal companion object {
 
         /** Factory function for creating [Head] instance. */
-        internal fun create(runtime: JxrPlatformAdapter): Head? {
-            return runtime.headActivityPose?.let { Head(it) }
+        internal fun create(platformAdapter: JxrPlatformAdapter): Head? {
+            return platformAdapter.headActivityPose?.let { Head(it) }
         }
     }
 }
@@ -148,7 +148,7 @@
     internal companion object {
 
         /** Factory function for creating [PerceptionSpace] instance. */
-        internal fun create(runtime: JxrPlatformAdapter): PerceptionSpace =
-            PerceptionSpace(runtime.perceptionSpaceActivityPose)
+        internal fun create(platformAdapter: JxrPlatformAdapter): PerceptionSpace =
+            PerceptionSpace(platformAdapter.perceptionSpaceActivityPose)
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/Entity.kt b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/Entity.kt
index 5affb34..7bcec3a 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/Entity.kt
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/Entity.kt
@@ -673,7 +673,7 @@
         public const val SIDE_BY_SIDE: Int = 2
     }
 
-    internal companion object {
+    public companion object {
         private fun getRtStereoMode(stereoMode: Int): Int {
             return when (stereoMode) {
                 StereoMode.MONO -> JxrPlatformAdapter.StereoSurfaceEntity.StereoMode.MONO
@@ -709,6 +709,34 @@
                 ),
                 entityManager,
             )
+
+        /**
+         * Public factory function for a StereoSurfaceEntity.
+         *
+         * This method must be called from the main thread.
+         * https://developer.android.com/guide/components/processes-and-threads
+         *
+         * @param session Session to create the StereoSurfaceEntity in.
+         * @param stereoMode Stereo mode for the surface.
+         * @param dimensions Dimensions for the surface.
+         * @param pose Pose of this entity relative to its parent, default value is Identity.
+         * @return a StereoSurfaceEntity instance
+         */
+        @MainThread
+        @JvmOverloads
+        public fun create(
+            session: Session,
+            stereoMode: Int = StereoSurfaceEntity.StereoMode.SIDE_BY_SIDE,
+            dimensions: Dimensions = Dimensions(1.0f, 1.0f, 1.0f),
+            pose: Pose = Pose.Identity,
+        ): StereoSurfaceEntity =
+            StereoSurfaceEntity.create(
+                session.platformAdapter,
+                session.entityManager,
+                stereoMode,
+                dimensions,
+                pose,
+            )
     }
 
     /**
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/InteractableComponent.kt b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/InteractableComponent.kt
index 3ba2924..ef45daa 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/InteractableComponent.kt
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/InteractableComponent.kt
@@ -66,7 +66,7 @@
         this.entity = null
     }
 
-    internal companion object {
+    public companion object {
         /** Factory for Interactable component. */
         internal fun create(
             runtime: JxrPlatformAdapter,
@@ -76,5 +76,28 @@
         ): InteractableComponent {
             return InteractableComponent(runtime, entityManager, executor, inputEventListener)
         }
+
+        /**
+         * Public factory for creating an [InteractableComponent]. It enables access to raw input
+         * events.
+         *
+         * @param session [Session] to create the [InteractableComponent] in.
+         * @param executor Executor for invoking [InputEventListener].
+         * @param inputEventListener [InputEventListener] that accepts [InputEvent]s.
+         * @return [InteractableComponent] instance.
+         */
+        @JvmStatic
+        @Suppress("ExecutorRegistration")
+        public fun create(
+            session: Session,
+            executor: Executor,
+            inputEventListener: InputEventListener,
+        ): InteractableComponent =
+            InteractableComponent.create(
+                session.platformAdapter,
+                session.entityManager,
+                executor,
+                inputEventListener,
+            )
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/JxrPlatformAdapter.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/JxrPlatformAdapter.java
index f12c28e3..f0395d3 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/JxrPlatformAdapter.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/JxrPlatformAdapter.java
@@ -387,7 +387,7 @@
      *
      * <p>For security reasons, Z testing for the new activity is disabled, and the activity is
      * always drawn on top of the inherited environment. Because Z testing is disabled, the activity
-     * should not spatialize itself, and should not curve its panel too much either.
+     * should not spatialize itself.
      *
      * @param bundle the input bundle to set with the inherit full space mode environment flag.
      * @return the input {@code bundle} with the inherit full space mode flag set.
@@ -402,6 +402,11 @@
      * the same task, the ratio is not applied to the new activity. Also, while the activity is in
      * full space mode, the preference is temporarily removed.
      *
+     * <p>If the activity's current aspect ratio differs from the {@code preferredRatio}, the panel
+     * is automatically resized. This resizing preserves the panel's area. To avoid runtime
+     * resizing, consider specifying the desired aspect ratio in your {@code AndroidManifest.xml}.
+     * This ensures your activity launches with the preferred aspect ratio from the start.
+     *
      * @param activity the activity to set the preference.
      * @param preferredRatio the aspect ratio determined by taking the panel's width over its
      *     height. A value <= 0.0f means there are no preferences.
@@ -470,7 +475,7 @@
                     ScaleWithDistanceMode.DEFAULT,
                     ScaleWithDistanceMode.DMM,
                 })
-        public @interface ScaleWithDistanceMode {
+        @interface ScaleWithDistanceMode {
             int DEFAULT = 3;
             int DMM = 2;
         }
@@ -575,6 +580,32 @@
         void setFixedAspectRatio(float fixedAspectRatio);
 
         /**
+         * Sets whether or not content (including content of all child nodes) is auto-hidden during
+         * resizing. Defaults to true.
+         *
+         * @param autoHideContent Whether or not content is auto-hidden during resizing.
+         */
+        void setAutoHideContent(boolean autoHideContent);
+
+        /**
+         * Sets whether the size of the ResizableComponent is automatically updated to match during
+         * an ongoing resize (to match the proposed size as resize events are received). Defaults to
+         * true.
+         *
+         * @param autoUpdateSize Whether or not the size of the ResizableComponent is automatically
+         *     updated during resizing.
+         */
+        void setAutoUpdateSize(boolean autoUpdateSize);
+
+        /**
+         * Sets whether to force showing the resize overlay even when this entity is not being
+         * resized. Defaults to false.
+         *
+         * @param show Whether or not to force show the resize overlay.
+         */
+        void setForceShowResizeOverlay(boolean show);
+
+        /**
          * Adds the listener to the set of listeners that are invoked through the resize operation,
          * such as start, ongoing and end.
          *
@@ -602,9 +633,9 @@
 
     /** Component to enable pointer capture. */
     interface PointerCaptureComponent extends Component {
-        public static final int POINTER_CAPTURE_STATE_PAUSED = 0;
-        public static final int POINTER_CAPTURE_STATE_ACTIVE = 1;
-        public static final int POINTER_CAPTURE_STATE_STOPPED = 2;
+        int POINTER_CAPTURE_STATE_PAUSED = 0;
+        int POINTER_CAPTURE_STATE_ACTIVE = 1;
+        int POINTER_CAPTURE_STATE_STOPPED = 2;
 
         /** The possible states of pointer capture. */
         @RestrictTo(RestrictTo.Scope.LIBRARY)
@@ -615,10 +646,15 @@
                     POINTER_CAPTURE_STATE_ACTIVE,
                     POINTER_CAPTURE_STATE_STOPPED,
                 })
-        public @interface PointerCaptureState {}
+        @interface PointerCaptureState {}
 
         /** Functional interface for receiving updates about the state of pointer capture. */
         interface StateListener {
+            /**
+             * Called when the state of pointer capture changes.
+             *
+             * @param newState The new state of pointer capture.
+             */
             void onStateChanged(@PointerCaptureState int newState);
         }
     }
@@ -639,6 +675,11 @@
     @SuppressWarnings("AndroidJdkLibsChecker")
     @FunctionalInterface
     interface InputEventListener {
+        /**
+         * Called when an input event occurs.
+         *
+         * @param event The input event that occurred.
+         */
         void onInputEvent(@NonNull InputEvent event);
     }
 
@@ -646,14 +687,24 @@
     @SuppressWarnings("AndroidJdkLibsChecker")
     @FunctionalInterface
     interface MoveEventListener {
-        void onMoveEvent(@NonNull final MoveEvent event);
+        /**
+         * Called when a move event occurs.
+         *
+         * @param event The move event that occurred.
+         */
+        void onMoveEvent(@NonNull MoveEvent event);
     }
 
     /** Interface for ResizeEvent listener. */
     @SuppressWarnings("AndroidJdkLibsChecker")
     @FunctionalInterface
     interface ResizeEventListener {
-        void onResizeEvent(@NonNull final ResizeEvent event);
+        /**
+         * Called when a resize event occurs.
+         *
+         * @param event The resize event that occurred.
+         */
+        void onResizeEvent(@NonNull ResizeEvent event);
     }
 
     /** Interface for a SceneCore ActivityPose */
@@ -705,20 +756,20 @@
      * <p>The camera's field of view can be retrieved from this CameraViewActivityPose.
      */
     interface CameraViewActivityPose extends ActivityPose {
-        public static final int CAMERA_TYPE_UNKNOWN = 0;
-        public static final int CAMERA_TYPE_LEFT_EYE = 1;
-        public static final int CAMERA_TYPE_RIGHT_EYE = 2;
+        int CAMERA_TYPE_UNKNOWN = 0;
+        int CAMERA_TYPE_LEFT_EYE = 1;
+        int CAMERA_TYPE_RIGHT_EYE = 2;
 
         /** Returns the type of camera that this space represents. */
         @CameraType
-        public int getCameraType();
+        int getCameraType();
 
         /**
          * The angles (in radians) representing the sides of the view frustum. These are not
          * expected to change over the lifetime of the session but in rare cases may change due to
          * updated camera settings
          */
-        static class Fov {
+        class Fov {
 
             public final float angleLeft;
             public final float angleRight;
@@ -733,6 +784,7 @@
             }
         }
 
+        /** Returns the field of view for this camera. */
         @NonNull
         Fov getFov();
 
@@ -745,7 +797,7 @@
                     CAMERA_TYPE_LEFT_EYE,
                     CAMERA_TYPE_RIGHT_EYE,
                 })
-        public @interface CameraType {}
+        @interface CameraType {}
     }
 
     /**
@@ -790,21 +842,25 @@
          */
         void addChild(@NonNull Entity child);
 
-        // Sets the provided Entities to be children of the Entity.
+        /** Sets the provided Entities to be children of the Entity. */
         void addChildren(@NonNull List<Entity> children);
 
-        // Returns the parent entity for this Entity.
+        /** Returns the parent entity for this Entity. */
         @Nullable
         Entity getParent();
 
-        // Sets the parent Entity for this Entity. The child Entity's pose will be relative to the
-        // pose of its parent.
+        /**
+         * Sets the parent Entity for this Entity. The child Entity's pose will be relative to the
+         * pose of its parent.
+         *
+         * @param parent The parent entity.
+         */
         void setParent(@Nullable Entity parent);
 
-        // Sets context-text for this entity to be consumed by Accessibility systems.
+        /** Sets context-text for this entity to be consumed by Accessibility systems. */
         void setContentDescription(@NonNull String text);
 
-        // Returns the all child entities of this Entity.
+        /** Returns the all child entities of this Entity. */
         @NonNull
         List<Entity> getChildren();
 
@@ -976,7 +1032,7 @@
          * <p>This value can be overwritten by user-enabled or system-enabled passthrough and will
          * not always match the opacity value returned by [getPassthroughOpacityPreference].
          */
-        public float getCurrentPassthroughOpacity();
+        float getCurrentPassthroughOpacity();
 
         /**
          * Gets the last passthrough opacity requested through [setPassthroughOpacityPreference].
@@ -991,17 +1047,17 @@
          */
         @SuppressWarnings("AutoBoxing")
         @Nullable
-        public Float getPassthroughOpacityPreference();
+        Float getPassthroughOpacityPreference();
 
         /**
          * Notifies an application when the passthrough state changes, such as when the application
          * enters or exits passthrough or when the passthrough opacity changes. This [listener] will
          * be called on the Application's UI thread.
          */
-        public void addOnPassthroughOpacityChangedListener(@NonNull Consumer<Float> listener);
+        void addOnPassthroughOpacityChangedListener(@NonNull Consumer<Float> listener);
 
         /** Remove a listener previously added by [addOnPassthroughOpacityChangedListener]. */
-        public void removeOnPassthroughOpacityChangedListener(@NonNull Consumer<Float> listener);
+        void removeOnPassthroughOpacityChangedListener(@NonNull Consumer<Float> listener);
 
         /**
          * Returns true if the environment set by [setSpatialEnvironmentPreference] is active.
@@ -1119,6 +1175,7 @@
         @SuppressWarnings("AndroidJdkLibsChecker")
         @FunctionalInterface
         interface OnSpaceUpdatedListener {
+            /** Called by the system when the underlying space has changed. */
             void onSpaceUpdated();
         }
     }
@@ -1173,9 +1230,9 @@
         @RestrictTo(RestrictTo.Scope.LIBRARY)
         @Retention(RetentionPolicy.SOURCE)
         @IntDef({AnimationState.PLAYING, AnimationState.STOPPED})
-        public @interface AnimationState {
-            public static final int PLAYING = 0;
-            public static final int STOPPED = 1;
+        @interface AnimationState {
+            int PLAYING = 0;
+            int STOPPED = 1;
         }
 
         /**
@@ -1272,13 +1329,13 @@
         @RestrictTo(RestrictTo.Scope.LIBRARY)
         @Retention(RetentionPolicy.SOURCE)
         @IntDef({StereoMode.MONO, StereoMode.TOP_BOTTOM, StereoMode.SIDE_BY_SIDE})
-        public @interface StereoMode {
+        @interface StereoMode {
             // Each eye will see the entire surface (no separation)
-            public static final int MONO = 0;
+            int MONO = 0;
             // The [top, bottom] halves of the surface will map to [left, right] eyes
-            public static final int TOP_BOTTOM = 1;
+            int TOP_BOTTOM = 1;
             // The [left, right] halves of the surface will map to [left, right] eyes
-            public static final int SIDE_BY_SIDE = 2;
+            int SIDE_BY_SIDE = 2;
         }
 
         /**
@@ -1328,7 +1385,7 @@
 
     /** Interface for Anchor entity. */
     interface AnchorEntity extends SystemSpaceEntity {
-        /* Returns the current state of the anchor synchronously.*/
+        /** Returns the current state of the anchor synchronously. */
         @NonNull
         State getState();
 
@@ -1393,11 +1450,21 @@
 
         /** Interface for listening to Anchor state changes. */
         interface OnStateChangedListener {
+            /**
+             * Called when the state of the anchor changes.
+             *
+             * @param newState The new state of the anchor.
+             */
             void onStateChanged(@NonNull State newState);
         }
 
         /** Interface for listening to Anchor persist state changes. */
         interface PersistStateChangeListener {
+            /**
+             * Called when the persist state of the anchor changes.
+             *
+             * @param newPersistState The new persist state of the anchor.
+             */
             void onPersistStateChanged(@NonNull PersistState newPersistState);
         }
     }
@@ -1881,6 +1948,7 @@
                 })
         public @interface SpatialCapability {}
 
+        /** The set of capabilities enabled for the platform. */
         @SuppressWarnings("MutableBareField")
         @SpatialCapability
         public int capabilities;
@@ -1889,6 +1957,12 @@
             this.capabilities = capabilities;
         }
 
+        /**
+         * Returns true if the given capability is enabled.
+         *
+         * @param capability The capability to check.
+         * @return True if the capability is enabled, false otherwise.
+         */
         public boolean hasCapability(@SpatialCapability int capability) {
             return (capabilities & capability) != 0;
         }
@@ -1897,6 +1971,18 @@
     /** Interface for a SceneCore SoundPoolExtensionsWrapper. */
     interface SoundPoolExtensionsWrapper {
 
+        /**
+         * Plays a sound as a point source.
+         *
+         * @param soundPool The SoundPool to use.
+         * @param soundId The ID of the sound to play.
+         * @param attributes The PointSourceAttributes to use.
+         * @param volume The volume of the sound.
+         * @param priority The priority of the sound.
+         * @param loop Whether to loop the sound.
+         * @param rate The playback rate of the sound.
+         * @return The result of the play operation.
+         */
         int play(
                 @NonNull SoundPool soundPool,
                 int soundId,
@@ -1906,6 +1992,18 @@
                 int loop,
                 float rate);
 
+        /**
+         * Plays a sound as a sound field.
+         *
+         * @param soundPool The SoundPool to use.
+         * @param soundId The ID of the sound to play.
+         * @param attributes The SoundFieldAttributes to use.
+         * @param volume The volume of the sound.
+         * @param priority The priority of the sound.
+         * @param loop Whether to loop the sound.
+         * @param rate The playback rate of the sound.
+         * @return The result of the play operation.
+         */
         int play(
                 @NonNull SoundPool soundPool,
                 int soundId,
@@ -1915,6 +2013,13 @@
                 int loop,
                 float rate);
 
+        /**
+         * Returns the spatial source type of the sound.
+         *
+         * @param soundPool The SoundPool to use.
+         * @param streamId The stream ID of the sound.
+         * @return The spatial source type of the sound.
+         */
         @SpatializerConstants.SourceType
         int getSpatialSourceType(@NonNull SoundPool soundPool, int streamId);
     }
@@ -1922,18 +2027,51 @@
     /** Interface for a SceneCore AudioTrackExtensionsWrapper */
     interface AudioTrackExtensionsWrapper {
 
+        /**
+         * Returns the PointSourceAttributes of the AudioTrack.
+         *
+         * @param track The AudioTrack to get the PointSourceAttributes from.
+         * @return The PointSourceAttributes of the AudioTrack.
+         */
         @Nullable
         PointSourceAttributes getPointSourceAttributes(@NonNull AudioTrack track);
 
+        /**
+         * Returns the SoundFieldAttributes of the AudioTrack.
+         *
+         * @param track The AudioTrack to get the SoundFieldAttributes from.
+         * @return The SoundFieldAttributes of the AudioTrack.
+         */
         @Nullable
         SoundFieldAttributes getSoundFieldAttributes(@NonNull AudioTrack track);
 
+        /**
+         * Returns the spatial source type of the AudioTrack.
+         *
+         * @param track The AudioTrack to get the spatial source type from.
+         * @return The spatial source type of the AudioTrack.
+         */
+        @SpatializerConstants.SourceType
         int getSpatialSourceType(@NonNull AudioTrack track);
 
+        /**
+         * Sets the PointSourceAttributes of the AudioTrack.
+         *
+         * @param builder The AudioTrack.Builder to set the PointSourceAttributes on.
+         * @param attributes The PointSourceAttributes to set.
+         * @return The AudioTrack.Builder with the PointSourceAttributes set.
+         */
         @NonNull
         AudioTrack.Builder setPointSourceAttributes(
                 @NonNull AudioTrack.Builder builder, @NonNull PointSourceAttributes attributes);
 
+        /**
+         * Sets the SoundFieldAttributes of the AudioTrack.
+         *
+         * @param builder The AudioTrack.Builder to set the SoundFieldAttributes on.
+         * @param attributes The SoundFieldAttributes to set.
+         * @return The AudioTrack.Builder with the SoundFieldAttributes set.
+         */
         @NonNull
         AudioTrack.Builder setSoundFieldAttributes(
                 @NonNull AudioTrack.Builder builder, @NonNull SoundFieldAttributes attributes);
@@ -1942,39 +2080,51 @@
     /** Interface for a SceneCore MediaPlayerExtensionsWrapper */
     interface MediaPlayerExtensionsWrapper {
 
+        /**
+         * Sets the PointSourceAttributes of the MediaPlayer.
+         *
+         * @param mediaPlayer The MediaPlayer to set the PointSourceAttributes on.
+         * @param attributes The PointSourceAttributes to set.
+         */
         void setPointSourceAttributes(
                 @NonNull MediaPlayer mediaPlayer, @NonNull PointSourceAttributes attributes);
 
+        /**
+         * Sets the SoundFieldAttributes of the MediaPlayer.
+         *
+         * @param mediaPlayer The MediaPlayer to set the SoundFieldAttributes on.
+         * @param attributes The SoundFieldAttributes to set.
+         */
         void setSoundFieldAttributes(
                 @NonNull MediaPlayer mediaPlayer, @NonNull SoundFieldAttributes attributes);
     }
 
     /** Represents a SceneCore PointSourceAttributes */
     class PointSourceAttributes {
-        private final Entity entity;
+        private final Entity mEntity;
 
         public PointSourceAttributes(@NonNull Entity entity) {
-            this.entity = entity;
+            this.mEntity = entity;
         }
 
         /** Gets the SceneCore {@link Entity} for this instance. */
         @NonNull
         public Entity getEntity() {
-            return this.entity;
+            return this.mEntity;
         }
     }
 
     /** Represents a SceneCore SoundFieldAttributes */
     class SoundFieldAttributes {
 
-        @SpatializerConstants.AmbisonicsOrder private final int ambisonicsOrder;
+        @SpatializerConstants.AmbisonicsOrder private final int mAmbisonicsOrder;
 
         public SoundFieldAttributes(int ambisonicsOrder) {
-            this.ambisonicsOrder = ambisonicsOrder;
+            this.mAmbisonicsOrder = ambisonicsOrder;
         }
 
         public int getAmbisonicsOrder() {
-            return ambisonicsOrder;
+            return mAmbisonicsOrder;
         }
     }
 
@@ -2026,13 +2176,13 @@
 
     /** Returns a [SoundPoolExtensionsWrapper] instance. */
     @NonNull
-    public SoundPoolExtensionsWrapper getSoundPoolExtensionsWrapper();
+    SoundPoolExtensionsWrapper getSoundPoolExtensionsWrapper();
 
     /** Returns an [AudioTrackExtensionssWrapper] instance. */
     @NonNull
-    public AudioTrackExtensionsWrapper getAudioTrackExtensionsWrapper();
+    AudioTrackExtensionsWrapper getAudioTrackExtensionsWrapper();
 
     /** Returns a [MediaPlayerExtensionsWrapper] instance. */
     @NonNull
-    public MediaPlayerExtensionsWrapper getMediaPlayerExtensionsWrapper();
+    MediaPlayerExtensionsWrapper getMediaPlayerExtensionsWrapper();
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/Model.kt b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/Model.kt
index 3d6459e..481b5b3 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/Model.kt
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/Model.kt
@@ -42,8 +42,8 @@
             message = "This function is deprecated, use createAsync() instead",
             replaceWith = ReplaceWith("createAsync()"),
         )
-        internal fun create(runtime: JxrPlatformAdapter, name: String): GltfModel {
-            val gltfResourceFuture = runtime.loadGltfByAssetName(name)
+        internal fun create(platformAdapter: JxrPlatformAdapter, name: String): GltfModel {
+            val gltfResourceFuture = platformAdapter.loadGltfByAssetName(name)
             // TODO: b/320858652 - Implement async loading of GltfModel.
             return GltfModel(gltfResourceFuture!!.get())
         }
@@ -54,10 +54,10 @@
         // warning, however, we get a build error - go/bugpattern/RestrictTo.
         @SuppressWarnings("RestrictTo")
         internal fun createAsync(
-            runtime: JxrPlatformAdapter,
+            platformAdapter: JxrPlatformAdapter,
             name: String,
         ): ListenableFuture<GltfModel> {
-            val gltfResourceFuture = runtime.loadGltfByAssetNameSplitEngine(name)
+            val gltfResourceFuture = platformAdapter.loadGltfByAssetNameSplitEngine(name)
             val modelFuture = ResolvableFuture.create<GltfModel>()
 
             // TODO: b/375070346 - remove this `!!` when we're sure the future is non-null.
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/MovableComponent.kt b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/MovableComponent.kt
index 9e3bde9..b8d28a9 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/MovableComponent.kt
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/MovableComponent.kt
@@ -32,7 +32,7 @@
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 public class MovableComponent
 private constructor(
-    private val runtime: JxrPlatformAdapter,
+    private val platformAdapter: JxrPlatformAdapter,
     private val entityManager: EntityManager,
     private val systemMovable: Boolean = true,
     private val scaleInZ: Boolean = true,
@@ -40,10 +40,10 @@
     private val shouldDisposeParentAnchor: Boolean = true,
 ) : Component {
     private val rtMovableComponent by lazy {
-        runtime.createMovableComponent(
+        platformAdapter.createMovableComponent(
             systemMovable,
             scaleInZ,
-            anchorPlacement.toRtAnchorPlacement(runtime),
+            anchorPlacement.toRtAnchorPlacement(platformAdapter),
             shouldDisposeParentAnchor,
         )
     }
@@ -136,6 +136,18 @@
     }
 
     /**
+     * Adds a listener to the set of active listeners for the move events. The listener will be
+     * invoked regardless of whether the entity is being moved by the system or the user.
+     *
+     * <p>The listener is invoked on the main thread.
+     *
+     * @param moveListener The move event listener to set.
+     */
+    public fun addMoveListener(moveListener: MoveListener) {
+        addMoveListener(HandlerExecutor.mainThreadExecutor, moveListener)
+    }
+
+    /**
      * Removes a listener from the set of active listeners for the move events.
      *
      * @param moveListener The move event listener to remove.
@@ -147,12 +159,12 @@
         }
     }
 
-    internal companion object {
+    public companion object {
         private val kDimensionsOneMeter = Dimensions(1f, 1f, 1f)
 
         /** Factory function for creating a MovableComponent. */
         internal fun create(
-            runtime: JxrPlatformAdapter,
+            platformAdapter: JxrPlatformAdapter,
             entityManager: EntityManager,
             systemMovable: Boolean = true,
             scaleInZ: Boolean = true,
@@ -160,7 +172,7 @@
             shouldDisposeParentAnchor: Boolean = true,
         ): MovableComponent {
             return MovableComponent(
-                runtime,
+                platformAdapter,
                 entityManager,
                 systemMovable,
                 scaleInZ,
@@ -168,5 +180,46 @@
                 shouldDisposeParentAnchor,
             )
         }
+
+        /**
+         * Public factory function for creating a MovableComponent. This component can be attached
+         * to a single instance of any non-Anchor Entity.
+         *
+         * When attached, this Component will enable the user to translate the Entity by pointing
+         * and dragging on it.
+         *
+         * @param session The [Session] instance.
+         * @param systemMovable A [Boolean] which causes the system to automatically apply transform
+         *   updates to the entity in response to user interaction.
+         * @param scaleInZ A [Boolean] which tells the system to update the scale of the Entity as
+         *   the user moves it closer and further away. This is mostly useful for Panel
+         *   auto-rescaling with Distance
+         * @param anchorPlacement A Set containing different [AnchorPlacement] for how to anchor the
+         *   [Entity] movable component. If this is not empty the movement semantics will be
+         *   slightly different from the system as it will add the ability to anchor to nearby
+         *   planes.
+         * @param shouldDisposeParentAnchor A [Boolean], which if set to true, when an entity is
+         *   moved off of an [AnchorEntity] that was created by the underlying [MovableComponent],
+         *   and the [AnchorEntity] has no other children, the AnchorEntity will be disposed, and
+         *   the underlying Anchor will be detached.
+         * @return [MovableComponent] instance.
+         */
+        @JvmOverloads
+        @JvmStatic
+        public fun create(
+            session: Session,
+            systemMovable: Boolean = true,
+            scaleInZ: Boolean = true,
+            anchorPlacement: Set<AnchorPlacement> = emptySet(),
+            shouldDisposeParentAnchor: Boolean = true,
+        ): MovableComponent =
+            MovableComponent.create(
+                platformAdapter = session.platformAdapter,
+                entityManager = session.entityManager,
+                systemMovable = systemMovable,
+                scaleInZ = scaleInZ,
+                anchorPlacement = anchorPlacement,
+                shouldDisposeParentAnchor = shouldDisposeParentAnchor,
+            )
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/PointerCaptureComponent.kt b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/PointerCaptureComponent.kt
index 48b1150..b7cfdcc8 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/PointerCaptureComponent.kt
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/PointerCaptureComponent.kt
@@ -32,7 +32,7 @@
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 public class PointerCaptureComponent
 private constructor(
-    private val runtime: JxrPlatformAdapter,
+    private val platformAdapter: JxrPlatformAdapter,
     private val entityManager: EntityManager,
     private val executor: Executor,
     private val stateListener: StateListener,
@@ -63,7 +63,11 @@
         }
 
     private val rtComponent by lazy {
-        runtime.createPointerCaptureComponent(executor, rtStateListener, rtInputEventListener)
+        platformAdapter.createPointerCaptureComponent(
+            executor,
+            rtStateListener,
+            rtInputEventListener
+        )
     }
 
     @RestrictTo(RestrictTo.Scope.LIBRARY)
@@ -123,7 +127,7 @@
             inputListener: InputEventListener,
         ): PointerCaptureComponent =
             PointerCaptureComponent(
-                session.runtime,
+                session.platformAdapter,
                 session.entityManager,
                 executor,
                 stateListener,
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/ResizableComponent.kt b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/ResizableComponent.kt
index def8015..bd1abf150 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/ResizableComponent.kt
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/ResizableComponent.kt
@@ -31,7 +31,7 @@
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 public class ResizableComponent
 private constructor(
-    private val runtime: JxrPlatformAdapter,
+    private val platformAdapter: JxrPlatformAdapter,
     minimumSize: Dimensions,
     maximumSize: Dimensions,
 ) : Component {
@@ -97,8 +97,51 @@
             }
         }
 
+    /**
+     * Whether the content of the entity (and all child entities) should be automatically hidden
+     * while it is being resized.
+     */
+    @get:Suppress("GetterSetterNames")
+    public var autoHideContent: Boolean = true
+        set(value) {
+            if (field != value) {
+                field = value
+                rtResizableComponent.setAutoHideContent(value)
+            }
+        }
+
+    /**
+     * Whether the size of the ResizableComponent should be automatically updated to match during an
+     * ongoing resize (to match the proposed size as resize events are received).
+     */
+    @get:Suppress("GetterSetterNames")
+    public var autoUpdateSize: Boolean = true
+        set(value) {
+            if (field != value) {
+                field = value
+                rtResizableComponent.setAutoUpdateSize(value)
+            }
+        }
+
+    /**
+     * Whether the resize overlay should be shown even if the entity is not being resized.
+     *
+     * This is useful for resizing multiple panels at once.
+     */
+    @get:Suppress("GetterSetterNames")
+    public var forceShowResizeOverlay: Boolean = false
+        set(value) {
+            if (field != value) {
+                field = value
+                rtResizableComponent.setForceShowResizeOverlay(value)
+            }
+        }
+
     private val rtResizableComponent by lazy {
-        runtime.createResizableComponent(minimumSize.toRtDimensions(), maximumSize.toRtDimensions())
+        platformAdapter.createResizableComponent(
+            minimumSize.toRtDimensions(),
+            maximumSize.toRtDimensions(),
+        )
     }
 
     private var entity: Entity? = null
@@ -162,6 +205,18 @@
     }
 
     /**
+     * Adds the listener to the set of listeners that are invoked through the resize operation, such
+     * as start, ongoing and end.
+     *
+     * The listener is invoked on the main thread.
+     *
+     * @param resizeListener The listener to be invoked when a resize event occurs.
+     */
+    public fun addResizeListener(resizeListener: ResizeListener) {
+        addResizeListener(HandlerExecutor.mainThreadExecutor, resizeListener)
+    }
+
+    /**
      * Removes a listener from the set listening to resize events.
      *
      * @param resizeListener The listener to be removed.
@@ -173,7 +228,7 @@
         }
     }
 
-    internal companion object {
+    public companion object {
         private val kDimensionsOneMeter = Dimensions(1f, 1f, 1f)
         /** Defaults min and max sizes in meters. */
         internal val kMinimumSize: Dimensions = Dimensions(0f, 0f, 0f)
@@ -181,11 +236,38 @@
 
         /** Factory function for creating [ResizableComponent] instance. */
         internal fun create(
-            runtime: JxrPlatformAdapter,
+            platformAdapter: JxrPlatformAdapter,
             minimumSize: Dimensions = kMinimumSize,
             maximumSize: Dimensions = kMaximumSize,
         ): ResizableComponent {
-            return ResizableComponent(runtime, minimumSize, maximumSize)
+            return ResizableComponent(platformAdapter, minimumSize, maximumSize)
         }
+
+        /**
+         * Public factory function for creating a ResizableComponent. This component can be attached
+         * to a single instance of any non-Anchor Entity.
+         *
+         * When attached, this Component will enable the user to resize the Entity by dragging along
+         * the boundaries of the interaction highlight.
+         *
+         * @param session The Session to create the ResizableComponent in.
+         * @param minimumSize A lower bound for the User's resize actions, in meters. This value is
+         *   used to set constraints on how small the user can resize the bounding box of the entity
+         *   down to. The size of the content inside that bounding box is fully controlled by the
+         *   application. The default value for this param is 0 meters.
+         * @param maximumSize An upper bound for the User's resize actions, in meters. This value is
+         *   used to set constraints on how large the user can resize the bounding box of the entity
+         *   up to. The size of the content inside that bounding box is fully controlled by the
+         *   application. The default value for this param is 10 meters.
+         * @return [ResizableComponent] instance.
+         */
+        @JvmOverloads
+        @JvmStatic
+        public fun create(
+            session: Session,
+            minimumSize: Dimensions = ResizableComponent.kMinimumSize,
+            maximumSize: Dimensions = ResizableComponent.kMaximumSize,
+        ): ResizableComponent =
+            ResizableComponent.create(session.platformAdapter, minimumSize, maximumSize)
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/Session.kt b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/Session.kt
index 9c77976..2f03fc40 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/Session.kt
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/Session.kt
@@ -54,7 +54,7 @@
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 public class Session(
     public val activity: Activity,
-    public val runtime: JxrPlatformAdapter,
+    public val platformAdapter: JxrPlatformAdapter,
     public val spatialEnvironment: SpatialEnvironment,
 ) {
     internal val entityManager by lazy { EntityManager() }
@@ -69,10 +69,10 @@
      *
      * The ActivitySpace is created automatically when the Session is created.
      */
-    public val activitySpace: ActivitySpace = ActivitySpace.create(runtime, entityManager)
+    public val activitySpace: ActivitySpace = ActivitySpace.create(platformAdapter, entityManager)
 
     /** The SpatialUser contains information about the user. */
-    public val spatialUser: SpatialUser = SpatialUser.create(runtime)
+    public val spatialUser: SpatialUser = SpatialUser.create(platformAdapter)
 
     /**
      * A spatialized PanelEntity associated with the "main window" for the Activity. When in
@@ -81,18 +81,18 @@
      * If called multiple times, this will return the same PanelEntity.
      */
     public val mainPanelEntity: PanelEntity =
-        PanelEntity.createMainPanelEntity(runtime, entityManager)
+        PanelEntity.createMainPanelEntity(platformAdapter, entityManager)
 
     /**
      * The PerceptionSpace represents the origin of the space in which the ARCore for XR API
      * provides tracking info. The transformations provided by the PerceptionSpace are only valid
      * for the call frame, as the transformation can be changed by the system at any time.
      */
-    public val perceptionSpace: PerceptionSpace = PerceptionSpace.create(runtime)
+    public val perceptionSpace: PerceptionSpace = PerceptionSpace.create(platformAdapter)
 
     // TODO: 378706624 - Remove this method once we have a better way to handle the root entity.
     public val activitySpaceRoot: Entity by lazy {
-        entityManager.getEntityForRtEntity(runtime.activitySpaceRootImpl)!!
+        entityManager.getEntityForRtEntity(platformAdapter.activitySpaceRootImpl)!!
     }
 
     public companion object {
@@ -107,10 +107,12 @@
          * For our Alpha release, we just directly instantiate the Android XR PlatformAdapter.
          */
         // TODO(b/326748782): Change the returned Session here to be nullable or asynchronous.
-        // TODO: b/372299691 - Rename the runtime parameter to platformAdapter.
         @JvmStatic
         @JvmOverloads
-        public fun create(activity: Activity, runtime: JxrPlatformAdapter? = null): Session {
+        public fun create(
+            activity: Activity,
+            platformAdapter: JxrPlatformAdapter? = null
+        ): Session {
             // TODO(bhavsar): Rethink moving this check when integration with Spatial Activity
             // happens.
             if (
@@ -128,9 +130,9 @@
             return activitySessionMap.computeIfAbsent(activity) {
                 Log.i(TAG, "Creating session for activity $activity")
                 val session =
-                    when (runtime) {
+                    when (platformAdapter) {
                         null -> {
-                            val runtimeImpl =
+                            val platformAdapterImpl =
                                 JxrPlatformAdapterAxr.create(
                                     activity,
                                     Executors.newSingleThreadScheduledExecutor(
@@ -141,9 +143,14 @@
                                         }
                                     ),
                                 )
-                            Session(activity, runtimeImpl, SpatialEnvironment(runtimeImpl))
+                            Session(
+                                activity,
+                                platformAdapterImpl,
+                                SpatialEnvironment(platformAdapterImpl)
+                            )
                         }
-                        else -> Session(activity, runtime, SpatialEnvironment(runtime))
+                        else ->
+                            Session(activity, platformAdapter, SpatialEnvironment(platformAdapter))
                     }
                 activity.registerActivityLifecycleCallbacks(
                     object : ActivityLifecycleCallbacks {
@@ -155,11 +162,11 @@
                         override fun onActivityStarted(activity: Activity) {}
 
                         override fun onActivityResumed(activity: Activity) {
-                            session.runtime.startRenderer()
+                            session.platformAdapter.startRenderer()
                         }
 
                         override fun onActivityPaused(activity: Activity) {
-                            session.runtime.stopRenderer()
+                            session.platformAdapter.stopRenderer()
                         }
 
                         override fun onActivityStopped(activity: Activity) {}
@@ -172,7 +179,7 @@
                         override fun onActivityDestroyed(activity: Activity) {
                             activitySessionMap.remove(activity)
                             session.entityManager.clear()
-                            session.runtime.dispose()
+                            session.platformAdapter.dispose()
                         }
                     }
                 )
@@ -196,7 +203,7 @@
      * should be called again to get the latest set of capabilities.
      */
     public fun getSpatialCapabilities(): SpatialCapabilities =
-        runtime.spatialCapabilities.toSpatialCapabilities()
+        platformAdapter.spatialCapabilities.toSpatialCapabilities()
 
     /**
      * Adds the given [Consumer] as a listener to be invoked when this Session's current
@@ -216,7 +223,7 @@
         callbackExecutor: Executor,
         listener: Consumer<SpatialCapabilities>,
     ): Unit {
-        // wrap the client's listener in a callback that receives & converts the runtime
+        // wrap the client's listener in a callback that receives & converts the platformAdapter
         // SpatialCapabilities type.
         val rtListener: Consumer<RtSpatialCapabilities> =
             Consumer<RtSpatialCapabilities> { rtCaps: RtSpatialCapabilities ->
@@ -225,7 +232,7 @@
         spatialCapabilitiesListeners.compute(
             listener,
             { _, _ ->
-                runtime.addSpatialCapabilitiesChangedListener(callbackExecutor, rtListener)
+                platformAdapter.addSpatialCapabilitiesChangedListener(callbackExecutor, rtListener)
                 rtListener
             },
         )
@@ -242,25 +249,13 @@
         spatialCapabilitiesListeners.computeIfPresent(
             listener,
             { _, rtListener ->
-                runtime.removeSpatialCapabilitiesChangedListener(rtListener)
+                platformAdapter.removeSpatialCapabilitiesChangedListener(rtListener)
                 null
             },
         )
     }
 
     /**
-     * If the primary Activity for this Session has focus, causes it to be placed in FullSpace Mode.
-     * Otherwise, this call does nothing.
-     */
-    public fun requestFullSpaceMode(): Unit = runtime.requestFullSpaceMode()
-
-    /**
-     * If the primary Activity for this Session has focus, causes it to be placed in HomeSpace Mode.
-     * Otherwise, this call does nothing.
-     */
-    public fun requestHomeSpaceMode(): Unit = runtime.requestHomeSpaceMode()
-
-    /**
      * Public factory function for a [GltfModel], where the glTF is asynchronously loaded.
      *
      * This method must be called from the main thread.
@@ -275,7 +270,7 @@
      */
     @MainThread
     public fun createGltfResourceAsync(name: String): ListenableFuture<GltfModel> {
-        return GltfModel.createAsync(runtime, name)
+        return GltfModel.createAsync(platformAdapter, name)
     }
 
     /**
@@ -284,7 +279,8 @@
      * @param name The path for an EXR image to be loaded
      * @return an EXRImage instance.
      */
-    public fun createExrImageResource(name: String): ExrImage = ExrImage.create(runtime, name)
+    public fun createExrImageResource(name: String): ExrImage =
+        ExrImage.create(platformAdapter, name)
 
     /**
      * Public factory function for a [GltfModelEntity].
@@ -300,29 +296,7 @@
     @JvmOverloads
     @MainThread
     public fun createGltfEntity(model: GltfModel, pose: Pose = Pose.Identity): GltfModelEntity =
-        GltfModelEntity.create(runtime, entityManager, model, pose)
-
-    /**
-     * Public factory function for a StereoSurfaceEntity.
-     *
-     * This method must be called from the main thread.
-     * https://developer.android.com/guide/components/processes-and-threads
-     *
-     * @param stereoMode Stereo mode for the surface.
-     * @param dimensions Dimensions for the surface.
-     * @param pose Pose of this entity relative to its parent, default value is Identity.
-     * @return a StereoSurfaceEntity instance
-     */
-    @MainThread
-    @JvmOverloads
-    public fun createStereoSurfaceEntity(
-        @StereoSurfaceEntity.StereoModeValue
-        stereoMode: Int = StereoSurfaceEntity.StereoMode.SIDE_BY_SIDE,
-        dimensions: Dimensions = Dimensions(1.0f, 1.0f, 1.0f),
-        pose: Pose = Pose.Identity,
-    ): StereoSurfaceEntity {
-        return StereoSurfaceEntity.create(runtime, entityManager, stereoMode, dimensions, pose)
-    }
+        GltfModelEntity.create(platformAdapter, entityManager, model, pose)
 
     // TODO(b/352629832): Update surfaceDimensionsPx to be a PixelDimensions
     /**
@@ -344,7 +318,7 @@
         pose: Pose = Pose.Identity,
     ): PanelEntity =
         PanelEntity.create(
-            runtime,
+            platformAdapter,
             entityManager,
             view,
             surfaceDimensionsPx,
@@ -378,7 +352,7 @@
         pose: Pose = Pose.Identity,
     ): ActivityPanelEntity =
         ActivityPanelEntity.create(
-            runtime,
+            platformAdapter,
             entityManager,
             PixelDimensions(windowBoundsPx.width(), windowBoundsPx.height()),
             name,
@@ -411,12 +385,12 @@
         timeout: Duration = Duration.ZERO,
     ): AnchorEntity {
         return AnchorEntity.create(
-            runtime,
+            platformAdapter,
             entityManager,
             bounds,
             planeType,
             planeSemantic,
-            timeout
+            timeout,
         )
     }
 
@@ -426,7 +400,7 @@
      * @param anchor The PerceptionAnchor to use for this AnchorEntity.
      */
     public fun createAnchorEntity(anchor: Anchor): AnchorEntity {
-        return AnchorEntity.create(runtime, entityManager, anchor)
+        return AnchorEntity.create(platformAdapter, entityManager, anchor)
     }
 
     /**
@@ -436,7 +410,7 @@
      * @param uuid UUID of the anchor to unpersist.
      */
     public fun unpersistAnchor(uuid: UUID): Boolean {
-        return runtime.unpersistAnchor(uuid)
+        return platformAdapter.unpersistAnchor(uuid)
     }
 
     /**
@@ -449,7 +423,7 @@
      */
     @JvmOverloads
     public fun createEntity(name: String, pose: Pose = Pose.Identity): Entity =
-        ContentlessEntity.create(runtime, entityManager, name, pose)
+        ContentlessEntity.create(platformAdapter, entityManager, name, pose)
 
     /**
      * Public factory function for a persisted AnchorEntity using UUID. Note that the system keeps a
@@ -460,85 +434,10 @@
      * @return a persisted AnchorEntity instance.
      */
     public fun createPersistedAnchorEntity(uuid: UUID): AnchorEntity {
-        return AnchorEntity.create(runtime, entityManager, uuid)
+        return AnchorEntity.create(platformAdapter, entityManager, uuid)
     }
 
     /**
-     * Public factory for creating an [InteractableComponent]. It enables access to raw input
-     * events.
-     *
-     * @param executor Executor for invoking [InputEventListener].
-     * @param inputEventListener [InputEventListener] that accepts [InputEvent]s.
-     * @return [InteractableComponent] instance.
-     */
-    @Suppress("ExecutorRegistration")
-    public fun createInteractableComponent(
-        executor: Executor,
-        inputEventListener: InputEventListener,
-    ): InteractableComponent =
-        InteractableComponent.create(runtime, entityManager, executor, inputEventListener)
-
-    /**
-     * Public factory function for creating a MovableComponent. This component can be attached to a
-     * single instance of any non-Anchor Entity.
-     *
-     * When attached, this Component will enable the user to translate the Entity by pointing and
-     * dragging on it.
-     *
-     * @param systemMovable A [Boolean] which causes the system to automatically apply transform
-     *   updates to the entity in response to user interaction.
-     * @param scaleInZ A [Boolean] which tells the system to update the scale of the Entity as the
-     *   user moves it closer and further away. This is mostly useful for Panel auto-rescaling with
-     *   Distance
-     * @param anchorPlacement A Set containing different [AnchorPlacement] for how to anchor the
-     *   [Entity] movable component. If this is not empty the movement semantics will be slightly
-     *   different from the system as it will add the ability to anchor to nearby planes.
-     * @param shouldDisposeParentAnchor A [Boolean], which if set to true, when an entity is moved
-     *   off of an [AnchorEntity] that was created by the underlying [MovableComponent], and the
-     *   [AnchorEntity] has no other children, the AnchorEntity will be disposed, and the underlying
-     *   Anchor will be detached.
-     * @return [MovableComponent] instance.
-     */
-    @JvmOverloads
-    public fun createMovableComponent(
-        systemMovable: Boolean = true,
-        scaleInZ: Boolean = true,
-        anchorPlacement: Set<AnchorPlacement> = emptySet(),
-        shouldDisposeParentAnchor: Boolean = true,
-    ): MovableComponent =
-        MovableComponent.create(
-            runtime = runtime,
-            entityManager = entityManager,
-            systemMovable = systemMovable,
-            scaleInZ = scaleInZ,
-            anchorPlacement = anchorPlacement,
-            shouldDisposeParentAnchor = shouldDisposeParentAnchor,
-        )
-
-    /**
-     * Public factory function for creating a ResizableComponent. This component can be attached to
-     * a single instance of any non-Anchor Entity.
-     *
-     * When attached, this Component will enable the user to resize the Entity by dragging along the
-     * boundaries of the interaction highlight.
-     *
-     * @param minimumSize A lower bound for the User's resize actions, in meters. This value is used
-     *   to set constraints on how small the user can resize the bounding box of the entity down to.
-     *   The size of the content inside that bounding box is fully controlled by the application.
-     *   The default value for this param is 0 meters.
-     * @param maximumSize An upper bound for the User's resize actions, in meters. This value is
-     *   used to set constraints on how large the user can resize the bounding box of the entity up
-     *   to. The size of the content inside that bounding box is fully controlled by the
-     *   application. The default value for this param is 10 meters.
-     * @return [ResizableComponent] instance.
-     */
-    @JvmOverloads
-    public fun createResizableComponent(
-        minimumSize: Dimensions = ResizableComponent.kMinimumSize,
-        maximumSize: Dimensions = ResizableComponent.kMaximumSize,
-    ): ResizableComponent = ResizableComponent.create(runtime, minimumSize, maximumSize)
-
-    /**
      * Sets the full space mode flag to the given [android.os.Bundle].
      *
      * The [android.os.Bundle] then could be used to launch an [android.app.Activity] with
@@ -557,7 +456,7 @@
      * @param bundle the input bundle to set with the full space mode flag.
      * @return the input bundle with the full space mode flag set.
      */
-    public fun setFullSpaceMode(bundle: Bundle): Bundle = runtime.setFullSpaceMode(bundle)
+    public fun setFullSpaceMode(bundle: Bundle): Bundle = platformAdapter.setFullSpaceMode(bundle)
 
     /**
      * Sets the inherit full space mode environvment flag to the given [android.os.Bundle].
@@ -586,13 +485,13 @@
      *
      * For security reasons, Z testing for the new activity is disabled, and the activity is always
      * drawn on top of the inherited environment. Because Z testing is disabled, the activity should
-     * not spatialize itself, and should not curve its panel too much either.
+     * not spatialize itself.
      *
      * @param bundle the input bundle to set with the inherit full space mode environment flag.
      * @return the input bundle with the inherit full space mode flag set.
      */
     public fun setFullSpaceModeWithEnvironmentInherited(bundle: Bundle): Bundle =
-        runtime.setFullSpaceModeWithEnvironmentInherited(bundle)
+        platformAdapter.setFullSpaceModeWithEnvironmentInherited(bundle)
 
     /**
      * Sets a preferred main panel aspect ratio for home space mode.
@@ -601,12 +500,17 @@
      * same task, the ratio is not applied to the new activity. Also, while the activity is in full
      * space mode, the preference is temporarily removed.
      *
+     * If the activity's current aspect ratio differs from the preferredRatio, the panel is
+     * automatically resized. This resizing preserves the panel's area. To avoid runtime resizing,
+     * consider specifying the desired aspect ratio in your AndroidManifest.xml. This ensures your
+     * activity launches with the preferred aspect ratio from the start.
+     *
      * @param activity the activity to set the preference.
      * @param preferredRatio the aspect ratio determined by taking the panel's width over its
      *   height. A value <= 0.0f means there are no preferences.
      */
     public fun setPreferredAspectRatio(activity: Activity, preferredRatio: Float): Unit =
-        runtime.setPreferredAspectRatio(activity, preferredRatio)
+        platformAdapter.setPreferredAspectRatio(activity, preferredRatio)
 
     /**
      * Returns all [Entity]s of the given type or its subtypes.
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialAudioTrack.kt b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialAudioTrack.kt
index 6ce3da5..f699c94 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialAudioTrack.kt
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialAudioTrack.kt
@@ -37,7 +37,7 @@
         @JvmStatic
         @SpatializerConstants.SourceType
         public fun getSpatialSourceType(session: Session, track: AudioTrack): Int {
-            return session.runtime.audioTrackExtensionsWrapper
+            return session.platformAdapter.audioTrackExtensionsWrapper
                 .getSpatialSourceType(track)
                 .sourceTypeToJxr()
         }
@@ -55,7 +55,7 @@
             track: AudioTrack,
         ): PointSourceAttributes? {
             val rtAttributes =
-                session.runtime.audioTrackExtensionsWrapper.getPointSourceAttributes(track)
+                session.platformAdapter.audioTrackExtensionsWrapper.getPointSourceAttributes(track)
             return rtAttributes?.toPointSourceAttributes(session)
         }
 
@@ -72,7 +72,7 @@
             track: AudioTrack
         ): SoundFieldAttributes? {
             val rtAttributes =
-                session.runtime.audioTrackExtensionsWrapper.getSoundFieldAttributes(track)
+                session.platformAdapter.audioTrackExtensionsWrapper.getSoundFieldAttributes(track)
             return rtAttributes?.toSoundFieldAttributes()
         }
     }
@@ -100,7 +100,7 @@
             attributes: PointSourceAttributes,
         ): AudioTrack.Builder {
 
-            return session.runtime.audioTrackExtensionsWrapper.setPointSourceAttributes(
+            return session.platformAdapter.audioTrackExtensionsWrapper.setPointSourceAttributes(
                 builder,
                 attributes.rtPointSourceAttributes,
             )
@@ -121,7 +121,7 @@
             builder: AudioTrack.Builder,
             attributes: SoundFieldAttributes,
         ): AudioTrack.Builder {
-            return session.runtime.audioTrackExtensionsWrapper.setSoundFieldAttributes(
+            return session.platformAdapter.audioTrackExtensionsWrapper.setSoundFieldAttributes(
                 builder,
                 attributes.rtSoundFieldAttributes,
             )
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialEnvironment.kt b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialEnvironment.kt
index b6fd2d7..d1b42b7 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialEnvironment.kt
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialEnvironment.kt
@@ -50,7 +50,7 @@
  * changed.
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
-public class SpatialEnvironment(runtime: JxrPlatformAdapter) {
+public class SpatialEnvironment(private val runtime: JxrPlatformAdapter) {
 
     private val TAG = "SpatialEnvironment"
 
@@ -385,6 +385,18 @@
         rtEnvironment.removeOnSpatialEnvironmentChangedListener(listener)
     }
 
+    /**
+     * If the primary Activity in a [Session] spatial environment has focus, causes the [Session] to
+     * be placed in FullSpace Mode. Otherwise, this call does nothing.
+     */
+    public fun requestFullSpaceMode(): Unit = runtime.requestFullSpaceMode()
+
+    /**
+     * If the primary Activity in a [Session] spatial environment has focus, causes the [Session] to
+     * be placed in HomeSpace Mode. Otherwise, this call does nothing.
+     */
+    public fun requestHomeSpaceMode(): Unit = runtime.requestHomeSpaceMode()
+
     /** Result values for calls to [setPassthroughOpacityPreference] */
     public sealed class SetPassthroughOpacityPreferenceResult()
 
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialMediaPlayer.kt b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialMediaPlayer.kt
index 66d3432..85df55b 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialMediaPlayer.kt
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialMediaPlayer.kt
@@ -41,7 +41,7 @@
             mediaPlayer: MediaPlayer,
             attributes: PointSourceAttributes,
         ) {
-            session.runtime.mediaPlayerExtensionsWrapper.setPointSourceAttributes(
+            session.platformAdapter.mediaPlayerExtensionsWrapper.setPointSourceAttributes(
                 mediaPlayer,
                 attributes.rtPointSourceAttributes,
             )
@@ -64,7 +64,7 @@
             mediaPlayer: MediaPlayer,
             attributes: SoundFieldAttributes,
         ) {
-            session.runtime.mediaPlayerExtensionsWrapper.setSoundFieldAttributes(
+            session.platformAdapter.mediaPlayerExtensionsWrapper.setSoundFieldAttributes(
                 mediaPlayer,
                 attributes.rtSoundFieldAttributes,
             )
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialSoundPool.kt b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialSoundPool.kt
index f0d4de4..adaa8b3 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialSoundPool.kt
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/SpatialSoundPool.kt
@@ -52,7 +52,7 @@
             rate: Float,
         ): Int {
 
-            return session.runtime.soundPoolExtensionsWrapper.play(
+            return session.platformAdapter.soundPoolExtensionsWrapper.play(
                 soundPool,
                 soundID,
                 attributes.rtPointSourceAttributes,
@@ -88,7 +88,7 @@
             rate: Float,
         ): Int {
 
-            return session.runtime.soundPoolExtensionsWrapper.play(
+            return session.platformAdapter.soundPoolExtensionsWrapper.play(
                 soundPool,
                 soundID,
                 attributes.rtSoundFieldAttributes,
@@ -113,7 +113,7 @@
             soundPool: SoundPool,
             streamId: Int
         ): Int {
-            return session.runtime.soundPoolExtensionsWrapper
+            return session.platformAdapter.soundPoolExtensionsWrapper
                 .getSpatialSourceType(soundPool, streamId)
                 .sourceTypeToJxr()
         }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/common/BaseEntity.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/common/BaseEntity.java
index c2584bc..8fa2041 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/common/BaseEntity.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/common/BaseEntity.java
@@ -32,27 +32,27 @@
 /** Implementation of a subset of core RealityCore Entity functionality. */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 public abstract class BaseEntity extends BaseActivityPose implements Entity {
-    private final List<Entity> children = new ArrayList<>();
-    private final List<Component> componentList = new ArrayList<>();
-    private BaseEntity parent;
-    private Pose pose = new Pose();
-    private Vector3 scale = new Vector3(1.0f, 1.0f, 1.0f);
-    private float alpha = 1.0f;
-    private boolean hidden = false;
+    private final List<Entity> mChildren = new ArrayList<>();
+    private final List<Component> mComponentList = new ArrayList<>();
+    private BaseEntity mParent;
+    private Pose mPose = new Pose();
+    private Vector3 mScale = new Vector3(1.0f, 1.0f, 1.0f);
+    private float mAlpha = 1.0f;
+    private boolean mHidden = false;
 
     protected void addChildInternal(@NonNull Entity child) {
-        if (children.contains(child)) {
+        if (mChildren.contains(child)) {
             Log.w("RealityCoreRuntime", "Trying to add child who is already a child.");
         }
-        children.add(child);
+        mChildren.add(child);
     }
 
     protected void removeChildInternal(@NonNull Entity child) {
-        if (!children.contains(child)) {
+        if (!mChildren.contains(child)) {
             Log.w("RealityCoreRuntime", "Trying to remove child who is not a child.");
             return;
         }
-        children.remove(child);
+        mChildren.remove(child);
     }
 
     @Override
@@ -61,8 +61,8 @@
     }
 
     @Override
-    public void addChildren(@NonNull List<Entity> children) {
-        for (Entity child : children) {
+    public void addChildren(@NonNull List<Entity> mChildren) {
+        for (Entity child : mChildren) {
             child.setParent(this);
         }
     }
@@ -70,7 +70,7 @@
     @Override
     @Nullable
     public Entity getParent() {
-        return parent;
+        return mParent;
     }
 
     @Override
@@ -79,19 +79,19 @@
             Log.e("RealityCoreRuntime", "Cannot set non-BaseEntity as a parent of a BaseEntity");
             return;
         }
-        if (this.parent != null) {
-            this.parent.removeChildInternal(this);
+        if (this.mParent != null) {
+            this.mParent.removeChildInternal(this);
         }
-        this.parent = (BaseEntity) parent;
-        if (this.parent != null) {
-            this.parent.addChildInternal(this);
+        this.mParent = (BaseEntity) parent;
+        if (this.mParent != null) {
+            this.mParent.addChildInternal(this);
         }
     }
 
     @Override
     @NonNull
     public List<Entity> getChildren() {
-        return children;
+        return mChildren;
     }
 
     @Override
@@ -103,12 +103,12 @@
     @Override
     @NonNull
     public Pose getPose() {
-        return pose;
+        return mPose;
     }
 
     @Override
     public void setPose(@NonNull Pose pose) {
-        this.pose = pose;
+        this.mPose = pose;
     }
 
     @Override
@@ -116,80 +116,80 @@
     public Pose getActivitySpacePose() {
         // Any parentless "space" entities (such as the root and anchor entities) are expected to
         // override this method non-recursively so that this error is never thrown.
-        if (parent == null) {
+        if (mParent == null) {
             throw new IllegalStateException("Cannot get pose in ActivitySpace with a null parent");
         }
 
-        return parent.getActivitySpacePose()
+        return mParent.getActivitySpacePose()
                 .compose(
                         new Pose(
-                                this.pose.getTranslation().times(parent.getWorldSpaceScale()),
-                                this.pose.getRotation()));
+                                this.mPose.getTranslation().times(mParent.getWorldSpaceScale()),
+                                this.mPose.getRotation()));
     }
 
     @Override
     @NonNull
     public Vector3 getScale() {
-        return scale;
+        return mScale;
     }
 
     @Override
     public void setScale(@NonNull Vector3 scale) {
-        this.scale = scale;
+        this.mScale = scale;
     }
 
     // Purely sets the value of the scale.
     protected final void setScaleInternal(@NonNull Vector3 scale) {
-        this.scale = scale;
+        this.mScale = scale;
     }
 
     @Override
     public float getAlpha() {
-        return alpha;
+        return mAlpha;
     }
 
     @Override
     public void setAlpha(float alpha) {
-        this.alpha = alpha;
+        this.mAlpha = alpha;
     }
 
     @Override
     public float getActivitySpaceAlpha() {
-        if (parent == null) {
-            return alpha;
+        if (mParent == null) {
+            return mAlpha;
         }
-        return parent.getActivitySpaceAlpha() * alpha;
+        return mParent.getActivitySpaceAlpha() * mAlpha;
     }
 
     @Override
     @NonNull
     public Vector3 getWorldSpaceScale() {
-        if (parent == null) {
+        if (mParent == null) {
             throw new IllegalStateException("Cannot get scale in WorldSpace with a null parent");
         }
-        return parent.getWorldSpaceScale().times(this.scale);
+        return mParent.getWorldSpaceScale().times(this.mScale);
     }
 
     @Override
     @NonNull
     public Vector3 getActivitySpaceScale() {
-        if (parent == null) {
+        if (mParent == null) {
             throw new IllegalStateException("Cannot get scale in ActivitySpace with a null parent");
         }
-        return parent.getActivitySpaceScale().times(this.scale);
+        return mParent.getActivitySpaceScale().times(this.mScale);
     }
 
     @Override
     public boolean isHidden(boolean includeParents) {
-        if (!includeParents || parent == null) {
-            return hidden;
+        if (!includeParents || mParent == null) {
+            return mHidden;
         }
-        return hidden || parent.isHidden(true);
+        return mHidden || mParent.isHidden(true);
     }
 
     @Override
     public void setHidden(boolean hidden) {
-        this.hidden = hidden;
+        this.mHidden = hidden;
     }
 
     @Override
@@ -197,7 +197,7 @@
         // Create a copy to avoid concurrent modification issues since the children detach
         // themselves
         // from their parents as they are disposed.
-        List<Entity> childrenToDispose = new ArrayList<>(children);
+        List<Entity> childrenToDispose = new ArrayList<>(mChildren);
         for (Entity child : childrenToDispose) {
             child.dispose();
         }
@@ -206,7 +206,7 @@
     @Override
     public boolean addComponent(@NonNull Component component) {
         if (component.onAttach(this)) {
-            componentList.add(component);
+            mComponentList.add(component);
             return true;
         }
         return false;
@@ -214,17 +214,17 @@
 
     @Override
     public void removeComponent(@NonNull Component component) {
-        if (componentList.contains(component)) {
+        if (mComponentList.contains(component)) {
             component.onDetach(this);
-            componentList.remove(component);
+            mComponentList.remove(component);
         }
     }
 
     @Override
     public void removeAllComponents() {
-        for (Component component : componentList) {
+        for (Component component : mComponentList) {
             component.onDetach(this);
         }
-        componentList.clear();
+        mComponentList.clear();
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ActivityPanelEntityImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ActivityPanelEntityImpl.java
index 3da6432..f37a553 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ActivityPanelEntityImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ActivityPanelEntityImpl.java
@@ -35,7 +35,7 @@
 /** Implementation of {@link ActivityPanelEntity}. */
 class ActivityPanelEntityImpl extends BasePanelEntity implements ActivityPanelEntity {
     private static final String TAG = ActivityPanelEntityImpl.class.getSimpleName();
-    private final ActivityPanel activityPanel;
+    private final ActivityPanel mActivityPanel;
 
     // TODO(b/352630140): Add a static factory method and remove the business logic from
     //                    JxrPlatformAdapterAxr.
@@ -51,7 +51,7 @@
         // We need to notify our base class of the pixelDimensions, even though the Extensions are
         // initialized in the factory method. (ext.ActivityPanel.setWindowBounds, etc)
         super.setPixelDimensions(windowBoundsPx);
-        this.activityPanel = activityPanel;
+        mActivityPanel = activityPanel;
     }
 
     @Override
@@ -61,7 +61,7 @@
         // launching an Activity into it. The Activity will then render into the size the
         // application
         // specified, and the system will apply letterboxing if necessary.
-        activityPanel.launchActivity(intent, bundle);
+        mActivityPanel.launchActivity(intent, bundle);
     }
 
     @Override
@@ -69,12 +69,12 @@
         // Note that moving an Activity into the Panel doesn't actually update the size. The
         // application
         // should explicitly call setPixelDimensions() to update the size of an ActivityPanel.
-        activityPanel.moveActivity(activity);
+        mActivityPanel.moveActivity(activity);
     }
 
     @Override
     public void setPixelDimensions(PixelDimensions dimensions) {
-        PixelDimensions oldDimensions = this.pixelDimensions;
+        PixelDimensions oldDimensions = mPixelDimensions;
         super.setPixelDimensions(dimensions);
 
         // Avoid updating the bounds if we were called with the same values.
@@ -83,7 +83,7 @@
             return;
         }
 
-        activityPanel.setWindowBounds(new Rect(0, 0, dimensions.width, dimensions.height));
+        mActivityPanel.setWindowBounds(new Rect(0, 0, dimensions.width, dimensions.height));
     }
 
     /**
@@ -93,7 +93,7 @@
      */
     @Override
     public void dispose() {
-        activityPanel.delete();
+        mActivityPanel.delete();
         super.dispose();
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ActivitySpaceImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ActivitySpaceImpl.java
index a959d70..7f539f7 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ActivitySpaceImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ActivitySpaceImpl.java
@@ -46,13 +46,13 @@
 
     private static final String TAG = "ActivitySpaceImpl";
 
-    private final Set<OnBoundsChangedListener> boundsListeners =
+    private final Set<OnBoundsChangedListener> mBoundsListeners =
             Collections.synchronizedSet(new HashSet<>());
 
-    private final Supplier<SpatialState> spatialStateProvider;
-    private final AtomicReference<Dimensions> bounds = new AtomicReference<>();
+    private final Supplier<SpatialState> mSpatialStateProvider;
+    private final AtomicReference<Dimensions> mBounds = new AtomicReference<>();
 
-    public ActivitySpaceImpl(
+    ActivitySpaceImpl(
             Node taskNode,
             XrExtensions extensions,
             EntityManager entityManager,
@@ -60,7 +60,7 @@
             ScheduledExecutorService executor) {
         super(taskNode, extensions, entityManager, executor);
 
-        this.spatialStateProvider = spatialStateProvider;
+        mSpatialStateProvider = spatialStateProvider;
     }
 
     /** Returns the identity pose since this entity defines the origin of the activity space. */
@@ -104,10 +104,10 @@
         // The bounds are kept in sync with the Extensions in the onBoundsChangedEvent callback. We
         // only
         // invoke getSpatialState if they've never been set.
-        return bounds.updateAndGet(
+        return mBounds.updateAndGet(
                 oldBounds -> {
                     if (oldBounds == null) {
-                        Bounds bounds = spatialStateProvider.get().getBounds();
+                        Bounds bounds = mSpatialStateProvider.get().getBounds();
                         return new Dimensions(bounds.width, bounds.height, bounds.depth);
                     }
                     return oldBounds;
@@ -116,12 +116,12 @@
 
     @Override
     public void addOnBoundsChangedListener(@NonNull OnBoundsChangedListener listener) {
-        this.boundsListeners.add(listener);
+        mBoundsListeners.add(listener);
     }
 
     @Override
     public void removeOnBoundsChangedListener(@NonNull OnBoundsChangedListener listener) {
-        this.boundsListeners.remove(listener);
+        mBoundsListeners.remove(listener);
     }
 
     /**
@@ -133,10 +133,10 @@
      */
     public void onBoundsChanged(Bounds newBounds) {
         Dimensions newDimensions =
-                bounds.updateAndGet(
+                mBounds.updateAndGet(
                         oldBounds ->
                                 new Dimensions(newBounds.width, newBounds.height, newBounds.depth));
-        for (OnBoundsChangedListener listener : boundsListeners) {
+        for (OnBoundsChangedListener listener : mBoundsListeners) {
             listener.onBoundsChanged(newDimensions);
         }
     }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AnchorEntityImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AnchorEntityImpl.java
index 8ab6970..9683589 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AnchorEntityImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AnchorEntityImpl.java
@@ -59,15 +59,15 @@
     public static final Duration PERSIST_STATE_CHECK_DELAY = Duration.ofMillis(500);
     public static final String ANCHOR_NODE_NAME = "AnchorNode";
     private static final String TAG = "AnchorEntityImpl";
-    private final ActivitySpaceImpl activitySpace;
-    private final AndroidXrEntity activitySpaceRoot;
-    private final PerceptionLibrary perceptionLibrary;
-    private OnStateChangedListener onStateChangedListener;
-    private State state = State.UNANCHORED;
-    private PersistState persistState = PersistState.PERSIST_NOT_REQUESTED;
-    private Anchor anchor;
-    private UUID uuid = null;
-    private PersistStateChangeListener persistStateChangeListener;
+    private final ActivitySpaceImpl mActivitySpace;
+    private final AndroidXrEntity mActivitySpaceRoot;
+    private final PerceptionLibrary mPerceptionLibrary;
+    private OnStateChangedListener mOnStateChangedListener;
+    private State mState = State.UNANCHORED;
+    private PersistState mPersistState = PersistState.PERSIST_NOT_REQUESTED;
+    private Anchor mAnchor;
+    private UUID mUuid = null;
+    private PersistStateChangeListener mPersistStateChangeListener;
 
     private static class AnchorCreationData {
 
@@ -76,7 +76,7 @@
         static final int ANCHOR_CREATION_PLANE = 3;
         static final int ANCHOR_CREATION_PERCEPTION_ANCHOR = 4;
 
-        @AnchorCreationType int anchorCreationType;
+        @AnchorCreationType int mAnchorCreationType;
 
         /** IntDef for Anchor creation types. */
         @IntDef({
@@ -89,23 +89,23 @@
         private @interface AnchorCreationType {}
 
         // Anchor that is already created via Perception API.
-        androidx.xr.arcore.Anchor perceptionAnchor;
+        androidx.xr.arcore.Anchor mPerceptionAnchor;
 
         // Anchor search deadline for semantic and persisted anchors.
-        Long anchorSearchDeadline;
+        Long mAnchorSearchDeadline;
 
         // Fields exclusively for semantic anchors.
-        Dimensions dimensions;
-        PlaneType planeType;
-        PlaneSemantic planeSemantic;
+        Dimensions mDimensions;
+        PlaneType mPlaneType;
+        PlaneSemantic mPlaneSemantic;
 
         // Fields exclusively for persisted anchors.
-        UUID uuid = null;
+        UUID mUuid = null;
 
         // Fields exclusively for plane anchors.
-        Plane plane;
-        Pose planeOffsetPose;
-        Long planeDataTimeNs;
+        Plane mPlane;
+        Pose mPlaneOffsetPose;
+        Long mPlaneDataTimeNs;
     }
 
     static AnchorEntityImpl createSemanticAnchor(
@@ -121,11 +121,11 @@
             ScheduledExecutorService executor,
             PerceptionLibrary perceptionLibrary) {
         AnchorCreationData anchorCreationData = new AnchorCreationData();
-        anchorCreationData.anchorCreationType = AnchorCreationData.ANCHOR_CREATION_SEMANTIC;
-        anchorCreationData.dimensions = dimensions;
-        anchorCreationData.planeType = planeType;
-        anchorCreationData.planeSemantic = planeSemantic;
-        anchorCreationData.anchorSearchDeadline = getAnchorDeadline(anchorSearchTimeout);
+        anchorCreationData.mAnchorCreationType = AnchorCreationData.ANCHOR_CREATION_SEMANTIC;
+        anchorCreationData.mDimensions = dimensions;
+        anchorCreationData.mPlaneType = planeType;
+        anchorCreationData.mPlaneSemantic = planeSemantic;
+        anchorCreationData.mAnchorSearchDeadline = getAnchorDeadline(anchorSearchTimeout);
         return new AnchorEntityImpl(
                 node,
                 anchorCreationData,
@@ -148,9 +148,9 @@
             ScheduledExecutorService executor,
             PerceptionLibrary perceptionLibrary) {
         AnchorCreationData anchorCreationData = new AnchorCreationData();
-        anchorCreationData.anchorCreationType = AnchorCreationData.ANCHOR_CREATION_PERSISTED;
-        anchorCreationData.uuid = uuid;
-        anchorCreationData.anchorSearchDeadline = getAnchorDeadline(anchorSearchTimeout);
+        anchorCreationData.mAnchorCreationType = AnchorCreationData.ANCHOR_CREATION_PERSISTED;
+        anchorCreationData.mUuid = uuid;
+        anchorCreationData.mAnchorSearchDeadline = getAnchorDeadline(anchorSearchTimeout);
         return new AnchorEntityImpl(
                 node,
                 anchorCreationData,
@@ -174,10 +174,10 @@
             ScheduledExecutorService executor,
             PerceptionLibrary perceptionLibrary) {
         AnchorCreationData anchorCreationData = new AnchorCreationData();
-        anchorCreationData.anchorCreationType = AnchorCreationData.ANCHOR_CREATION_PLANE;
-        anchorCreationData.plane = plane;
-        anchorCreationData.planeOffsetPose = planeOffsetPose;
-        anchorCreationData.planeDataTimeNs = planeDataTimeNs;
+        anchorCreationData.mAnchorCreationType = AnchorCreationData.ANCHOR_CREATION_PLANE;
+        anchorCreationData.mPlane = plane;
+        anchorCreationData.mPlaneOffsetPose = planeOffsetPose;
+        anchorCreationData.mPlaneDataTimeNs = planeDataTimeNs;
         return new AnchorEntityImpl(
                 node,
                 anchorCreationData,
@@ -199,9 +199,9 @@
             ScheduledExecutorService executor,
             PerceptionLibrary perceptionLibrary) {
         AnchorCreationData anchorCreationData = new AnchorCreationData();
-        anchorCreationData.anchorCreationType =
+        anchorCreationData.mAnchorCreationType =
                 AnchorCreationData.ANCHOR_CREATION_PERCEPTION_ANCHOR;
-        anchorCreationData.perceptionAnchor = anchor;
+        anchorCreationData.mPerceptionAnchor = anchor;
         return new AnchorEntityImpl(
                 node,
                 anchorCreationData,
@@ -223,50 +223,50 @@
             ScheduledExecutorService executor,
             PerceptionLibrary perceptionLibrary) {
         super(node, extensions, entityManager, executor);
-        this.perceptionLibrary = perceptionLibrary;
+        mPerceptionLibrary = perceptionLibrary;
 
         try (NodeTransaction transaction = extensions.createNodeTransaction()) {
             transaction.setName(node, ANCHOR_NODE_NAME).apply();
         }
 
         if (activitySpace instanceof ActivitySpaceImpl) {
-            this.activitySpace = (ActivitySpaceImpl) activitySpace;
+            mActivitySpace = (ActivitySpaceImpl) activitySpace;
         } else {
             Log.e(
                     TAG,
                     "ActivitySpace is not an instance of ActivitySpaceImpl.Anchor is in Error"
                             + " state.");
-            this.state = State.ERROR;
-            this.activitySpace = null;
+            mState = State.ERROR;
+            mActivitySpace = null;
         }
 
         if (activitySpaceRoot instanceof AndroidXrEntity) {
-            this.activitySpaceRoot = (AndroidXrEntity) activitySpaceRoot;
+            mActivitySpaceRoot = (AndroidXrEntity) activitySpaceRoot;
         } else {
             Log.e(
                     TAG,
                     "ActivitySpaceRoot is not an instance of AndroidXrEntity. Anchor is in Error"
                             + " state.");
-            this.state = State.ERROR;
-            this.activitySpaceRoot = null;
+            mState = State.ERROR;
+            mActivitySpaceRoot = null;
         }
 
         // Return early if the state is already in an error state.
-        if (this.state == State.ERROR) {
+        if (mState == State.ERROR) {
             return;
         }
 
         // If we are creating a semantic or persisted anchor then we need to search for the anchor
         // asynchronously. Otherwise we can create the anchor on the plane.
-        if (anchorCreationData.anchorCreationType
+        if (anchorCreationData.mAnchorCreationType
                 == AnchorCreationData.ANCHOR_CREATION_PERCEPTION_ANCHOR) {
-            tryConvertAnchor(anchorCreationData.perceptionAnchor);
-        } else if (anchorCreationData.anchorCreationType
+            tryConvertAnchor(anchorCreationData.mPerceptionAnchor);
+        } else if (anchorCreationData.mAnchorCreationType
                         == AnchorCreationData.ANCHOR_CREATION_SEMANTIC
-                || anchorCreationData.anchorCreationType
+                || anchorCreationData.mAnchorCreationType
                         == AnchorCreationData.ANCHOR_CREATION_PERSISTED) {
             tryFindAnchor(anchorCreationData);
-        } else if (anchorCreationData.anchorCreationType
+        } else if (anchorCreationData.mAnchorCreationType
                 == AnchorCreationData.ANCHOR_CREATION_PLANE) {
             tryCreateAnchorForPlane(anchorCreationData);
         }
@@ -286,9 +286,9 @@
     // Converts a perception anchor to JXRCore runtime anchor.
     private void tryConvertAnchor(androidx.xr.arcore.Anchor perceptionAnchor) {
         ExportableAnchor exportableAnchor = (ExportableAnchor) perceptionAnchor.getRuntimeAnchor();
-        this.anchor =
+        mAnchor =
                 new Anchor(exportableAnchor.getNativePointer(), exportableAnchor.getAnchorToken());
-        if (anchor.getAnchorToken() == null) {
+        if (mAnchor.getAnchorToken() == null) {
             updateState(State.ERROR);
             return;
         }
@@ -298,11 +298,11 @@
     // Creates an anchor on the provided plane.
     private void tryCreateAnchorForPlane(AnchorCreationData anchorCreationData) {
         androidx.xr.scenecore.impl.perception.Pose perceptionPose =
-                RuntimeUtils.poseToPerceptionPose(anchorCreationData.planeOffsetPose);
-        anchor =
-                anchorCreationData.plane.createAnchor(
-                        perceptionPose, anchorCreationData.planeDataTimeNs);
-        if (anchor == null || anchor.getAnchorToken() == null) {
+                RuntimeUtils.poseToPerceptionPose(anchorCreationData.mPlaneOffsetPose);
+        mAnchor =
+                anchorCreationData.mPlane.createAnchor(
+                        perceptionPose, anchorCreationData.mPlaneDataTimeNs);
+        if (mAnchor == null || mAnchor.getAnchorToken() == null) {
             updateState(State.ERROR);
             return;
         }
@@ -312,7 +312,7 @@
     // Schedules a search for the anchor.
     private void scheduleTryFindAnchor(AnchorCreationData anchorCreationData) {
         ScheduledFuture<?> unusedAnchorFuture =
-                executor.schedule(
+                mExecutor.schedule(
                         () -> tryFindAnchor(anchorCreationData),
                         ANCHOR_SEARCH_DELAY.toMillis(),
                         MILLISECONDS);
@@ -325,7 +325,7 @@
     }
 
     private synchronized void cancelAnchorSearch() {
-        if (state == State.UNANCHORED) {
+        if (mState == State.UNANCHORED) {
             Log.i(TAG, "Stopping search for anchor, reached timeout.");
             updateState(State.TIMED_OUT);
         }
@@ -334,71 +334,72 @@
     // Searches for the anchor and updates the state based on the result. If the anchor wasn't found
     // then the search is scheduled again if the deadline has not been exceeded.
     private void tryFindAnchor(AnchorCreationData anchorCreationData) {
-        if (this.activitySpace == null) {
+        if (mActivitySpace == null) {
             Log.e(TAG, "Skipping search for anchor there is no valid parent.");
             return;
         }
         synchronized (this) {
-            if (state != State.UNANCHORED) {
+            if (mState != State.UNANCHORED) {
                 // This should only be searching for an anchor if the state is UNANCHORED. If the
                 // state is
                 // ANCHORED then the anchor was already found, if it is ERROR then the entity no
                 // longer can
                 // use the anchor. Return here to stop the search.
-                Log.i(TAG, "Stopping search for anchor, the state is: " + state);
+                Log.i(TAG, "Stopping search for anchor, the state is: " + mState);
                 return;
             }
         }
         // Check if we are passed the deadline if so, cancel the search.
-        if (searchDeadlineExceeded(anchorCreationData.anchorSearchDeadline)) {
+        if (searchDeadlineExceeded(anchorCreationData.mAnchorSearchDeadline)) {
             cancelAnchorSearch();
             return;
         }
 
-        if (perceptionLibrary.getSession() == null) {
+        if (mPerceptionLibrary.getSession() == null) {
             scheduleTryFindAnchor(anchorCreationData);
             return;
         }
 
-        if (anchorCreationData.anchorCreationType == AnchorCreationData.ANCHOR_CREATION_SEMANTIC) {
-            anchor = findPlaneAnchor(anchorCreationData);
-        } else if (anchorCreationData.anchorCreationType
+        if (anchorCreationData.mAnchorCreationType == AnchorCreationData.ANCHOR_CREATION_SEMANTIC) {
+            mAnchor = findPlaneAnchor(anchorCreationData);
+        } else if (anchorCreationData.mAnchorCreationType
                 == AnchorCreationData.ANCHOR_CREATION_PERSISTED) {
-            anchor = perceptionLibrary.getSession().createAnchorFromUuid(anchorCreationData.uuid);
+            mAnchor =
+                    mPerceptionLibrary.getSession().createAnchorFromUuid(anchorCreationData.mUuid);
         } else {
             Log.e(
                     TAG,
                     "Searching for anchor creation type is not supported: "
-                            + anchorCreationData.anchorCreationType);
+                            + anchorCreationData.mAnchorCreationType);
         }
 
-        if (anchor == null || anchor.getAnchorToken() == null) {
+        if (mAnchor == null || mAnchor.getAnchorToken() == null) {
             scheduleTryFindAnchor(anchorCreationData);
             return;
         }
-        Log.i(TAG, "Received anchor: " + anchor.getAnchorToken());
+        Log.i(TAG, "Received anchor: " + mAnchor.getAnchorToken());
         // TODO: b/330933143 - Handle Additional anchor states (e.g. Error/ Becoming unanchored)
         synchronized (this) {
             // Make sure that we are still looking for the anchor before updating the state. The
             // application might have closed or disposed of the AnchorEntity while the search was
             // still
             // active on another thread.
-            if (state != State.UNANCHORED
-                    || searchDeadlineExceeded(anchorCreationData.anchorSearchDeadline)) {
+            if (mState != State.UNANCHORED
+                    || searchDeadlineExceeded(anchorCreationData.mAnchorSearchDeadline)) {
                 Log.i(TAG, "Found anchor but no longer searching.");
-                if (searchDeadlineExceeded(anchorCreationData.anchorSearchDeadline)) {
+                if (searchDeadlineExceeded(anchorCreationData.mAnchorSearchDeadline)) {
                     cancelAnchorSearch();
                 }
                 // Detach the found anchor since it is no longer needed.
-                if (!anchor.detach()) {
+                if (!mAnchor.detach()) {
                     Log.e(TAG, "Error when detaching anchor.");
                 }
                 return;
             }
             updateState(State.ANCHORED);
-            if (anchorCreationData.anchorCreationType
+            if (anchorCreationData.mAnchorCreationType
                     == AnchorCreationData.ANCHOR_CREATION_PERSISTED) {
-                this.uuid = anchorCreationData.uuid;
+                mUuid = anchorCreationData.mUuid;
                 updatePersistState(PersistState.PERSISTED);
             }
         }
@@ -409,7 +410,7 @@
     // the plane if found.
     @Nullable
     private Anchor findPlaneAnchor(AnchorCreationData anchorCreationData) {
-        for (Plane plane : perceptionLibrary.getSession().getAllPlanes()) {
+        for (Plane plane : mPerceptionLibrary.getSession().getAllPlanes()) {
             long timeNow = SystemClock.uptimeMillis() * 1000000;
             PlaneData planeData = plane.getData(timeNow);
             if (planeData == null) {
@@ -426,11 +427,11 @@
                             + planeData.type
                             + ", Label: "
                             + planeData.label);
-            Plane.Type perceptionType = RuntimeUtils.getPlaneType(anchorCreationData.planeType);
+            Plane.Type perceptionType = RuntimeUtils.getPlaneType(anchorCreationData.mPlaneType);
             Plane.Label perceptionLabel =
-                    RuntimeUtils.getPlaneLabel(anchorCreationData.planeSemantic);
-            if (anchorCreationData.dimensions.width <= planeData.extentWidth
-                    && anchorCreationData.dimensions.height <= planeData.extentHeight
+                    RuntimeUtils.getPlaneLabel(anchorCreationData.mPlaneSemantic);
+            if (anchorCreationData.mDimensions.width <= planeData.extentWidth
+                    && anchorCreationData.mDimensions.height <= planeData.extentHeight
                     && (planeData.type == perceptionType || perceptionType == Plane.Type.ARBITRARY)
                     && (planeData.label == perceptionLabel
                             || perceptionLabel == Plane.Label.UNKNOWN)) {
@@ -442,59 +443,59 @@
     }
 
     private synchronized void updateState(State newState) {
-        if (state == newState) {
+        if (mState == newState) {
             return;
         }
-        state = newState;
-        if (state == State.ANCHORED) {
-            try (NodeTransaction transaction = extensions.createNodeTransaction()) {
+        mState = newState;
+        if (mState == State.ANCHORED) {
+            try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
                 // Attach to the root CPM node. This will enable the anchored content to be visible.
                 // Note
                 // that the parent of the Entity is null, but the CPM Node is still attached.
                 transaction
-                        .setParent(node, activitySpace.getNode())
-                        .setAnchorId(node, anchor.getAnchorToken())
+                        .setParent(mNode, mActivitySpace.getNode())
+                        .setAnchorId(mNode, mAnchor.getAnchorToken())
                         .apply();
             }
         }
-        if (onStateChangedListener != null) {
-            onStateChangedListener.onStateChanged(state);
+        if (mOnStateChangedListener != null) {
+            mOnStateChangedListener.onStateChanged(mState);
         }
     }
 
     @Override
     public State getState() {
-        return state;
+        return mState;
     }
 
     @Override
     public void setOnStateChangedListener(OnStateChangedListener onStateChangedListener) {
-        this.onStateChangedListener = onStateChangedListener;
+        mOnStateChangedListener = onStateChangedListener;
     }
 
     @Override
     @Nullable
     public UUID persist() {
-        if (uuid != null) {
-            return uuid;
+        if (mUuid != null) {
+            return mUuid;
         }
-        if (state != State.ANCHORED) {
+        if (mState != State.ANCHORED) {
             Log.e(TAG, "Cannot persist an anchor that is not in the ANCHORED state.");
             return null;
         }
-        uuid = anchor.persist();
-        if (uuid == null) {
+        mUuid = mAnchor.persist();
+        if (mUuid == null) {
             Log.e(TAG, "Failed to get a UUID for the anchor.");
             return null;
         }
         updatePersistState(PersistState.PERSIST_PENDING);
         schedulePersistStateCheck();
-        return uuid;
+        return mUuid;
     }
 
     private void schedulePersistStateCheck() {
         ScheduledFuture<?> unusedPersistStateFuture =
-                executor.schedule(
+                mExecutor.schedule(
                         this::checkPersistState,
                         PERSIST_STATE_CHECK_DELAY.toMillis(),
                         MILLISECONDS);
@@ -502,14 +503,14 @@
 
     private void checkPersistState() {
         synchronized (this) {
-            if (anchor == null) {
+            if (mAnchor == null) {
                 Log.i(
                         TAG,
                         "Anchor is disposed before becoming persisted, stop checking its persist"
                                 + " state.");
                 return;
             }
-            if (anchor.getPersistState() == Anchor.PersistState.PERSISTED) {
+            if (mAnchor.getPersistState() == Anchor.PersistState.PERSISTED) {
                 updatePersistState(PersistState.PERSISTED);
                 Log.i(TAG, "Anchor is persisted.");
                 return;
@@ -521,27 +522,27 @@
     @Override
     public void registerPersistStateChangeListener(
             PersistStateChangeListener persistStateChangeListener) {
-        this.persistStateChangeListener = persistStateChangeListener;
+        mPersistStateChangeListener = persistStateChangeListener;
     }
 
     private synchronized void updatePersistState(PersistState newPersistState) {
-        if (persistState == newPersistState) {
+        if (mPersistState == newPersistState) {
             return;
         }
-        persistState = newPersistState;
-        if (persistStateChangeListener != null) {
-            persistStateChangeListener.onPersistStateChanged(newPersistState);
+        mPersistState = newPersistState;
+        if (mPersistStateChangeListener != null) {
+            mPersistStateChangeListener.onPersistStateChanged(newPersistState);
         }
     }
 
     @Override
     public PersistState getPersistState() {
-        return persistState;
+        return mPersistState;
     }
 
     @Override
     public long nativePointer() {
-        return anchor.getAnchorId();
+        return mAnchor.getAnchorId();
     }
 
     @Override
@@ -564,12 +565,12 @@
     @Override
     public Pose getPoseInActivitySpace() {
         synchronized (this) {
-            if (activitySpace == null) {
+            if (mActivitySpace == null) {
                 throw new IllegalStateException(
                         "Cannot get pose in Activity Space with a null Activity Space.");
             }
 
-            if (state != State.ANCHORED) {
+            if (mState != State.ANCHORED) {
                 Log.w(
                         TAG,
                         "Cannot retrieve pose in underlying space. Ensure that the anchor is"
@@ -581,7 +582,7 @@
             // we can
             // just compose the two poses without scaling.
             final Pose openXrToAnchor = this.getPoseInOpenXrReferenceSpace();
-            final Pose openXrToActivitySpace = activitySpace.getPoseInOpenXrReferenceSpace();
+            final Pose openXrToActivitySpace = mActivitySpace.getPoseInOpenXrReferenceSpace();
             if (openXrToActivitySpace == null || openXrToAnchor == null) {
                 Log.e(
                         TAG,
@@ -598,7 +599,7 @@
     // TODO: b/360168321 Use the OpenXrPosableHelper when retrieving the pose in world space.
     @Override
     public Pose getActivitySpacePose() {
-        if (activitySpaceRoot == null) {
+        if (mActivitySpaceRoot == null) {
             throw new IllegalStateException(
                     "Cannot get pose in World Space Pose with a null World Space Entity.");
         }
@@ -609,13 +610,13 @@
         // compose the two poses without scaling.
         final Pose activitySpaceToAnchor = this.getPoseInActivitySpace();
         final Pose worldSpaceToActivitySpace =
-                activitySpaceRoot.getPoseInActivitySpace().getInverse();
+                mActivitySpaceRoot.getPoseInActivitySpace().getInverse();
         return worldSpaceToActivitySpace.compose(activitySpaceToAnchor);
     }
 
     @Override
     public Vector3 getActivitySpaceScale() {
-        return getWorldSpaceScale().div(activitySpace.getWorldSpaceScale());
+        return getWorldSpaceScale().div(mActivitySpace.getWorldSpaceScale());
     }
 
     @Override
@@ -630,22 +631,22 @@
 
         synchronized (this) {
             // Return early if it is already in the error state.
-            if (state == State.ERROR) {
+            if (mState == State.ERROR) {
                 return;
             }
             updateState(State.ERROR);
-            if (anchor != null && !anchor.detach()) {
+            if (mAnchor != null && !mAnchor.detach()) {
                 Log.e(TAG, "Error when detaching anchor.");
             }
-            anchor = null;
+            mAnchor = null;
         }
 
         // Set the parent of the CPM node to null; to hide the anchored content.The parent of the
         // entity
         // was always null so does not need to be reset.
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-            transaction.setAnchorId(node, null);
-            transaction.setParent(node, null).apply();
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
+            transaction.setAnchorId(mNode, null);
+            transaction.setParent(mNode, null).apply();
         }
         super.dispose();
     }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AnchorPlacementImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AnchorPlacementImpl.java
index 65f75a5..3d04c55 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AnchorPlacementImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AnchorPlacementImpl.java
@@ -32,8 +32,8 @@
  * will not be anchored.
  */
 class AnchorPlacementImpl implements AnchorPlacement {
-    protected Set<PlaneType> planeTypeFilter = new HashSet<>();
-    protected Set<PlaneSemantic> planeSemanticFilter = new HashSet<>();
+    protected Set<PlaneType> mPlaneTypeFilter = new HashSet<>();
+    protected Set<PlaneSemantic> mPlaneSemanticFilter = new HashSet<>();
 
     AnchorPlacementImpl() {}
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AndroidXrEntity.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AndroidXrEntity.java
index 1bbb7d8..0f2298a 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AndroidXrEntity.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AndroidXrEntity.java
@@ -48,29 +48,29 @@
 @SuppressWarnings({"BanSynchronizedMethods", "BanConcurrentHashMap"})
 abstract class AndroidXrEntity extends BaseEntity implements Entity {
 
-    protected final Node node;
-    protected final XrExtensions extensions;
-    protected final ScheduledExecutorService executor;
+    protected final Node mNode;
+    protected final XrExtensions mExtensions;
+    protected final ScheduledExecutorService mExecutor;
     // Visible for testing
-    final ConcurrentHashMap<InputEventListener, Executor> inputEventListenerMap =
+    final ConcurrentHashMap<InputEventListener, Executor> mInputEventListenerMap =
             new ConcurrentHashMap<>();
-    Optional<InputEventListener> pointerCaptureInputEventListener = Optional.empty();
-    Optional<Executor> pointerCaptureExecutor = Optional.empty();
-    final ConcurrentHashMap<Consumer<ReformEvent>, Executor> reformEventConsumerMap =
+    Optional<InputEventListener> mPointerCaptureInputEventListener = Optional.empty();
+    Optional<Executor> mPointerCaptureExecutor = Optional.empty();
+    final ConcurrentHashMap<Consumer<ReformEvent>, Executor> mReformEventConsumerMap =
             new ConcurrentHashMap<>();
-    private final EntityManager entityManager;
-    private ReformOptions reformOptions;
+    private final EntityManager mEntityManager;
+    private ReformOptions mReformOptions;
 
     AndroidXrEntity(
             Node node,
             XrExtensions extensions,
             EntityManager entityManager,
             ScheduledExecutorService executor) {
-        this.node = node;
-        this.extensions = extensions;
-        this.entityManager = entityManager;
-        this.executor = executor;
-        entityManager.setEntityForNode(node, this);
+        mNode = node;
+        mExtensions = extensions;
+        mEntityManager = entityManager;
+        mExecutor = executor;
+        mEntityManager.setEntityForNode(node, this);
     }
 
     @Override
@@ -78,15 +78,15 @@
         // TODO: b/321268237 - Minimize the number of node transactions
         super.setPose(pose);
 
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
             transaction
                     .setPosition(
-                            node,
+                            mNode,
                             pose.getTranslation().getX(),
                             pose.getTranslation().getY(),
                             pose.getTranslation().getZ())
                     .setOrientation(
-                            node,
+                            mNode,
                             pose.getRotation().getX(),
                             pose.getRotation().getY(),
                             pose.getRotation().getZ(),
@@ -98,8 +98,8 @@
     @Override
     public void setScale(Vector3 scale) {
         super.setScale(scale);
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-            transaction.setScale(node, scale.getX(), scale.getY(), scale.getZ()).apply();
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
+            transaction.setScale(mNode, scale.getX(), scale.getY(), scale.getZ()).apply();
         }
     }
 
@@ -136,7 +136,7 @@
 
     // Returns the underlying extension Node for the Entity.
     public Node getNode() {
-        return node;
+        return mNode;
     }
 
     @Override
@@ -151,11 +151,11 @@
 
         AndroidXrEntity xrParent = (AndroidXrEntity) parent;
 
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
             if (xrParent == null) {
-                transaction.setVisibility(node, false).setParent(node, null);
+                transaction.setVisibility(mNode, false).setParent(mNode, null);
             } else {
-                transaction.setParent(node, xrParent.getNode());
+                transaction.setParent(mNode, xrParent.getNode());
             }
             transaction.apply();
         }
@@ -164,8 +164,8 @@
     @Override
     public void setSize(Dimensions dimensions) {
         // TODO: b/326479171: Uncomment when extensions implement setSize.
-        // try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-        //   transaction.setSize(node, dimensions.width, dimensions.height,
+        // try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
+        //   transaction.setSize(mNode, dimensions.width, dimensions.height,
         // dimensions.depth).apply();
         // }
     }
@@ -174,8 +174,8 @@
     public void setAlpha(float alpha) {
         super.setAlpha(alpha);
 
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-            transaction.setAlpha(node, alpha).apply();
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
+            transaction.setAlpha(mNode, alpha).apply();
         }
     }
 
@@ -183,25 +183,25 @@
     public void setHidden(boolean hidden) {
         super.setHidden(hidden);
 
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-            if (reformOptions != null) {
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
+            if (mReformOptions != null) {
                 if (hidden) {
                     // Since this entity is being hidden, disable reform and the highlights around
                     // the node.
-                    transaction.disableReform(node);
+                    transaction.disableReform(mNode);
                 } else {
                     // Enables reform and the highlights around the node.
-                    transaction.enableReform(node, reformOptions);
+                    transaction.enableReform(mNode, mReformOptions);
                 }
             }
-            transaction.setVisibility(node, !hidden).apply();
+            transaction.setVisibility(mNode, !hidden).apply();
         }
     }
 
     @Override
     public void addInputEventListener(Executor executor, InputEventListener eventListener) {
         maybeSetupInputListeners();
-        inputEventListenerMap.put(eventListener, executor == null ? this.executor : executor);
+        mInputEventListenerMap.put(eventListener, executor == null ? mExecutor : executor);
     }
 
     /**
@@ -216,7 +216,7 @@
             Executor executor,
             InputEventListener eventListener,
             PointerCaptureComponent.StateListener stateListener) {
-        if (pointerCaptureInputEventListener.isPresent()) {
+        if (mPointerCaptureInputEventListener.isPresent()) {
             return false;
         }
         getNode()
@@ -244,76 +244,76 @@
     private void addPointerCaptureInputListener(
             Executor executor, InputEventListener eventListener) {
         maybeSetupInputListeners();
-        pointerCaptureInputEventListener = Optional.of(eventListener);
-        pointerCaptureExecutor = Optional.ofNullable(executor);
+        mPointerCaptureInputEventListener = Optional.of(eventListener);
+        mPointerCaptureExecutor = Optional.ofNullable(executor);
     }
 
     private void maybeSetupInputListeners() {
-        if (inputEventListenerMap.isEmpty() && pointerCaptureInputEventListener.isEmpty()) {
-            node.listenForInput(
+        if (mInputEventListenerMap.isEmpty() && mPointerCaptureInputEventListener.isEmpty()) {
+            mNode.listenForInput(
                     (xrInputEvent) -> {
                         if (xrInputEvent.getDispatchFlags()
                                 == InputEvent.DISPATCH_FLAG_CAPTURED_POINTER) {
-                            pointerCaptureInputEventListener.ifPresent(
+                            mPointerCaptureInputEventListener.ifPresent(
                                     (listener) ->
-                                            pointerCaptureExecutor
-                                                    .orElse(this.executor)
+                                            mPointerCaptureExecutor
+                                                    .orElse(mExecutor)
                                                     .execute(
                                                             () ->
                                                                     listener.onInputEvent(
                                                                             RuntimeUtils
                                                                                     .getInputEvent(
                                                                                             xrInputEvent,
-                                                                                            entityManager))));
+                                                                                            mEntityManager))));
                         } else {
-                            inputEventListenerMap.forEach(
+                            mInputEventListenerMap.forEach(
                                     (inputEventListener, listenerExecutor) ->
                                             listenerExecutor.execute(
                                                     () ->
                                                             inputEventListener.onInputEvent(
                                                                     RuntimeUtils.getInputEvent(
                                                                             xrInputEvent,
-                                                                            entityManager))));
+                                                                            mEntityManager))));
                         }
                     },
-                    this.executor);
+                    mExecutor);
         }
     }
 
     @Override
     public void removeInputEventListener(InputEventListener consumer) {
-        inputEventListenerMap.remove(consumer);
+        mInputEventListenerMap.remove(consumer);
         maybeStopListeningForInput();
     }
 
     /** Stop any pointer capture requests on this Entity. */
     public void stopPointerCapture() {
         getNode().stopPointerCapture();
-        pointerCaptureInputEventListener = Optional.empty();
-        pointerCaptureExecutor = Optional.empty();
+        mPointerCaptureInputEventListener = Optional.empty();
+        mPointerCaptureExecutor = Optional.empty();
         maybeStopListeningForInput();
     }
 
     private void maybeStopListeningForInput() {
-        if (inputEventListenerMap.isEmpty() && pointerCaptureInputEventListener.isEmpty()) {
-            node.stopListeningForInput();
+        if (mInputEventListenerMap.isEmpty() && mPointerCaptureInputEventListener.isEmpty()) {
+            mNode.stopListeningForInput();
         }
     }
 
     @Override
     public void dispose() {
-        inputEventListenerMap.clear();
-        node.stopListeningForInput();
-        reformEventConsumerMap.clear();
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-            transaction.disableReform(node);
+        mInputEventListenerMap.clear();
+        mNode.stopListeningForInput();
+        mReformEventConsumerMap.clear();
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
+            transaction.disableReform(mNode);
         }
 
         // SystemSpaceEntityImpls (Anchors, ActivitySpace, etc) should have null parents.
         if (getParent() != null) {
             setParent(null);
         }
-        entityManager.removeEntityForNode(node);
+        mEntityManager.removeEntityForNode(mNode);
         super.dispose();
     }
 
@@ -323,11 +323,11 @@
      * @return The reform options for this entity.
      */
     public ReformOptions getReformOptions() {
-        if (reformOptions == null) {
+        if (mReformOptions == null) {
             Consumer<ReformEvent> reformEventConsumer =
                     reformEvent -> {
-                        if ((reformOptions.getEnabledReform() & ReformOptions.ALLOW_MOVE) != 0
-                                && (reformOptions.getFlags()
+                        if ((mReformOptions.getEnabledReform() & ReformOptions.ALLOW_MOVE) != 0
+                                && (mReformOptions.getFlags()
                                                 & ReformOptions.FLAG_ALLOW_SYSTEM_MOVEMENT)
                                         != 0) {
                             // Update the cached pose of the entity.
@@ -349,14 +349,14 @@
                                             reformEvent.getProposedScale().y,
                                             reformEvent.getProposedScale().z));
                         }
-                        reformEventConsumerMap.forEach(
+                        mReformEventConsumerMap.forEach(
                                 (eventConsumer, consumerExecutor) ->
                                         consumerExecutor.execute(
                                                 () -> eventConsumer.accept(reformEvent)));
                     };
-            reformOptions = extensions.createReformOptions(reformEventConsumer, executor);
+            mReformOptions = mExtensions.createReformOptions(reformEventConsumer, mExecutor);
         }
-        return reformOptions;
+        return mReformOptions;
     }
 
     /**
@@ -364,13 +364,13 @@
      * provided by {@link #getReformOptions()}.
      */
     public synchronized void updateReformOptions() {
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-            if (reformOptions.getEnabledReform() == 0) {
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
+            if (mReformOptions.getEnabledReform() == 0) {
                 // Disables reform and the highlights around the node.
-                transaction.disableReform(node);
+                transaction.disableReform(mNode);
             } else {
                 // Enables reform and the highlights around the node.
-                transaction.enableReform(node, reformOptions);
+                transaction.enableReform(mNode, mReformOptions);
             }
             transaction.apply();
         }
@@ -378,11 +378,11 @@
 
     public void addReformEventConsumer(
             Consumer<ReformEvent> reformEventConsumer, Executor executor) {
-        executor = (executor == null) ? this.executor : executor;
-        reformEventConsumerMap.put(reformEventConsumer, executor);
+        executor = (executor == null) ? mExecutor : executor;
+        mReformEventConsumerMap.put(reformEventConsumer, executor);
     }
 
     public void removeReformEventConsumer(Consumer<ReformEvent> reformEventConsumer) {
-        reformEventConsumerMap.remove(reformEventConsumer);
+        mReformEventConsumerMap.remove(reformEventConsumer);
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AudioTrackExtensionsWrapperImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AudioTrackExtensionsWrapperImpl.java
index 6e07e54..9ebcad34 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AudioTrackExtensionsWrapperImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/AudioTrackExtensionsWrapperImpl.java
@@ -29,26 +29,26 @@
 /** Implementation of the {@link AudioTrackExtensionsWrapper} */
 final class AudioTrackExtensionsWrapperImpl implements AudioTrackExtensionsWrapper {
 
-    private final AudioTrackExtensions extensions;
+    private final AudioTrackExtensions mExtensions;
 
-    private final EntityManager entityManager;
+    private final EntityManager mEntityManager;
 
     AudioTrackExtensionsWrapperImpl(AudioTrackExtensions extensions, EntityManager entityManager) {
-        this.extensions = extensions;
-        this.entityManager = entityManager;
+        mExtensions = extensions;
+        mEntityManager = entityManager;
     }
 
     @Nullable
     @Override
     public PointSourceAttributes getPointSourceAttributes(@NonNull AudioTrack audioTrack) {
         androidx.xr.extensions.media.PointSourceAttributes extAttributes =
-                extensions.getPointSourceAttributes(audioTrack);
+                mExtensions.getPointSourceAttributes(audioTrack);
 
         if (extAttributes == null) {
             return null;
         }
 
-        Entity entity = entityManager.getEntityForNode(extAttributes.getNode());
+        Entity entity = mEntityManager.getEntityForNode(extAttributes.getNode());
 
         if (entity == null) {
             return null;
@@ -61,7 +61,7 @@
     @Override
     public SoundFieldAttributes getSoundFieldAttributes(@NonNull AudioTrack audioTrack) {
         androidx.xr.extensions.media.SoundFieldAttributes extAttributes =
-                extensions.getSoundFieldAttributes(audioTrack);
+                mExtensions.getSoundFieldAttributes(audioTrack);
 
         if (extAttributes == null) {
             return null;
@@ -72,7 +72,8 @@
 
     @Override
     public int getSpatialSourceType(@NonNull AudioTrack audioTrack) {
-        return extensions.getSpatialSourceType(audioTrack);
+        return MediaUtils.convertExtensionsToSourceType(
+                mExtensions.getSpatialSourceType(audioTrack));
     }
 
     @Override
@@ -82,7 +83,7 @@
         androidx.xr.extensions.media.PointSourceAttributes extAttributes =
                 MediaUtils.convertPointSourceAttributesToExtensions(attributes);
 
-        return extensions.setPointSourceAttributes(builder, extAttributes);
+        return mExtensions.setPointSourceAttributes(builder, extAttributes);
     }
 
     @Override
@@ -92,6 +93,6 @@
         androidx.xr.extensions.media.SoundFieldAttributes extAttributes =
                 MediaUtils.convertSoundFieldAttributesToExtensions(attributes);
 
-        return extensions.setSoundFieldAttributes(builder, extAttributes);
+        return mExtensions.setSoundFieldAttributes(builder, extAttributes);
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/BasePanelEntity.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/BasePanelEntity.java
index 38da5e0..41a4e9e5 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/BasePanelEntity.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/BasePanelEntity.java
@@ -31,8 +31,8 @@
 /** BasePanelEntity provides implementations of capabilities common to PanelEntities. */
 @SuppressWarnings("deprecation") // TODO(b/373435470): Remove
 abstract class BasePanelEntity extends AndroidXrEntity implements PanelEntity {
-    protected PixelDimensions pixelDimensions;
-    private float cornerRadius;
+    protected PixelDimensions mPixelDimensions;
+    private float mCornerRadius;
 
     BasePanelEntity(
             Node node,
@@ -43,7 +43,7 @@
     }
 
     private float getDefaultPixelDensity() {
-        return extensions
+        return mExtensions
                 .getConfig()
                 .defaultPixelsPerMeter(Resources.getSystem().getDisplayMetrics().density);
     }
@@ -62,8 +62,8 @@
     public Dimensions getSize() {
         Vector3 pixelDensity = getPixelDensity();
         return new Dimensions(
-                pixelDimensions.width / pixelDensity.getX(),
-                pixelDimensions.height / pixelDensity.getY(),
+                mPixelDimensions.width / pixelDensity.getX(),
+                mPixelDimensions.height / pixelDensity.getY(),
                 0);
     }
 
@@ -75,12 +75,12 @@
 
     @Override
     public PixelDimensions getPixelDimensions() {
-        return pixelDimensions;
+        return mPixelDimensions;
     }
 
     @Override
     public void setPixelDimensions(PixelDimensions dimensions) {
-        pixelDimensions = dimensions;
+        mPixelDimensions = dimensions;
     }
 
     @Override
@@ -88,14 +88,14 @@
         if (value < 0.0f) {
             throw new IllegalArgumentException("Corner radius can't be negative: " + value);
         }
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-            transaction.setCornerRadius(node, value).apply();
-            cornerRadius = value;
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
+            transaction.setCornerRadius(mNode, value).apply();
+            mCornerRadius = value;
         }
     }
 
     @Override
     public float getCornerRadius() {
-        return cornerRadius;
+        return mCornerRadius;
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/CameraViewActivityPoseImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/CameraViewActivityPoseImpl.java
index cabab63..38c3b2e 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/CameraViewActivityPoseImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/CameraViewActivityPoseImpl.java
@@ -34,42 +34,41 @@
  */
 final class CameraViewActivityPoseImpl extends BaseActivityPose implements CameraViewActivityPose {
     private static final String TAG = "CameraViewActivityPose";
-    private final PerceptionLibrary perceptionLibrary;
-    @CameraType private final int cameraType;
-    private final OpenXrActivityPoseHelper openXrActivityPoseHelper;
+    private final PerceptionLibrary mPerceptionLibrary;
+    @CameraType private final int mCameraType;
+    private final OpenXrActivityPoseHelper mOpenXrActivityPoseHelper;
     // Default the pose to null. A null pose indicates that the camera is not ready yet.
-    private Pose lastOpenXrPose = null;
+    private Pose mLastOpenXrPose = null;
 
-    public CameraViewActivityPoseImpl(
+    CameraViewActivityPoseImpl(
             @CameraType int cameraType,
             ActivitySpaceImpl activitySpace,
             AndroidXrEntity activitySpaceRoot,
             PerceptionLibrary perceptionLibrary) {
-        this.cameraType = cameraType;
-        this.perceptionLibrary = perceptionLibrary;
-        this.openXrActivityPoseHelper =
-                new OpenXrActivityPoseHelper(activitySpace, activitySpaceRoot);
+        mCameraType = cameraType;
+        mPerceptionLibrary = perceptionLibrary;
+        mOpenXrActivityPoseHelper = new OpenXrActivityPoseHelper(activitySpace, activitySpaceRoot);
     }
 
     @Override
     public Pose getPoseInActivitySpace() {
-        return openXrActivityPoseHelper.getPoseInActivitySpace(getPoseInOpenXrReferenceSpace());
+        return mOpenXrActivityPoseHelper.getPoseInActivitySpace(getPoseInOpenXrReferenceSpace());
     }
 
     @Override
     public Pose getActivitySpacePose() {
-        return openXrActivityPoseHelper.getActivitySpacePose(getPoseInOpenXrReferenceSpace());
+        return mOpenXrActivityPoseHelper.getActivitySpacePose(getPoseInOpenXrReferenceSpace());
     }
 
     @Override
     public Vector3 getActivitySpaceScale() {
         // This WorldPose is assumed to always have a scale of 1.0f in the OpenXR reference space.
-        return openXrActivityPoseHelper.getActivitySpaceScale(new Vector3(1f, 1f, 1f));
+        return mOpenXrActivityPoseHelper.getActivitySpaceScale(new Vector3(1f, 1f, 1f));
     }
 
     @Nullable
     private ViewProjection getViewProjection() {
-        final Session session = perceptionLibrary.getSession();
+        final Session session = mPerceptionLibrary.getSession();
         if (session == null) {
             Log.w(TAG, "Cannot retrieve the camera pose with a null perception session.");
             return null;
@@ -79,12 +78,12 @@
             Log.e(TAG, "Error retrieving the camera.");
             return null;
         }
-        if (cameraType == CameraViewActivityPose.CAMERA_TYPE_LEFT_EYE) {
+        if (mCameraType == CameraViewActivityPose.CAMERA_TYPE_LEFT_EYE) {
             return perceptionViews.getLeftEye();
-        } else if (cameraType == CameraViewActivityPose.CAMERA_TYPE_RIGHT_EYE) {
+        } else if (mCameraType == CameraViewActivityPose.CAMERA_TYPE_RIGHT_EYE) {
             return perceptionViews.getRightEye();
         } else {
-            Log.w(TAG, "Unsupported camera type: " + cameraType);
+            Log.w(TAG, "Unsupported camera type: " + mCameraType);
             return null;
         }
     }
@@ -94,15 +93,15 @@
     public Pose getPoseInOpenXrReferenceSpace() {
         ViewProjection viewProjection = getViewProjection();
         if (viewProjection != null) {
-            lastOpenXrPose = RuntimeUtils.fromPerceptionPose(viewProjection.getPose());
+            mLastOpenXrPose = RuntimeUtils.fromPerceptionPose(viewProjection.getPose());
         }
-        return lastOpenXrPose;
+        return mLastOpenXrPose;
     }
 
     @Override
     @CameraType
     public int getCameraType() {
-        return cameraType;
+        return mCameraType;
     }
 
     @Override
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/EntityManager.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/EntityManager.java
index 4bb5465..def6de7 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/EntityManager.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/EntityManager.java
@@ -35,7 +35,7 @@
  */
 @SuppressWarnings("BanConcurrentHashMap")
 final class EntityManager {
-    private final Map<Node, Entity> nodeEntityMap = new ConcurrentHashMap<>();
+    private final Map<Node, Entity> mNodeEntityMap = new ConcurrentHashMap<>();
 
     /**
      * Returns the {@link Entity} associated with the given {@link Node}.
@@ -46,7 +46,7 @@
      */
     @Nullable
     Entity getEntityForNode(@NonNull Node node) {
-        return nodeEntityMap.get(node);
+        return mNodeEntityMap.get(node);
     }
 
     /**
@@ -56,7 +56,7 @@
      * @param entity the {@link Entity} to associate with the given {@link Node}.
      */
     void setEntityForNode(@NonNull Node node, @NonNull Entity entity) {
-        nodeEntityMap.put(node, entity);
+        mNodeEntityMap.put(node, entity);
     }
 
     /**
@@ -66,7 +66,7 @@
      * @return a list of all {@link Entity}s of type {@code T} (including subtypes of {@code T}).
      */
     <T extends Entity> List<T> getEntitiesOfType(@NonNull Class<T> entityClass) {
-        return nodeEntityMap.values().stream()
+        return mNodeEntityMap.values().stream()
                 .filter(entityClass::isInstance)
                 .map(entityClass::cast)
                 .collect(toCollection(ArrayList::new));
@@ -74,16 +74,16 @@
 
     /** Returns a collection of all {@link Entity}s. */
     Collection<Entity> getAllEntities() {
-        return nodeEntityMap.values();
+        return mNodeEntityMap.values();
     }
 
     /** Removes the given {@link Node} from the map. */
     void removeEntityForNode(@NonNull Node node) {
-        nodeEntityMap.remove(node);
+        mNodeEntityMap.remove(node);
     }
 
     /** Clears the EntityManager. */
     void clear() {
-        nodeEntityMap.clear();
+        mNodeEntityMap.clear();
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ExrImageResourceImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ExrImageResourceImpl.java
index c011afa..9628d57 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ExrImageResourceImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ExrImageResourceImpl.java
@@ -27,13 +27,13 @@
 @SuppressWarnings({"deprecation", "UnnecessarilyFullyQualified"}) // TODO(b/373435470): Remove
 final class ExrImageResourceImpl implements ExrImageResource {
     // Note: right now the "environment" format accessible through the XRExtensions layer is .EXR
-    private final androidx.xr.extensions.asset.EnvironmentToken token;
+    private final androidx.xr.extensions.asset.EnvironmentToken mToken;
 
-    public ExrImageResourceImpl(androidx.xr.extensions.asset.EnvironmentToken token) {
-        this.token = token;
+    ExrImageResourceImpl(androidx.xr.extensions.asset.EnvironmentToken token) {
+        mToken = token;
     }
 
     public androidx.xr.extensions.asset.EnvironmentToken getToken() {
-        return token;
+        return mToken;
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfEntityImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfEntityImpl.java
index 622b2e7..dcd8413 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfEntityImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfEntityImpl.java
@@ -34,7 +34,7 @@
 // TODO: b/321782625 - Add tests when the Extensions can be faked.
 @SuppressWarnings("deprecation") // TODO(b/373435470): Remove
 final class GltfEntityImpl extends AndroidXrEntity implements GltfEntity {
-    public GltfEntityImpl(
+    GltfEntityImpl(
             GltfModelResourceImpl gltfModelResource,
             Entity parentEntity,
             XrExtensions extensions,
@@ -44,7 +44,7 @@
         setParent(parentEntity);
 
         try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-            transaction.setGltfModel(node, gltfModelResource.getExtensionModelToken()).apply();
+            transaction.setGltfModel(mNode, gltfModelResource.getExtensionModelToken()).apply();
         }
     }
 
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfEntityImplSplitEngine.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfEntityImplSplitEngine.java
index 242c3c7..7373d82 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfEntityImplSplitEngine.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfEntityImplSplitEngine.java
@@ -38,14 +38,14 @@
  */
 // TODO: b/375520647 - Add unit tests for this class.
 class GltfEntityImplSplitEngine extends AndroidXrEntity implements GltfEntity {
-    private final ImpressApi impressApi;
-    private final SplitEngineSubspaceManager splitEngineSubspaceManager;
-    private final SubspaceNode subspace;
-    private final int modelImpressNode;
-    private final int subspaceImpressNode;
-    @AnimationState private int animationState = AnimationState.STOPPED;
+    private final ImpressApi mImpressApi;
+    private final SplitEngineSubspaceManager mSplitEngineSubspaceManager;
+    private final SubspaceNode mSubspace;
+    private final int mModelImpressNode;
+    private final int mSubspaceImpressNode;
+    @AnimationState private int mAnimationState = AnimationState.STOPPED;
 
-    public GltfEntityImplSplitEngine(
+    GltfEntityImplSplitEngine(
             GltfModelResourceImplSplitEngine gltfModelResource,
             Entity parentEntity,
             ImpressApi impressApi,
@@ -54,27 +54,26 @@
             EntityManager entityManager,
             ScheduledExecutorService executor) {
         super(extensions.createNode(), extensions, entityManager, executor);
-        this.impressApi = impressApi;
-        this.splitEngineSubspaceManager = splitEngineSubspaceManager;
+        mImpressApi = impressApi;
+        mSplitEngineSubspaceManager = splitEngineSubspaceManager;
         setParent(parentEntity);
 
         // TODO(b/377907379): - Punt this logic to the UI thread, so that applications can create
         // Gltf entities from any thread.
 
         // System will only render Impress nodes that are parented by this subspace node.
-        this.subspaceImpressNode = impressApi.createImpressNode();
-        String subspaceName = "gltf_entity_subspace_" + subspaceImpressNode;
+        mSubspaceImpressNode = impressApi.createImpressNode();
+        String subspaceName = "gltf_entity_subspace_" + mSubspaceImpressNode;
 
-        this.subspace =
-                splitEngineSubspaceManager.createSubspace(subspaceName, subspaceImpressNode);
+        mSubspace = splitEngineSubspaceManager.createSubspace(subspaceName, mSubspaceImpressNode);
 
         try (NodeTransaction transaction = extensions.createNodeTransaction()) {
             // Make the Entity node a parent of the subspace node.
-            transaction.setParent(subspace.subspaceNode, this.node).apply();
+            transaction.setParent(mSubspace.subspaceNode, mNode).apply();
         }
-        this.modelImpressNode =
+        mModelImpressNode =
                 impressApi.instanceGltfModel(gltfModelResource.getExtensionModelToken());
-        impressApi.setImpressNodeParent(modelImpressNode, subspaceImpressNode);
+        impressApi.setImpressNodeParent(mModelImpressNode, mSubspaceImpressNode);
         // The Impress node hierarchy is: Subspace Impress node --- parent of ---> model Impress
         // node.
         // The CPM node hierarchy is: Entity CPM node --- parent of ---> Subspace CPM node.
@@ -92,8 +91,8 @@
         // from
         // this method.
         ListenableFuture<Void> future =
-                impressApi.animateGltfModel(modelImpressNode, animationName, looping);
-        animationState = AnimationState.PLAYING;
+                mImpressApi.animateGltfModel(mModelImpressNode, animationName, looping);
+        mAnimationState = AnimationState.PLAYING;
 
         // At the moment, we don't do anything interesting on failure except for logging. If we
         // didn't
@@ -105,7 +104,7 @@
                     try {
                         future.get();
                         // The animation played to completion and has stopped
-                        animationState = AnimationState.STOPPED;
+                        mAnimationState = AnimationState.STOPPED;
                     } catch (Exception e) {
                         if (e instanceof InterruptedException) {
                             // If this happened, then it's likely Impress is shutting down and we
@@ -115,38 +114,38 @@
                         } else {
                             // Some other error happened.  Log it and stop the animation.
                             Log.e("GltfEntityImpl", "Could not start animation: " + e);
-                            animationState = AnimationState.STOPPED;
+                            mAnimationState = AnimationState.STOPPED;
                         }
                     }
                 },
-                this.executor);
+                mExecutor);
     }
 
     @Override
     public void stopAnimation() {
         // TODO(b/377907379): - Punt this logic to the UI thread.
-        impressApi.stopGltfModelAnimation(modelImpressNode);
-        animationState = AnimationState.STOPPED;
+        mImpressApi.stopGltfModelAnimation(mModelImpressNode);
+        mAnimationState = AnimationState.STOPPED;
     }
 
     @Override
     @AnimationState
     public int getAnimationState() {
-        return animationState;
+        return mAnimationState;
     }
 
     @SuppressWarnings("ObjectToString")
     @Override
     public void dispose() {
         // TODO(b/377907379): - Punt this logic to the UI thread.
-        splitEngineSubspaceManager.deleteSubspace(subspace.subspaceId);
-        impressApi.destroyImpressNode(modelImpressNode);
-        impressApi.destroyImpressNode(subspaceImpressNode);
+        mSplitEngineSubspaceManager.deleteSubspace(mSubspace.subspaceId);
+        mImpressApi.destroyImpressNode(mModelImpressNode);
+        mImpressApi.destroyImpressNode(mSubspaceImpressNode);
         super.dispose();
     }
 
     public void setColliderEnabled(boolean enableCollider) {
         // TODO(b/377907379): - Punt this logic to the UI thread
-        impressApi.setGltfModelColliderEnabled(modelImpressNode, enableCollider);
+        mImpressApi.setGltfModelColliderEnabled(mModelImpressNode, enableCollider);
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfModelResourceImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfModelResourceImpl.java
index 2dca9f2..175d95d 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfModelResourceImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfModelResourceImpl.java
@@ -25,13 +25,13 @@
  */
 @SuppressWarnings({"deprecation", "UnnecessarilyFullyQualified"}) // TODO(b/373435470): Remove
 final class GltfModelResourceImpl implements GltfModelResource {
-    private final androidx.xr.extensions.asset.GltfModelToken token;
+    private final androidx.xr.extensions.asset.GltfModelToken mToken;
 
-    public GltfModelResourceImpl(androidx.xr.extensions.asset.GltfModelToken token) {
-        this.token = token;
+    GltfModelResourceImpl(androidx.xr.extensions.asset.GltfModelToken token) {
+        mToken = token;
     }
 
     public androidx.xr.extensions.asset.GltfModelToken getExtensionModelToken() {
-        return token;
+        return mToken;
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfModelResourceImplSplitEngine.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfModelResourceImplSplitEngine.java
index 13681ef..25fe73e 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfModelResourceImplSplitEngine.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/GltfModelResourceImplSplitEngine.java
@@ -27,13 +27,13 @@
 // TODO: b/362368652 - Add an interface which returns an integer animation IDX given a string
 //                     animation name for a loaded GLTF.
 final class GltfModelResourceImplSplitEngine implements GltfModelResource {
-    private final long token;
+    private final long mToken;
 
-    public GltfModelResourceImplSplitEngine(long token) {
-        this.token = token;
+    GltfModelResourceImplSplitEngine(long token) {
+        mToken = token;
     }
 
     public long getExtensionModelToken() {
-        return token;
+        return mToken;
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/HeadActivityPoseImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/HeadActivityPoseImpl.java
index d1b9b59..293202d 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/HeadActivityPoseImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/HeadActivityPoseImpl.java
@@ -29,47 +29,46 @@
  * the user's head.
  */
 class HeadActivityPoseImpl extends BaseActivityPose implements HeadActivityPose {
-    private final PerceptionLibrary perceptionLibrary;
-    private final OpenXrActivityPoseHelper openXrActivityPoseHelper;
+    private final PerceptionLibrary mPerceptionLibrary;
+    private final OpenXrActivityPoseHelper mOpenXrActivityPoseHelper;
     // Default the pose to null. A null pose indicates that the head is not ready yet.
-    private Pose lastOpenXrPose = null;
+    private Pose mLastOpenXrPose = null;
 
-    public HeadActivityPoseImpl(
+    HeadActivityPoseImpl(
             ActivitySpaceImpl activitySpace,
             AndroidXrEntity activitySpaceRoot,
             PerceptionLibrary perceptionLibrary) {
-        this.perceptionLibrary = perceptionLibrary;
-        this.openXrActivityPoseHelper =
-                new OpenXrActivityPoseHelper(activitySpace, activitySpaceRoot);
+        mPerceptionLibrary = perceptionLibrary;
+        mOpenXrActivityPoseHelper = new OpenXrActivityPoseHelper(activitySpace, activitySpaceRoot);
     }
 
     @Override
     public Pose getPoseInActivitySpace() {
-        return openXrActivityPoseHelper.getPoseInActivitySpace(getPoseInOpenXrReferenceSpace());
+        return mOpenXrActivityPoseHelper.getPoseInActivitySpace(getPoseInOpenXrReferenceSpace());
     }
 
     @Override
     public Pose getActivitySpacePose() {
-        return openXrActivityPoseHelper.getActivitySpacePose(getPoseInOpenXrReferenceSpace());
+        return mOpenXrActivityPoseHelper.getActivitySpacePose(getPoseInOpenXrReferenceSpace());
     }
 
     @Override
     public Vector3 getActivitySpaceScale() {
         // This WorldPose is assumed to always have a scale of 1.0f in the OpenXR reference space.
-        return openXrActivityPoseHelper.getActivitySpaceScale(new Vector3(1f, 1f, 1f));
+        return mOpenXrActivityPoseHelper.getActivitySpaceScale(new Vector3(1f, 1f, 1f));
     }
 
     /** Gets the pose in the OpenXR reference space. Can be null if it is not yet ready. */
     @Nullable
     public Pose getPoseInOpenXrReferenceSpace() {
-        final Session session = perceptionLibrary.getSession();
+        final Session session = mPerceptionLibrary.getSession();
         if (session == null) {
-            return lastOpenXrPose;
+            return mLastOpenXrPose;
         }
         androidx.xr.scenecore.impl.perception.Pose perceptionHeadPose = session.getHeadPose();
         if (perceptionHeadPose != null) {
-            lastOpenXrPose = RuntimeUtils.fromPerceptionPose(perceptionHeadPose);
+            mLastOpenXrPose = RuntimeUtils.fromPerceptionPose(perceptionHeadPose);
         }
-        return lastOpenXrPose;
+        return mLastOpenXrPose;
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/InteractableComponentImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/InteractableComponentImpl.java
index f2d5118..b320c51 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/InteractableComponentImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/InteractableComponentImpl.java
@@ -26,27 +26,27 @@
 
 /** Implementation of [JxrPlatformAdapter.InteractableComponent]. */
 class InteractableComponentImpl implements InteractableComponent {
-    final InputEventListener consumer;
-    final Executor executor;
-    Entity entity;
+    final InputEventListener mConsumer;
+    final Executor mExecutor;
+    Entity mEntity;
 
     InteractableComponentImpl(Executor executor, InputEventListener consumer) {
-        this.consumer = consumer;
-        this.executor = executor;
+        mConsumer = consumer;
+        mExecutor = executor;
     }
 
     @Override
     public boolean onAttach(Entity entity) {
-        if (this.entity != null) {
-            Log.e("Runtime", "Already attached to entity " + this.entity);
+        if (mEntity != null) {
+            Log.e("Runtime", "Already attached to entity " + mEntity);
             return false;
         }
-        this.entity = entity;
+        mEntity = entity;
         if (entity instanceof GltfEntityImplSplitEngine) {
             ((GltfEntityImplSplitEngine) entity).setColliderEnabled(true);
         }
         // InputEvent type translation happens here.
-        entity.addInputEventListener(executor, consumer);
+        entity.addInputEventListener(mExecutor, mConsumer);
         return true;
     }
 
@@ -55,7 +55,7 @@
         if (entity instanceof GltfEntityImplSplitEngine) {
             ((GltfEntityImplSplitEngine) entity).setColliderEnabled(false);
         }
-        entity.removeInputEventListener(consumer);
-        this.entity = null;
+        entity.removeInputEventListener(mConsumer);
+        mEntity = null;
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/JxrPlatformAdapterAxr.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/JxrPlatformAdapterAxr.java
index 47da4bd..546b33f 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/JxrPlatformAdapterAxr.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/JxrPlatformAdapterAxr.java
@@ -86,40 +86,40 @@
     private static final String TAG = "JxrPlatformAdapterAxr";
     private static final String SPLIT_ENGINE_LIBRARY_NAME = "impress_api_jni";
 
-    private final ActivitySpaceImpl activitySpace;
-    private final HeadActivityPoseImpl headActivityPose;
-    private final PerceptionSpaceActivityPoseImpl perceptionSpaceActivityPose;
-    private final List<CameraViewActivityPoseImpl> cameraActivityPoses = new ArrayList<>();
-    private final ScheduledExecutorService executor;
-    private final XrExtensions extensions;
+    private final ActivitySpaceImpl mActivitySpace;
+    private final HeadActivityPoseImpl mHeadActivityPose;
+    private final PerceptionSpaceActivityPoseImpl mPerceptionSpaceActivityPose;
+    private final List<CameraViewActivityPoseImpl> mCameraActivityPoses = new ArrayList<>();
+    private final ScheduledExecutorService mExecutor;
+    private final XrExtensions mExtensions;
 
-    private final SoundPoolExtensionsWrapper soundPoolExtensionsWrapper;
-    private final AudioTrackExtensionsWrapper audioTrackExtensionsWrapper;
-    private final MediaPlayerExtensionsWrapper mediaPlayerExtensionsWrapper;
+    private final SoundPoolExtensionsWrapper mSoundPoolExtensionsWrapper;
+    private final AudioTrackExtensionsWrapper mAudioTrackExtensionsWrapper;
+    private final MediaPlayerExtensionsWrapper mMediaPlayerExtensionsWrapper;
 
-    private final PerceptionLibrary perceptionLibrary;
-    private final SpatialEnvironmentImpl environment;
-    private final boolean useSplitEngine;
-    private final Node taskWindowLeashNode;
-    private final int openXrReferenceSpaceType;
-    private final EntityManager entityManager;
-    private final PanelEntity mainPanelEntity;
-    private final ImpressApi impressApi;
-    private final Map<Consumer<SpatialCapabilities>, Executor> spatialCapabilitiesChangedListeners =
-            new ConcurrentHashMap<>();
+    private final PerceptionLibrary mPerceptionLibrary;
+    private final SpatialEnvironmentImpl mEnvironment;
+    private final boolean mUseSplitEngine;
+    private final Node mTaskWindowLeashNode;
+    private final int mOpenXrReferenceSpaceType;
+    private final EntityManager mEntityManager;
+    private final PanelEntity mMainPanelEntity;
+    private final ImpressApi mImpressApi;
+    private final Map<Consumer<SpatialCapabilities>, Executor>
+            mSpatialCapabilitiesChangedListeners = new ConcurrentHashMap<>();
 
-    @Nullable private Activity activity;
-    private SplitEngineSubspaceManager splitEngineSubspaceManager;
-    private ImpSplitEngineRenderer splitEngineRenderer;
-    private boolean frameLoopStarted;
+    @Nullable private Activity mActivity;
+    private SplitEngineSubspaceManager mSplitEngineSubspaceManager;
+    private ImpSplitEngineRenderer mSplitEngineRenderer;
+    private boolean mFrameLoopStarted;
 
     // TODO b/373481538: remove lazy initialization once XR Extensions bug is fixed. This will allow
     // us to remove the lazySpatialStateProvider instance and pass the spatialState directly.
-    private final AtomicReference<SpatialState> spatialState = new AtomicReference<>(null);
+    private final AtomicReference<SpatialState> mSpatialState = new AtomicReference<>(null);
 
     // Returns the currently-known spatial state, or fetches it from the extensions if it has never
     // been set. The spatial state is kept updated in the SpatialStateCallback.
-    private final Supplier<SpatialState> lazySpatialStateProvider;
+    private final Supplier<SpatialState> mLazySpatialStateProvider;
 
     private JxrPlatformAdapterAxr(
             Activity activity,
@@ -133,102 +133,103 @@
             Node rootSceneNode,
             Node taskWindowLeashNode,
             boolean useSplitEngine) {
-        this.activity = activity;
-        this.executor = executor;
-        this.extensions = extensions;
+        mActivity = activity;
+        mExecutor = executor;
+        mExtensions = extensions;
 
-        this.lazySpatialStateProvider =
+        mLazySpatialStateProvider =
                 () ->
-                        spatialState.updateAndGet(
+                        mSpatialState.updateAndGet(
                                 oldSpatialState -> {
                                     if (oldSpatialState == null) {
-                                        oldSpatialState = this.extensions.getSpatialState(activity);
+                                        oldSpatialState = mExtensions.getSpatialState(activity);
                                     }
                                     return oldSpatialState;
                                 });
         setSpatialStateCallback();
 
-        soundPoolExtensionsWrapper =
+        mSoundPoolExtensionsWrapper =
                 new SoundPoolExtensionsWrapperImpl(
                         extensions.getXrSpatialAudioExtensions().getSoundPoolExtensions());
-        audioTrackExtensionsWrapper =
+        mAudioTrackExtensionsWrapper =
                 new AudioTrackExtensionsWrapperImpl(
                         extensions.getXrSpatialAudioExtensions().getAudioTrackExtensions(),
                         entityManager);
-        mediaPlayerExtensionsWrapper =
+        mMediaPlayerExtensionsWrapper =
                 new MediaPlayerExtensionsWrapperImpl(
                         extensions.getXrSpatialAudioExtensions().getMediaPlayerExtensions());
-        this.entityManager = entityManager;
-        this.perceptionLibrary = perceptionLibrary;
-        this.taskWindowLeashNode = taskWindowLeashNode;
-        this.environment =
+        mEntityManager = entityManager;
+        mPerceptionLibrary = perceptionLibrary;
+        mTaskWindowLeashNode = taskWindowLeashNode;
+        mEnvironment =
                 new SpatialEnvironmentImpl(
                         activity,
                         extensions,
                         rootSceneNode,
-                        lazySpatialStateProvider,
+                        mLazySpatialStateProvider,
                         useSplitEngine);
-        this.activitySpace =
+        mActivitySpace =
                 new ActivitySpaceImpl(
                         rootSceneNode,
                         extensions,
                         entityManager,
-                        lazySpatialStateProvider,
+                        mLazySpatialStateProvider,
                         executor);
-        this.headActivityPose =
+        mHeadActivityPose =
                 new HeadActivityPoseImpl(
-                        activitySpace,
+                        mActivitySpace,
                         (AndroidXrEntity) getActivitySpaceRootImpl(),
                         perceptionLibrary);
-        this.perceptionSpaceActivityPose =
+        mPerceptionSpaceActivityPose =
                 new PerceptionSpaceActivityPoseImpl(
-                        activitySpace, (AndroidXrEntity) getActivitySpaceRootImpl());
-        this.cameraActivityPoses.add(
+                        mActivitySpace, (AndroidXrEntity) getActivitySpaceRootImpl());
+        mCameraActivityPoses.add(
                 new CameraViewActivityPoseImpl(
                         CameraViewActivityPose.CAMERA_TYPE_LEFT_EYE,
-                        activitySpace,
+                        mActivitySpace,
                         (AndroidXrEntity) getActivitySpaceRootImpl(),
                         perceptionLibrary));
-        this.cameraActivityPoses.add(
+        mCameraActivityPoses.add(
                 new CameraViewActivityPoseImpl(
                         CameraViewActivityPose.CAMERA_TYPE_RIGHT_EYE,
-                        activitySpace,
+                        mActivitySpace,
                         (AndroidXrEntity) getActivitySpaceRootImpl(),
                         perceptionLibrary));
-        this.useSplitEngine = useSplitEngine;
-        this.openXrReferenceSpaceType = extensions.getOpenXrWorldSpaceType();
+        mUseSplitEngine = useSplitEngine;
+        mOpenXrReferenceSpaceType = extensions.getOpenXrWorldSpaceType();
 
-        this.mainPanelEntity =
+        mMainPanelEntity =
                 new MainPanelEntityImpl(
                         activity, taskWindowLeashNode, extensions, entityManager, executor);
-        this.mainPanelEntity.setParent(activitySpace);
+        mMainPanelEntity.setParent(mActivitySpace);
 
         // TODO:b/377918731 - Move this logic into factories and inject SE into the constructor
         if (impressApi == null) {
             // TODO: b/370116937) - Check against useSplitEngine as well and don't load this if
             //                      SplitEngine is disabled.
-            this.impressApi = new ImpressApiImpl();
+            mImpressApi = new ImpressApiImpl();
         } else {
-            this.impressApi = impressApi;
+            mImpressApi = impressApi;
         }
 
         if (useSplitEngine && subspaceManager == null && renderer == null) {
             ImpSplitEngine.SplitEngineSetupParams impApiSetupParams =
                     new ImpSplitEngine.SplitEngineSetupParams();
             impApiSetupParams.jniLibraryName = SPLIT_ENGINE_LIBRARY_NAME;
-            this.splitEngineRenderer = ImpSplitEngineRenderer.create(activity, impApiSetupParams);
+            mSplitEngineRenderer = ImpSplitEngineRenderer.create(activity, impApiSetupParams);
             startRenderer();
-            this.splitEngineSubspaceManager =
+            mSplitEngineSubspaceManager =
                     new SplitEngineSubspaceManager(
-                            this.splitEngineRenderer,
+                            mSplitEngineRenderer,
                             rootSceneNode,
                             taskWindowLeashNode,
                             SPLIT_ENGINE_LIBRARY_NAME);
-            this.impressApi.setup(splitEngineRenderer.getView());
-            environment.onSplitEngineReady(this.splitEngineSubspaceManager, this.impressApi);
+            mImpressApi.setup(mSplitEngineRenderer.getView());
+            mEnvironment.onSplitEngineReady(mSplitEngineSubspaceManager, mImpressApi);
         }
     }
 
+    /** Create a new @c JxrPlatformAdapterAxr. */
     @NonNull
     public static JxrPlatformAdapterAxr create(
             @NonNull Activity activity, @NonNull ScheduledExecutorService executor) {
@@ -244,6 +245,7 @@
                 /* useSplitEngine= */ true);
     }
 
+    /** Create a new @c JxrPlatformAdapterAxr. */
     @NonNull
     public static JxrPlatformAdapterAxr create(
             @NonNull Activity activity,
@@ -261,6 +263,7 @@
                 useSplitEngine);
     }
 
+    /** Create a new @c JxrPlatformAdapterAxr. */
     @NonNull
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
     public static JxrPlatformAdapterAxr create(
@@ -282,6 +285,7 @@
                 /* useSplitEngine= */ false);
     }
 
+    /** Create a new @c JxrPlatformAdapterAxr. */
     @NonNull
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
     public static JxrPlatformAdapterAxr create(
@@ -396,7 +400,7 @@
     @VisibleForTesting
     synchronized void onSpatialStateChanged(
             @NonNull androidx.xr.extensions.space.SpatialState newSpatialState) {
-        SpatialState previousSpatialState = this.spatialState.getAndSet(newSpatialState);
+        SpatialState previousSpatialState = mSpatialState.getAndSet(newSpatialState);
 
         boolean spatialCapabilitiesChanged =
                 previousSpatialState == null
@@ -409,7 +413,7 @@
                         || !newSpatialState.getBounds().equals(previousSpatialState.getBounds());
 
         EnumSet<SpatialEnvironmentImpl.ChangedSpatialStates> changedSpatialStates =
-                environment.setSpatialState(newSpatialState);
+                mEnvironment.setSpatialState(newSpatialState);
         boolean environmentVisibilityChanged =
                 changedSpatialStates.contains(
                         SpatialEnvironmentImpl.ChangedSpatialStates.ENVIRONMENT_CHANGED);
@@ -419,12 +423,12 @@
 
         // Fire the state change events only after all the states have been updated.
         if (environmentVisibilityChanged) {
-            environment.fireOnSpatialEnvironmentChangedEvent(
-                    environment.isSpatialEnvironmentPreferenceActive());
+            mEnvironment.fireOnSpatialEnvironmentChangedEvent(
+                    mEnvironment.isSpatialEnvironmentPreferenceActive());
         }
         if (passthroughVisibilityChanged) {
-            environment.firePassthroughOpacityChangedEvent(
-                    environment.getCurrentPassthroughOpacity());
+            mEnvironment.firePassthroughOpacityChangedEvent(
+                    mEnvironment.getCurrentPassthroughOpacity());
         }
 
         if (spatialCapabilitiesChanged) {
@@ -432,29 +436,29 @@
                     RuntimeUtils.convertSpatialCapabilities(
                             newSpatialState.getSpatialCapabilities());
 
-            spatialCapabilitiesChangedListeners.forEach(
+            mSpatialCapabilitiesChangedListeners.forEach(
                     (listener, executor) ->
                             executor.execute(() -> listener.accept(spatialCapabilities)));
         }
 
         if (hasBoundsChanged) {
-            activitySpace.onBoundsChanged(newSpatialState.getBounds());
+            mActivitySpace.onBoundsChanged(newSpatialState.getBounds());
         }
     }
 
     private void setSpatialStateCallback() {
         Handler mainHandler = new Handler(Looper.getMainLooper());
-        extensions.registerSpatialStateCallback(
-                activity, this::onSpatialStateChanged, mainHandler::post);
+        mExtensions.registerSpatialStateCallback(
+                mActivity, this::onSpatialStateChanged, mainHandler::post);
     }
 
     private synchronized void initPerceptionLibrary() {
-        if (perceptionLibrary.getSession() != null) {
+        if (mPerceptionLibrary.getSession() != null) {
             Log.w(TAG, "Cannot init perception session, already initialized.");
             return;
         }
         ListenableFuture<Session> sessionFuture =
-                perceptionLibrary.initSession(activity, openXrReferenceSpaceType, executor);
+                mPerceptionLibrary.initSession(mActivity, mOpenXrReferenceSpaceType, mExecutor);
         Objects.requireNonNull(sessionFuture)
                 .addListener(
                         () -> {
@@ -470,26 +474,26 @@
                                                 + e.getMessage());
                             }
                         },
-                        executor);
+                        mExecutor);
     }
 
     @Override
     @NonNull
     public SpatialCapabilities getSpatialCapabilities() {
         return RuntimeUtils.convertSpatialCapabilities(
-                lazySpatialStateProvider.get().getSpatialCapabilities());
+                mLazySpatialStateProvider.get().getSpatialCapabilities());
     }
 
     @Override
     public void addSpatialCapabilitiesChangedListener(
             @NonNull Executor executor, @NonNull Consumer<SpatialCapabilities> listener) {
-        spatialCapabilitiesChangedListeners.put(listener, executor);
+        mSpatialCapabilitiesChangedListeners.put(listener, executor);
     }
 
     @Override
     public void removeSpatialCapabilitiesChangedListener(
             @NonNull Consumer<SpatialCapabilities> listener) {
-        spatialCapabilitiesChangedListeners.remove(listener);
+        mSpatialCapabilitiesChangedListeners.remove(listener);
     }
 
     @Override
@@ -503,23 +507,23 @@
     @Override
     @NonNull
     public SpatialEnvironment getSpatialEnvironment() {
-        return environment;
+        return mEnvironment;
     }
 
     @Override
     @NonNull
     public ActivitySpace getActivitySpace() {
-        return activitySpace;
+        return mActivitySpace;
     }
 
     @Override
     @Nullable
     public HeadActivityPose getHeadActivityPose() {
         // If it is unable to retrieve a pose the head in not yet loaded in openXR so return null.
-        if (headActivityPose.getPoseInOpenXrReferenceSpace() == null) {
+        if (mHeadActivityPose.getPoseInOpenXrReferenceSpace() == null) {
             return null;
         }
-        return headActivityPose;
+        return mHeadActivityPose;
     }
 
     @Override
@@ -528,9 +532,9 @@
             @CameraViewActivityPose.CameraType int cameraType) {
         CameraViewActivityPoseImpl cameraViewActivityPose = null;
         if (cameraType == CameraViewActivityPose.CAMERA_TYPE_LEFT_EYE) {
-            cameraViewActivityPose = cameraActivityPoses.get(0);
+            cameraViewActivityPose = mCameraActivityPoses.get(0);
         } else if (cameraType == CameraViewActivityPose.CAMERA_TYPE_RIGHT_EYE) {
-            cameraViewActivityPose = cameraActivityPoses.get(1);
+            cameraViewActivityPose = mCameraActivityPoses.get(1);
         }
         // If it is unable to retrieve a pose the camera in not yet loaded in openXR so return null.
         if (cameraViewActivityPose == null
@@ -543,13 +547,16 @@
     @Override
     @NonNull
     public PerceptionSpaceActivityPose getPerceptionSpaceActivityPose() {
-        return perceptionSpaceActivityPose;
+        return mPerceptionSpaceActivityPose;
     }
 
+    /**
+     * Get the user's current head pose relative to @c XR_REFERENCE_SPACE_TYPE_UNBOUNDED_ANDROID.
+     */
     // TODO(b/349180723): Refactor to a streaming based approach.
     @Nullable
     public Pose getHeadPoseInOpenXrUnboundedSpace() {
-        Session session = perceptionLibrary.getSession();
+        Session session = mPerceptionLibrary.getSession();
         if (session == null) {
             Log.w(TAG, "Perception session is uninitialized, returning null head pose.");
             return null;
@@ -557,9 +564,12 @@
         return RuntimeUtils.fromPerceptionPose(Objects.requireNonNull(session.getHeadPose()));
     }
 
+    /**
+     * Get the user's current eye views relative to @c XR_REFERENCE_SPACE_TYPE_UNBOUNDED_ANDROID.
+     */
     @Nullable
     public ViewProjections getStereoViewsInOpenXrUnboundedSpace() {
-        Session session = perceptionLibrary.getSession();
+        Session session = mPerceptionLibrary.getSession();
         if (session == null) {
             Log.w(TAG, "Perception session is uninitialized, returning null head pose.");
             return null;
@@ -575,21 +585,21 @@
         // and
         // will be the default parent for new content entities.
 
-        return activitySpace;
+        return mActivitySpace;
     }
 
     @Override
     public void requestFullSpaceMode() {
         // TODO: b/376934871 - Check async results.
-        extensions.requestFullSpaceMode(
-                activity, /* requestEnter= */ true, (result) -> {}, Runnable::run);
+        mExtensions.requestFullSpaceMode(
+                mActivity, /* requestEnter= */ true, (result) -> {}, Runnable::run);
     }
 
     @Override
     public void requestHomeSpaceMode() {
         // TODO: b/376934871 - Check async results.
-        extensions.requestFullSpaceMode(
-                activity, /* requestEnter= */ false, (result) -> {}, Runnable::run);
+        mExtensions.requestFullSpaceMode(
+                mActivity, /* requestEnter= */ false, (result) -> {}, Runnable::run);
     }
 
     // TODO: b/374345896 - Delete this method once we've finalized the SplitEngine migration.
@@ -605,7 +615,7 @@
         ResolvableFuture<GltfModelResource> gltfModelResourceFuture = ResolvableFuture.create();
         InputStream asset;
         try {
-            asset = activity.getAssets().open(assetName);
+            asset = mActivity.getAssets().open(assetName);
         } catch (Exception e) {
             Log.w(TAG, "Could not open asset with error: " + e.getMessage());
             return null;
@@ -613,7 +623,7 @@
 
         CompletableFuture<androidx.xr.extensions.asset.GltfModelToken> tokenFuture;
         try {
-            tokenFuture = extensions.loadGltfModel(asset, asset.available(), 0, assetName);
+            tokenFuture = mExtensions.loadGltfModel(asset, asset.available(), 0, assetName);
             // Unfortunately, there is no way to avoid "leaking" this future, since we want to
             // return a
             // ListenableFuture. This should be a short lived problem since clients should be using
@@ -648,7 +658,7 @@
 
         ListenableFuture<Long> gltfTokenFuture;
         try {
-            gltfTokenFuture = impressApi.loadGltfModel(name);
+            gltfTokenFuture = mImpressApi.loadGltfModel(name);
         } catch (RuntimeException e) {
             Log.e(TAG, "Failed to load glTF model with error: " + e.getMessage());
             // TODO:b/375070346 - make this method NonNull and set the gltfModelResourceFuture to an
@@ -680,7 +690,7 @@
                 // cause a
                 // thread hop because the Impress API already dispatches its callbacks to the main
                 // thread.
-                activity::runOnUiThread);
+                mActivity::runOnUiThread);
         return gltfModelResourceFuture;
     }
 
@@ -698,7 +708,7 @@
         InputStream asset;
         try {
             // NOTE: extensions.loadEnvironment expects a .EXR file.
-            asset = activity.getAssets().open(assetName);
+            asset = mActivity.getAssets().open(assetName);
         } catch (Exception e) {
             Log.w(TAG, "Could not open asset with error: " + e.getMessage());
             return null;
@@ -709,7 +719,7 @@
             // NOTE: At the moment, extensions.loadEnvironment expects a .EXR file explicitly. This
             //       will need to be updated as support for GLTF environment geometry is added by
             //       the system.
-            tokenFuture = extensions.loadEnvironment(asset, asset.available(), 0, assetName);
+            tokenFuture = mExtensions.loadEnvironment(asset, asset.available(), 0, assetName);
             // Unfortunately, there is no way to avoid "leaking" this future, since we want to
             // return a
             // ListenableFuture. This method should be deleted soon, once the SplitEngine backed
@@ -730,7 +740,7 @@
     @NonNull
     public GltfEntity createGltfEntity(
             @NonNull Pose pose, @NonNull GltfModelResource model, @Nullable Entity parentEntity) {
-        if (useSplitEngine && model instanceof GltfModelResourceImplSplitEngine) {
+        if (mUseSplitEngine && model instanceof GltfModelResourceImplSplitEngine) {
             return createGltfEntitySplitEngine(pose, model, parentEntity);
         }
         if (parentEntity == null) {
@@ -743,9 +753,9 @@
                 new GltfEntityImpl(
                         (GltfModelResourceImpl) model,
                         parentEntity,
-                        extensions,
-                        entityManager,
-                        executor);
+                        mExtensions,
+                        mEntityManager,
+                        mExecutor);
         entity.setPose(pose);
         return entity;
     }
@@ -757,12 +767,11 @@
             @NonNull Dimensions dimensions,
             @NonNull Pose pose,
             @NonNull Entity parentEntity) {
-        if (useSplitEngine) {
+        if (mUseSplitEngine) {
             return createStereoSurfaceEntitySplitEngine(stereoMode, dimensions, pose, parentEntity);
         } else {
-            // TODO: b/377983872 - Throw UnsupportedOperationException here.
-            Log.w(TAG, "stereo surface only works with split engine.");
-            return new StereoSurfaceEntityImpl(parentEntity, extensions, entityManager, executor);
+            throw new UnsupportedOperationException(
+                    "StereoSurfaceEntity is not supported without SplitEngine.");
         }
     }
 
@@ -783,11 +792,11 @@
                 new SurfaceControlViewHost(
                         context, Objects.requireNonNull(context.getDisplay()), new Binder());
         surfaceControlViewHost.setView(view, surfaceDimensionsPx.width, surfaceDimensionsPx.height);
-        Node node = extensions.createNode();
+        Node node = mExtensions.createNode();
         SurfacePackage surfacePackage =
                 Objects.requireNonNull(surfaceControlViewHost.getSurfacePackage());
 
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
             transaction
                     .setName(node, name)
                     .setSurfacePackage(node, surfacePackage)
@@ -804,11 +813,11 @@
         PanelEntity panelEntity =
                 new PanelEntityImpl(
                         node,
-                        extensions,
-                        entityManager,
+                        mExtensions,
+                        mEntityManager,
                         surfaceControlViewHost,
                         surfaceDimensionsPx,
-                        executor);
+                        mExecutor);
         panelEntity.setParent(parent);
         panelEntity.setPose(pose);
         return panelEntity;
@@ -817,10 +826,10 @@
     @Override
     @NonNull
     public PanelEntity getMainPanelEntity() {
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-            transaction.setVisibility(taskWindowLeashNode, true).apply();
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
+            transaction.setVisibility(mTaskWindowLeashNode, true).apply();
         }
-        return mainPanelEntity;
+        return mMainPanelEntity;
     }
 
     @Override
@@ -843,15 +852,15 @@
                 scaleInZ,
                 anchorPlacement,
                 shouldDisposeParentAnchor,
-                perceptionLibrary,
-                extensions,
-                activitySpace,
+                mPerceptionLibrary,
+                mExtensions,
+                mActivitySpace,
                 (AndroidXrEntity) getActivitySpaceRootImpl(),
-                perceptionSpaceActivityPose,
-                entityManager,
+                mPerceptionSpaceActivityPose,
+                mEntityManager,
                 new PanelShadowRenderer(
-                        activitySpace, perceptionSpaceActivityPose, activity, extensions),
-                executor);
+                        mActivitySpace, mPerceptionSpaceActivityPose, mActivity, mExtensions),
+                mExecutor);
     }
 
     @Override
@@ -860,8 +869,8 @@
             @NonNull Set<PlaneType> planeTypeFilter,
             @NonNull Set<PlaneSemantic> planeSemanticFilter) {
         AnchorPlacementImpl anchorPlacement = new AnchorPlacementImpl();
-        anchorPlacement.planeTypeFilter.addAll(planeTypeFilter);
-        anchorPlacement.planeSemanticFilter.addAll(planeSemanticFilter);
+        anchorPlacement.mPlaneTypeFilter.addAll(planeTypeFilter);
+        anchorPlacement.mPlaneSemanticFilter.addAll(planeSemanticFilter);
         return anchorPlacement;
     }
 
@@ -869,7 +878,7 @@
     @NonNull
     public ResizableComponent createResizableComponent(
             @NonNull Dimensions minimumSize, @NonNull Dimensions maximumSize) {
-        return new ResizableComponentImpl(executor, extensions, minimumSize, maximumSize);
+        return new ResizableComponentImpl(mExecutor, mExtensions, minimumSize, maximumSize);
     }
 
     @Override
@@ -895,9 +904,9 @@
         // TODO(b/352630140): Move this into a static factory method of ActivityPanelEntityImpl.
         Rect windowBoundsRect = new Rect(0, 0, windowBoundsPx.width, windowBoundsPx.height);
         ActivityPanel activityPanel =
-                extensions.createActivityPanel(
+                mExtensions.createActivityPanel(
                         hostActivity, new ActivityPanelLaunchParameters(windowBoundsRect));
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
             transaction
                     .setVisibility(activityPanel.getNode(), true)
                     .setName(activityPanel.getNode(), name)
@@ -910,11 +919,11 @@
         ActivityPanelEntityImpl activityPanelEntity =
                 new ActivityPanelEntityImpl(
                         activityPanel.getNode(),
-                        extensions,
-                        entityManager,
+                        mExtensions,
+                        mEntityManager,
                         activityPanel,
                         windowBoundsPx,
-                        executor);
+                        mExecutor);
         activityPanelEntity.setParent(parent);
         activityPanelEntity.setPose(pose);
         return activityPanelEntity;
@@ -927,7 +936,7 @@
             @NonNull PlaneType planeType,
             @NonNull PlaneSemantic planeSemantic,
             @NonNull Duration searchTimeout) {
-        Node node = extensions.createNode();
+        Node node = mExtensions.createNode();
         return AnchorEntityImpl.createSemanticAnchor(
                 node,
                 bounds,
@@ -936,37 +945,37 @@
                 searchTimeout,
                 getActivitySpace(),
                 getActivitySpaceRootImpl(),
-                extensions,
-                entityManager,
-                executor,
-                perceptionLibrary);
+                mExtensions,
+                mEntityManager,
+                mExecutor,
+                mPerceptionLibrary);
     }
 
     @Override
     @NonNull
     public AnchorEntity createAnchorEntity(@NonNull Anchor anchor) {
-        Node node = extensions.createNode();
+        Node node = mExtensions.createNode();
         return AnchorEntityImpl.createAnchorFromPerceptionAnchor(
                 node,
                 anchor,
                 getActivitySpace(),
                 getActivitySpaceRootImpl(),
-                extensions,
-                entityManager,
-                executor,
-                perceptionLibrary);
+                mExtensions,
+                mEntityManager,
+                mExecutor,
+                mPerceptionLibrary);
     }
 
     @Override
     @NonNull
     public Entity createEntity(@NonNull Pose pose, @NonNull String name, @NonNull Entity parent) {
-        Node node = extensions.createNode();
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
+        Node node = mExtensions.createNode();
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
             transaction.setName(node, name).apply();
         }
 
         // This entity is used to back JXR Core's ContentlessEntity.
-        Entity entity = new AndroidXrEntity(node, extensions, entityManager, executor) {};
+        Entity entity = new AndroidXrEntity(node, mExtensions, mEntityManager, mExecutor) {};
         entity.setParent(parent);
         entity.setPose(pose);
         return entity;
@@ -976,22 +985,22 @@
     @NonNull
     public AnchorEntity createPersistedAnchorEntity(
             @NonNull UUID uuid, @NonNull Duration searchTimeout) {
-        Node node = extensions.createNode();
+        Node node = mExtensions.createNode();
         return AnchorEntityImpl.createPersistedAnchor(
                 node,
                 uuid,
                 searchTimeout,
                 getActivitySpace(),
                 getActivitySpaceRootImpl(),
-                extensions,
-                entityManager,
-                executor,
-                perceptionLibrary);
+                mExtensions,
+                mEntityManager,
+                mExecutor,
+                mPerceptionLibrary);
     }
 
     @Override
     public boolean unpersistAnchor(@NonNull UUID uuid) {
-        Session session = perceptionLibrary.getSession();
+        Session session = mPerceptionLibrary.getSession();
         if (session == null) {
             Log.w(TAG, "Cannot unpersist anchor, perception session is not initialized.");
             return false;
@@ -1002,76 +1011,77 @@
     @Override
     @NonNull
     public Bundle setFullSpaceMode(@NonNull Bundle bundle) {
-        return extensions.setFullSpaceMode(bundle);
+        return mExtensions.setFullSpaceMode(bundle);
     }
 
     @Override
     @NonNull
     public Bundle setFullSpaceModeWithEnvironmentInherited(@NonNull Bundle bundle) {
-        return extensions.setFullSpaceModeWithEnvironmentInherited(bundle);
+        return mExtensions.setFullSpaceModeWithEnvironmentInherited(bundle);
     }
 
     @Override
     public void setPreferredAspectRatio(@NonNull Activity activity, float preferredRatio) {
         // TODO: b/376934871 - Check async results.
-        extensions.setPreferredAspectRatio(activity, preferredRatio, (result) -> {}, Runnable::run);
+        mExtensions.setPreferredAspectRatio(
+                activity, preferredRatio, (result) -> {}, Runnable::run);
     }
 
     @Override
     public void startRenderer() {
-        if (splitEngineRenderer == null || frameLoopStarted) {
+        if (mSplitEngineRenderer == null || mFrameLoopStarted) {
             return;
         }
-        frameLoopStarted = true;
-        splitEngineRenderer.startFrameLoop();
+        mFrameLoopStarted = true;
+        mSplitEngineRenderer.startFrameLoop();
     }
 
     @Override
     public void stopRenderer() {
-        if (splitEngineRenderer == null || !frameLoopStarted) {
+        if (mSplitEngineRenderer == null || !mFrameLoopStarted) {
             return;
         }
-        frameLoopStarted = false;
-        splitEngineRenderer.stopFrameLoop();
+        mFrameLoopStarted = false;
+        mSplitEngineRenderer.stopFrameLoop();
     }
 
     @Override
     public void dispose() {
         Log.i(TAG, "Disposing resources");
-        environment.dispose();
-        extensions.clearSpatialStateCallback(activity);
+        mEnvironment.dispose();
+        mExtensions.clearSpatialStateCallback(mActivity);
         // TODO: b/376934871 - Check async results.
-        extensions.detachSpatialScene(activity, (result) -> {}, Runnable::run);
-        activity = null;
-        entityManager.getAllEntities().forEach(Entity::dispose);
-        entityManager.clear();
-        if (splitEngineRenderer != null && splitEngineSubspaceManager != null) {
-            splitEngineRenderer.destroy();
-            splitEngineSubspaceManager.destroy();
+        mExtensions.detachSpatialScene(mActivity, (result) -> {}, Runnable::run);
+        mActivity = null;
+        mEntityManager.getAllEntities().forEach(Entity::dispose);
+        mEntityManager.clear();
+        if (mSplitEngineRenderer != null && mSplitEngineSubspaceManager != null) {
+            mSplitEngineRenderer.destroy();
+            mSplitEngineSubspaceManager.destroy();
         }
     }
 
     public void setSplitEngineSubspaceManager(
             @Nullable SplitEngineSubspaceManager splitEngineSubspaceManager) {
-        this.splitEngineSubspaceManager = splitEngineSubspaceManager;
+        mSplitEngineSubspaceManager = splitEngineSubspaceManager;
     }
 
     @Override
     @NonNull
     public SoundPoolExtensionsWrapper getSoundPoolExtensionsWrapper() {
-        return soundPoolExtensionsWrapper;
+        return mSoundPoolExtensionsWrapper;
     }
 
     @Override
     @NonNull
     public AudioTrackExtensionsWrapper getAudioTrackExtensionsWrapper() {
-        return audioTrackExtensionsWrapper;
+        return mAudioTrackExtensionsWrapper;
     }
 
     @Override
     @NonNull
     public MediaPlayerExtensionsWrapper getMediaPlayerExtensionsWrapper() {
-        return mediaPlayerExtensionsWrapper;
+        return mMediaPlayerExtensionsWrapper;
     }
 
     /**
@@ -1083,7 +1093,7 @@
      * @return the OpenXR XrSession, encoded in a jlong
      */
     public long getNativeSession() {
-        Session session = perceptionLibrary.getSession();
+        Session session = mPerceptionLibrary.getSession();
         if (session == null) {
             Log.w(TAG, "Perception session is uninitilazied, returning XR_NULL_HANDLE");
             return Session.XR_NULL_HANDLE;
@@ -1107,7 +1117,7 @@
      * @return the OpenXR XrInstance, encoded in a jlong
      */
     public long getNativeInstance() {
-        Session session = perceptionLibrary.getSession();
+        Session session = mPerceptionLibrary.getSession();
         if (session == null) {
             Log.w(TAG, "Perception session is uninitilazied, returning XR_NULL_HANDLE");
             return Session.XR_NULL_HANDLE;
@@ -1135,11 +1145,11 @@
         StereoSurfaceEntity entity =
                 new StereoSurfaceEntitySplitEngineImpl(
                         parentEntity,
-                        impressApi,
-                        splitEngineSubspaceManager,
-                        extensions,
-                        entityManager,
-                        executor,
+                        mImpressApi,
+                        mSplitEngineSubspaceManager,
+                        mExtensions,
+                        mEntityManager,
+                        mExecutor,
                         stereoMode);
         entity.setPose(pose);
         entity.setDimensions(dimensions);
@@ -1163,11 +1173,11 @@
                 new GltfEntityImplSplitEngine(
                         (GltfModelResourceImplSplitEngine) model,
                         parentEntity,
-                        impressApi,
-                        splitEngineSubspaceManager,
-                        extensions,
-                        entityManager,
-                        executor);
+                        mImpressApi,
+                        mSplitEngineSubspaceManager,
+                        mExtensions,
+                        mEntityManager,
+                        mExecutor);
         entity.setPose(pose);
         return entity;
     }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/LoggingEntityImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/LoggingEntityImpl.java
index 2c1487b..15fc13d 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/LoggingEntityImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/LoggingEntityImpl.java
@@ -34,7 +34,7 @@
 
     private static final String TAG = "RealityCoreRuntime";
 
-    public LoggingEntityImpl() {
+    LoggingEntityImpl() {
         Log.i(TAG, "Creating LoggingEntity.");
     }
 
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/MainPanelEntityImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/MainPanelEntityImpl.java
index 3d4c32a..dff60b7 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/MainPanelEntityImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/MainPanelEntityImpl.java
@@ -35,7 +35,7 @@
  */
 @SuppressWarnings("deprecation") // TODO(b/373435470): Remove
 final class MainPanelEntityImpl extends BasePanelEntity implements PanelEntity {
-    Activity runtimeActivity;
+    Activity mRuntimeActivity;
 
     // Note that we expect the Node supplied here to be the WindowLeash node.
     MainPanelEntityImpl(
@@ -45,7 +45,7 @@
             EntityManager entityManager,
             ScheduledExecutorService executor) {
         super(node, extensions, entityManager, executor);
-        runtimeActivity = activity;
+        mRuntimeActivity = activity;
 
         // Read the Pixel dimensions for the primary panel off the Activity's WindowManager.
         //   Note that this requires MinAPI 30.
@@ -55,7 +55,7 @@
     }
 
     private Rect getBoundsFromWindowManager() {
-        return runtimeActivity.getWindowManager().getCurrentWindowMetrics().getBounds();
+        return mRuntimeActivity.getWindowManager().getCurrentWindowMetrics().getBounds();
     }
 
     @Override
@@ -83,8 +83,8 @@
         // called.
         super.setPixelDimensions(dimensions);
         // TODO: b/376934871 - Check async results.
-        extensions.setMainWindowSize(
-                runtimeActivity,
+        mExtensions.setMainWindowSize(
+                mRuntimeActivity,
                 dimensions.width,
                 dimensions.height,
                 (result) -> {},
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/MediaPlayerExtensionsWrapperImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/MediaPlayerExtensionsWrapperImpl.java
index b741ef8..099b304 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/MediaPlayerExtensionsWrapperImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/MediaPlayerExtensionsWrapperImpl.java
@@ -27,10 +27,10 @@
 /** Implementation of the {@link MediaPlayerExtensionsWrapper}. */
 final class MediaPlayerExtensionsWrapperImpl implements MediaPlayerExtensionsWrapper {
 
-    private final MediaPlayerExtensions extensions;
+    private final MediaPlayerExtensions mExtensions;
 
-    public MediaPlayerExtensionsWrapperImpl(@NonNull MediaPlayerExtensions extensions) {
-        this.extensions = extensions;
+    MediaPlayerExtensionsWrapperImpl(@NonNull MediaPlayerExtensions extensions) {
+        mExtensions = extensions;
     }
 
     @Override
@@ -39,7 +39,7 @@
         androidx.xr.extensions.media.PointSourceAttributes extAttributes =
                 MediaUtils.convertPointSourceAttributesToExtensions(attributes);
 
-        extensions.setPointSourceAttributes(mediaPlayer, extAttributes);
+        mExtensions.setPointSourceAttributes(mediaPlayer, extAttributes);
     }
 
     @Override
@@ -48,6 +48,6 @@
         androidx.xr.extensions.media.SoundFieldAttributes extAttributes =
                 MediaUtils.convertSoundFieldAttributesToExtensions(attributes);
 
-        extensions.setSoundFieldAttributes(mediaPlayer, extAttributes);
+        mExtensions.setSoundFieldAttributes(mediaPlayer, extAttributes);
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/MovableComponentImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/MovableComponentImpl.java
index 035bc3e..9e3bee5 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/MovableComponentImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/MovableComponentImpl.java
@@ -59,34 +59,34 @@
 class MovableComponentImpl implements MovableComponent {
     private static final String TAG = "MovableComponentImpl";
     static final float MIN_PLANE_ANCHOR_DISTANCE = .2f;
-    private final boolean systemMovable;
-    private final boolean scaleInZ;
-    private final boolean shouldDisposeParentAnchor;
-    private final PerceptionLibrary perceptionLibrary;
-    private final XrExtensions extensions;
-    private final ActivitySpaceImpl activitySpaceImpl;
-    private final AndroidXrEntity activitySpaceEntity;
-    private final PerceptionSpaceActivityPoseImpl perceptionSpaceActivityPose;
-    private final EntityManager entityManager;
-    private final PanelShadowRenderer panelShadowRenderer;
-    private final ScheduledExecutorService runtimeExecutor;
-    private final ConcurrentHashMap<MoveEventListener, Executor> moveEventListenersMap =
+    private final boolean mSystemMovable;
+    private final boolean mScaleInZ;
+    private final boolean mShouldDisposeParentAnchor;
+    private final PerceptionLibrary mPerceptionLibrary;
+    private final XrExtensions mExtensions;
+    private final ActivitySpaceImpl mActivitySpaceImpl;
+    private final AndroidXrEntity mActivitySpaceEntity;
+    private final PerceptionSpaceActivityPoseImpl mPerceptionSpaceActivityPose;
+    private final EntityManager mEntityManager;
+    private final PanelShadowRenderer mPanelShadowRenderer;
+    private final ScheduledExecutorService mRuntimeExecutor;
+    private final ConcurrentHashMap<MoveEventListener, Executor> mMoveEventListenersMap =
             new ConcurrentHashMap<>();
-    private final Map<PlaneType, Map<PlaneSemantic, AnchorPlacementImpl>> anchorableFilters =
+    private final Map<PlaneType, Map<PlaneSemantic, AnchorPlacementImpl>> mAnchorableFilters =
             new EnumMap<>(PlaneType.class);
     // Visible for testing.
-    Consumer<ReformEvent> reformEventConsumer;
-    private Entity entity;
-    private Entity initialParent;
-    private Pose lastPose = new Pose();
-    private Vector3 lastScale = new Vector3(1f, 1f, 1f);
-    private Dimensions currentSize;
-    private boolean userAnchorable = false;
-    private AnchorEntity createdAnchorEntity;
-    private AnchorPlacementImpl createdAnchorPlacement;
-    @ScaleWithDistanceMode private int scaleWithDistanceMode = ScaleWithDistanceMode.DEFAULT;
+    Consumer<ReformEvent> mReformEventConsumer;
+    private Entity mEntity;
+    private Entity mInitialParent;
+    private Pose mLastPose = new Pose();
+    private Vector3 mLastScale = new Vector3(1f, 1f, 1f);
+    private Dimensions mCurrentSize;
+    private boolean mUserAnchorable = false;
+    private AnchorEntity mCreatedAnchorEntity;
+    private AnchorPlacementImpl mCreatedAnchorPlacement;
+    @ScaleWithDistanceMode private int mScaleWithDistanceMode = ScaleWithDistanceMode.DEFAULT;
 
-    public MovableComponentImpl(
+    MovableComponentImpl(
             boolean systemMovable,
             boolean scaleInZ,
             Set<AnchorPlacement> anchorPlacement,
@@ -99,60 +99,62 @@
             EntityManager entityManager,
             PanelShadowRenderer panelShadowRenderer,
             ScheduledExecutorService runtimeExecutor) {
-        this.systemMovable = systemMovable;
-        this.scaleInZ = scaleInZ;
-        this.shouldDisposeParentAnchor = shouldDisposeParentAnchor;
-        this.perceptionLibrary = perceptionLibrary;
-        this.extensions = extensions;
-        this.activitySpaceImpl = activitySpaceImpl;
-        this.activitySpaceEntity = activitySpaceEntity;
-        this.perceptionSpaceActivityPose = perceptionSpaceActivityPose;
-        this.entityManager = entityManager;
-        this.panelShadowRenderer = panelShadowRenderer;
-        this.runtimeExecutor = runtimeExecutor;
+        mSystemMovable = systemMovable;
+        mScaleInZ = scaleInZ;
+        mShouldDisposeParentAnchor = shouldDisposeParentAnchor;
+        mPerceptionLibrary = perceptionLibrary;
+        mExtensions = extensions;
+        mActivitySpaceImpl = activitySpaceImpl;
+        mActivitySpaceEntity = activitySpaceEntity;
+        mPerceptionSpaceActivityPose = perceptionSpaceActivityPose;
+        mEntityManager = entityManager;
+        mPanelShadowRenderer = panelShadowRenderer;
+        mRuntimeExecutor = runtimeExecutor;
         setUpAnchorPlacement(anchorPlacement);
     }
 
     @Override
     public boolean onAttach(Entity entity) {
-        if (this.entity != null) {
-            Log.e(TAG, "Already attached to entity " + this.entity);
+        if (mEntity != null) {
+            Log.e(TAG, "Already attached to entity " + mEntity);
             return false;
         }
-        this.entity = entity;
+        mEntity = entity;
         ReformOptions reformOptions = ((AndroidXrEntity) entity).getReformOptions();
         // The math for anchoring uses the pose relative to the activity space so we should not set
         // the reform options to be relative to the parent if the entity is anchorable.
-        int reformFlags = userAnchorable ? 0 : ReformOptions.FLAG_POSE_RELATIVE_TO_PARENT;
+        int reformFlags = mUserAnchorable ? 0 : ReformOptions.FLAG_POSE_RELATIVE_TO_PARENT;
         reformFlags =
-                (systemMovable && !userAnchorable)
+                (mSystemMovable && !mUserAnchorable)
                         ? reformFlags | ReformOptions.FLAG_ALLOW_SYSTEM_MOVEMENT
                         : reformFlags;
-        reformFlags = scaleInZ ? reformFlags | ReformOptions.FLAG_SCALE_WITH_DISTANCE : reformFlags;
+        reformFlags =
+                mScaleInZ ? reformFlags | ReformOptions.FLAG_SCALE_WITH_DISTANCE : reformFlags;
         reformOptions.setFlags(reformFlags);
         reformOptions.setEnabledReform(reformOptions.getEnabledReform() | ReformOptions.ALLOW_MOVE);
         reformOptions.setScaleWithDistanceMode(
-                translateScaleWithDistanceMode(scaleWithDistanceMode));
+                translateScaleWithDistanceMode(mScaleWithDistanceMode));
 
         // TODO: b/348037292 - Remove this special case for PanelEntityImpl.
-        if (entity instanceof PanelEntityImpl && currentSize == null) {
-            currentSize = ((PanelEntityImpl) entity).getSize();
+        if (entity instanceof PanelEntityImpl && mCurrentSize == null) {
+            mCurrentSize = ((PanelEntityImpl) entity).getSize();
         }
-        if (currentSize != null) {
+        if (mCurrentSize != null) {
             reformOptions.setCurrentSize(
-                    new Vec3(currentSize.width, currentSize.height, currentSize.depth));
+                    new Vec3(mCurrentSize.width, mCurrentSize.height, mCurrentSize.depth));
         }
-        if (userAnchorable && systemMovable && reformEventConsumer == null) {
-            reformEventConsumer =
+        if (mUserAnchorable && mSystemMovable && mReformEventConsumer == null) {
+            mReformEventConsumer =
                     reformEvent -> {
                         Pair<Pose, Entity> unused = getUpdatedReformEventPoseAndParent(reformEvent);
                     };
         }
-        lastPose = entity.getPose();
-        lastScale = entity.getScale();
+        mLastPose = entity.getPose();
+        mLastScale = entity.getScale();
         ((AndroidXrEntity) entity).updateReformOptions();
-        if (reformEventConsumer != null) {
-            ((AndroidXrEntity) entity).addReformEventConsumer(reformEventConsumer, runtimeExecutor);
+        if (mReformEventConsumer != null) {
+            ((AndroidXrEntity) entity)
+                    .addReformEventConsumer(mReformEventConsumer, mRuntimeExecutor);
         }
         return true;
     }
@@ -165,70 +167,70 @@
         // Clear any flags that were set by this component.
         int reformFlags = reformOptions.getFlags();
         reformFlags =
-                systemMovable
+                mSystemMovable
                         ? reformFlags & ~ReformOptions.FLAG_ALLOW_SYSTEM_MOVEMENT
                         : reformFlags;
         reformFlags =
-                scaleInZ ? reformFlags & ~ReformOptions.FLAG_SCALE_WITH_DISTANCE : reformFlags;
+                mScaleInZ ? reformFlags & ~ReformOptions.FLAG_SCALE_WITH_DISTANCE : reformFlags;
         reformOptions.setFlags(reformFlags);
         ((AndroidXrEntity) entity).updateReformOptions();
-        if (reformEventConsumer != null) {
-            ((AndroidXrEntity) entity).removeReformEventConsumer(reformEventConsumer);
-            reformEventConsumer = null;
+        if (mReformEventConsumer != null) {
+            ((AndroidXrEntity) entity).removeReformEventConsumer(mReformEventConsumer);
+            mReformEventConsumer = null;
         }
-        this.entity = null;
+        mEntity = null;
     }
 
     @Override
     public void setSize(Dimensions dimensions) {
-        currentSize = dimensions;
-        if (entity == null) {
+        mCurrentSize = dimensions;
+        if (mEntity == null) {
             Log.i(TAG, "setSize called before component is attached to an Entity.");
             return;
         }
-        ReformOptions reformOptions = ((AndroidXrEntity) entity).getReformOptions();
+        ReformOptions reformOptions = ((AndroidXrEntity) mEntity).getReformOptions();
         reformOptions.setCurrentSize(
                 new Vec3(dimensions.width, dimensions.height, dimensions.depth));
-        ((AndroidXrEntity) entity).updateReformOptions();
+        ((AndroidXrEntity) mEntity).updateReformOptions();
     }
 
     @Override
     @ScaleWithDistanceMode
     public int getScaleWithDistanceMode() {
-        return scaleWithDistanceMode;
+        return mScaleWithDistanceMode;
     }
 
     @Override
     public void setScaleWithDistanceMode(@ScaleWithDistanceMode int scaleWithDistanceMode) {
-        this.scaleWithDistanceMode = scaleWithDistanceMode;
-        if (entity == null) {
+        mScaleWithDistanceMode = scaleWithDistanceMode;
+        if (mEntity == null) {
             Log.w(
                     TAG,
                     "setScaleWithDistanceMode called before component is attached to an Entity.");
             return;
         }
-        ReformOptions reformOptions = ((AndroidXrEntity) entity).getReformOptions();
+        ReformOptions reformOptions = ((AndroidXrEntity) mEntity).getReformOptions();
         reformOptions.setScaleWithDistanceMode(
                 translateScaleWithDistanceMode(scaleWithDistanceMode));
-        ((AndroidXrEntity) entity).updateReformOptions();
+        ((AndroidXrEntity) mEntity).updateReformOptions();
     }
 
     @Override
     public void addMoveEventListener(Executor executor, MoveEventListener moveEventListener) {
-        if (reformEventConsumer != null) {
-            ((AndroidXrEntity) entity).removeReformEventConsumer(reformEventConsumer);
+        if (mReformEventConsumer != null) {
+            ((AndroidXrEntity) mEntity).removeReformEventConsumer(mReformEventConsumer);
         }
-        reformEventConsumer =
+        mReformEventConsumer =
                 reformEvent -> {
                     if (reformEvent.getType() != ReformEvent.REFORM_TYPE_MOVE) {
                         return;
                     }
                     if (reformEvent.getState() == ReformEvent.REFORM_STATE_START) {
-                        initialParent = entity.getParent();
+                        mInitialParent = mEntity.getParent();
                     }
                     Pose newPose;
                     Entity updatedParent = null;
-                    if (userAnchorable) {
+                    if (mUserAnchorable) {
                         Pair<Pose, Entity> updatedPoseParentPair =
                                 getUpdatedReformEventPoseAndParent(reformEvent);
                         newPose = updatedPoseParentPair.first;
@@ -243,7 +245,7 @@
                     Entity disposeEntity = null;
 
                     Entity parent = updatedParent;
-                    moveEventListenersMap.forEach(
+                    mMoveEventListenersMap.forEach(
                             (listener, listenerExecutor) ->
                                     executor.execute(
                                             () ->
@@ -264,22 +266,22 @@
                                                                             RuntimeUtils.getVector3(
                                                                                     reformEvent
                                                                                             .getCurrentRayDirection())),
-                                                                    lastPose,
+                                                                    mLastPose,
                                                                     newPose,
-                                                                    lastScale,
+                                                                    mLastScale,
                                                                     newScale,
-                                                                    initialParent,
+                                                                    mInitialParent,
                                                                     parent,
                                                                     disposeEntity))));
-                    lastPose = newPose;
-                    lastScale = newScale;
+                    mLastPose = newPose;
+                    mLastScale = newScale;
                 };
-        moveEventListenersMap.put(moveEventListener, executor);
-        if (entity == null) {
+        mMoveEventListenersMap.put(moveEventListener, executor);
+        if (mEntity == null) {
             Log.i(TAG, "setMoveEventListener called before component is attached to an Entity.");
             return;
         }
-        ((AndroidXrEntity) entity).addReformEventConsumer(reformEventConsumer, executor);
+        ((AndroidXrEntity) mEntity).addReformEventConsumer(mReformEventConsumer, executor);
     }
 
     private void setUpAnchorPlacement(Set<AnchorPlacement> anchorPlacement) {
@@ -291,39 +293,39 @@
             AnchorPlacementImpl placementImpl = (AnchorPlacementImpl) placement;
             Map<PlaneSemantic, AnchorPlacementImpl> anchorablePlaneSemantic =
                     new EnumMap<>(PlaneSemantic.class);
-            for (PlaneSemantic planeSemantic : placementImpl.planeSemanticFilter) {
+            for (PlaneSemantic planeSemantic : placementImpl.mPlaneSemanticFilter) {
                 anchorablePlaneSemantic.put(planeSemantic, placementImpl);
             }
-            for (PlaneType planeType : placementImpl.planeTypeFilter) {
-                this.anchorableFilters.put(planeType, anchorablePlaneSemantic);
+            for (PlaneType planeType : placementImpl.mPlaneTypeFilter) {
+                mAnchorableFilters.put(planeType, anchorablePlaneSemantic);
             }
         }
-        if (!anchorableFilters.isEmpty()) {
-            this.userAnchorable = true;
+        if (!mAnchorableFilters.isEmpty()) {
+            mUserAnchorable = true;
         }
     }
 
     @Override
     public void removeMoveEventListener(MoveEventListener moveEventListener) {
-        moveEventListenersMap.remove(moveEventListener);
+        mMoveEventListenersMap.remove(moveEventListener);
     }
 
     private Pair<Pose, Entity> getUpdatedReformEventPoseAndParent(ReformEvent reformEvent) {
         if (reformEvent.getState() == ReformEvent.REFORM_STATE_END && shouldRenderPlaneShadow()) {
-            panelShadowRenderer.destroy();
+            mPanelShadowRenderer.destroy();
         }
         Pose proposedPose =
                 RuntimeUtils.getPose(
                         reformEvent.getProposedPosition(), reformEvent.getProposedOrientation());
         Pair<Pose, Entity> updatedEntity = updatePoseWithPlanes(proposedPose, reformEvent);
-        if (systemMovable) {
-            entity.setPose(updatedEntity.first);
+        if (mSystemMovable) {
+            mEntity.setPose(updatedEntity.first);
         }
         return updatedEntity;
     }
 
     private Pair<Pose, Entity> updatePoseWithPlanes(Pose proposedPose, ReformEvent reformEvent) {
-        Session session = perceptionLibrary.getSession();
+        Session session = mPerceptionLibrary.getSession();
         if (session == null) {
             Log.w(TAG, "Unable to load perception session, cannot anchor object to a plane.");
             return Pair.create(proposedPose, null);
@@ -336,7 +338,7 @@
         // The proposed pose is relative to the activity space, it needs to be updated to be in the
         // perception reference space to be compared against the planes..
         Pose updatedPoseInOpenXr =
-                activitySpaceImpl.transformPoseTo(proposedPose, perceptionSpaceActivityPose);
+                mActivitySpaceImpl.transformPoseTo(proposedPose, mPerceptionSpaceActivityPose);
 
         // Create variables to store the plane in case we need to anchor to it later.
         Plane anchorablePlane = null;
@@ -385,53 +387,53 @@
             }
         } else if (shouldRenderPlaneShadow()) {
             // If there is nothing to anchor to, hide the plane shadow.
-            panelShadowRenderer.hidePlane();
+            mPanelShadowRenderer.hidePlane();
         }
 
         // If the entity was anchored and the reform is complete, update the entity to be in the
         // activity space and remove the previously created anchor data. If
         // shouldDisposeParentAnchor is
         // true dispose the previously created anchor entity.
-        if (createdAnchorEntity != null
-                && entity.getParent() == createdAnchorEntity
+        if (mCreatedAnchorEntity != null
+                && mEntity.getParent() == mCreatedAnchorEntity
                 && reformEvent.getState() == ReformEvent.REFORM_STATE_END) {
 
-            entity.setScale(
-                    entity.getWorldSpaceScale().div(activitySpaceImpl.getWorldSpaceScale()));
-            entity.setParent(activitySpaceImpl);
+            mEntity.setScale(
+                    mEntity.getWorldSpaceScale().div(mActivitySpaceImpl.getWorldSpaceScale()));
+            mEntity.setParent(mActivitySpaceImpl);
             checkAndDisposeAnchorEntity();
-            createdAnchorEntity = null;
-            createdAnchorPlacement = null;
+            mCreatedAnchorEntity = null;
+            mCreatedAnchorPlacement = null;
 
             // Move the updated pose back to the activity space.
             Pose updatedPoseInActivitySpace =
-                    perceptionSpaceActivityPose.transformPoseTo(
-                            updatedPoseInOpenXr, activitySpaceImpl);
-            return Pair.create(updatedPoseInActivitySpace, activitySpaceImpl);
+                    mPerceptionSpaceActivityPose.transformPoseTo(
+                            updatedPoseInOpenXr, mActivitySpaceImpl);
+            return Pair.create(updatedPoseInActivitySpace, mActivitySpaceImpl);
         }
 
         // If the entity has a parent, transform the pose to the parent's space.
-        Entity parent = entity.getParent();
-        if (parent == null || parent == activitySpaceImpl) {
+        Entity parent = mEntity.getParent();
+        if (parent == null || parent == mActivitySpaceImpl) {
             return Pair.create(
-                    perceptionSpaceActivityPose.transformPoseTo(
-                            updatedPoseInOpenXr, activitySpaceImpl),
+                    mPerceptionSpaceActivityPose.transformPoseTo(
+                            updatedPoseInOpenXr, mActivitySpaceImpl),
                     null);
         }
 
         return Pair.create(
-                perceptionSpaceActivityPose.transformPoseTo(updatedPoseInOpenXr, parent), null);
+                mPerceptionSpaceActivityPose.transformPoseTo(updatedPoseInOpenXr, parent), null);
     }
 
     // Gets the anchor placement settings for the given plane data, if it is null the entity should
     // not be anchored to this plane.
     @Nullable
     private AnchorPlacementImpl getAnchorPlacementIfAnchorable(PlaneData planeData) {
-        if (!userAnchorable || !systemMovable) {
+        if (!mUserAnchorable || !mSystemMovable) {
             return null;
         }
         Map<PlaneSemantic, AnchorPlacementImpl> anchorablePlaneSemantic =
-                anchorableFilters.get(RuntimeUtils.getPlaneType(planeData.type));
+                mAnchorableFilters.get(RuntimeUtils.getPlaneType(planeData.type));
         if (anchorablePlaneSemantic != null) {
             if (anchorablePlaneSemantic.containsKey(
                     RuntimeUtils.getPlaneSemantic(planeData.label))) {
@@ -440,7 +442,7 @@
                 return anchorablePlaneSemantic.get(PlaneSemantic.ANY);
             }
         }
-        anchorablePlaneSemantic = anchorableFilters.get(PlaneType.ANY);
+        anchorablePlaneSemantic = mAnchorableFilters.get(PlaneType.ANY);
         if (anchorablePlaneSemantic != null) {
             if (anchorablePlaneSemantic.containsKey(
                     RuntimeUtils.getPlaneSemantic(planeData.label))) {
@@ -460,16 +462,16 @@
             Long dataTimeNs) {
         AnchorEntityImpl anchorEntity =
                 AnchorEntityImpl.createAnchorFromPlane(
-                        extensions.createNode(),
+                        mExtensions.createNode(),
                         plane,
                         new Pose(),
                         dataTimeNs,
-                        activitySpaceImpl,
-                        activitySpaceEntity,
-                        extensions,
-                        entityManager,
-                        runtimeExecutor,
-                        perceptionLibrary);
+                        mActivitySpaceImpl,
+                        mActivitySpaceEntity,
+                        mExtensions,
+                        mEntityManager,
+                        mRuntimeExecutor,
+                        mPerceptionLibrary);
         if (anchorEntity.getState() != AnchorEntityImpl.State.ANCHORED) {
             return Pair.create(updatedPose, null);
         }
@@ -479,8 +481,8 @@
         // AnchorEntity. Note the AnchorEntity has a scale of 1 so we don't need to also scale by
         // the
         // anchor entity's scale.
-        Vector3 entityScale = entity.getWorldSpaceScale();
-        entity.setScale(entityScale);
+        Vector3 entityScale = mEntity.getWorldSpaceScale();
+        mEntity.setScale(entityScale);
         Quaternion planeRotation =
                 RuntimeUtils.fromPerceptionPose(anchorablePlaneData.centerPose).getRotation();
         Pose rotatedPose =
@@ -497,13 +499,13 @@
                                 0f,
                                 poseToAnchor.getTranslation().getZ()),
                         poseToAnchor.getRotation());
-        entity.setParent(anchorEntity);
+        mEntity.setParent(anchorEntity);
         // If the anchor placement settings specify that the anchor should be disposed, dispose of
         // the
         // previously created anchor entity.
         checkAndDisposeAnchorEntity();
-        createdAnchorEntity = anchorEntity;
-        createdAnchorPlacement = anchorPlacement;
+        mCreatedAnchorEntity = anchorEntity;
+        mCreatedAnchorPlacement = anchorPlacement;
         return Pair.create(poseToAnchor, anchorEntity);
     }
 
@@ -546,22 +548,22 @@
         if (!shouldRenderPlaneShadow()) {
             return;
         }
-        panelShadowRenderer.updatePanelPose(proposedPose, planePose, (PanelEntityImpl) entity);
+        mPanelShadowRenderer.updatePanelPose(proposedPose, planePose, (PanelEntityImpl) mEntity);
     }
 
     private boolean shouldRenderPlaneShadow() {
-        return entity instanceof PanelEntityImpl && systemMovable;
+        return mEntity instanceof PanelEntityImpl && mSystemMovable;
     }
 
     // Checks if there is a created anchor entity and if it should be disposed. If so, disposes of
     // the
     // anchor entity. Resets the createdAnchorEntity and createdAnchorPlacement to null.
     private void checkAndDisposeAnchorEntity() {
-        if (createdAnchorEntity != null
-                && createdAnchorEntity.getChildren().isEmpty()
-                && createdAnchorPlacement != null
-                && shouldDisposeParentAnchor) {
-            createdAnchorEntity.dispose();
+        if (mCreatedAnchorEntity != null
+                && mCreatedAnchorEntity.getChildren().isEmpty()
+                && mCreatedAnchorPlacement != null
+                && mShouldDisposeParentAnchor) {
+            mCreatedAnchorEntity.dispose();
         }
     }
 
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/OpenXrActivityPoseHelper.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/OpenXrActivityPoseHelper.java
index b977948..cdc8d68 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/OpenXrActivityPoseHelper.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/OpenXrActivityPoseHelper.java
@@ -27,13 +27,12 @@
  */
 final class OpenXrActivityPoseHelper {
     private static final String TAG = "OpenXrPoseHelper";
-    private final ActivitySpaceImpl activitySpace;
-    private final AndroidXrEntity activitySpaceRoot;
+    private final ActivitySpaceImpl mActivitySpace;
+    private final AndroidXrEntity mActivitySpaceRoot;
 
-    public OpenXrActivityPoseHelper(
-            ActivitySpaceImpl activitySpace, AndroidXrEntity activitySpaceRoot) {
-        this.activitySpace = activitySpace;
-        this.activitySpaceRoot = activitySpaceRoot;
+    OpenXrActivityPoseHelper(ActivitySpaceImpl activitySpace, AndroidXrEntity activitySpaceRoot) {
+        mActivitySpace = activitySpace;
+        mActivitySpaceRoot = activitySpaceRoot;
     }
 
     /**
@@ -42,7 +41,7 @@
      * identity pose.
      */
     public Pose getPoseInActivitySpace(Pose openXrToPose) {
-        if (activitySpace == null) {
+        if (mActivitySpace == null) {
             Log.e(TAG, "Cannot get pose in Activity Space with a null Activity Space.");
             return new Pose();
         }
@@ -50,7 +49,7 @@
         // ActivitySpace and the ActivityPose should have unit scale and the ActivityPose should
         // have no
         // direct parent so we can just compose the two poses without scaling.
-        final Pose openXrToActivitySpace = activitySpace.getPoseInOpenXrReferenceSpace();
+        final Pose openXrToActivitySpace = mActivitySpace.getPoseInOpenXrReferenceSpace();
         // TODO: b/353575470 throw an exception here instead of returning identity pose.
         if (openXrToActivitySpace == null || openXrToPose == null) {
             Log.e(
@@ -66,7 +65,7 @@
 
     /** Returns the ActivityPose's pose in the activity space. */
     public Pose getActivitySpacePose(Pose openXrToPose) {
-        if (activitySpaceRoot == null) {
+        if (mActivitySpaceRoot == null) {
             Log.e(TAG, "Cannot get pose in World Space Pose with a null World Space Entity.");
             return new Pose();
         }
@@ -76,16 +75,16 @@
         // parent so we can just compose the two poses without scaling.
         final Pose activitySpaceToPose = this.getPoseInActivitySpace(openXrToPose);
         final Pose worldSpaceToActivitySpace =
-                activitySpaceRoot.getPoseInActivitySpace().getInverse();
+                mActivitySpaceRoot.getPoseInActivitySpace().getInverse();
         return worldSpaceToActivitySpace.compose(activitySpaceToPose);
     }
 
     /** Returns the scale of the WorldPose with respect to the activity space. */
     public Vector3 getActivitySpaceScale(Vector3 openXrScale) {
-        if (activitySpace == null) {
+        if (mActivitySpace == null) {
             Log.e(TAG, "Cannot get scale in Activity Space with a null Activity Space Entity.");
             return new Vector3(1f, 1f, 1f);
         }
-        return openXrScale.div(activitySpace.getWorldSpaceScale());
+        return openXrScale.div(mActivitySpace.getWorldSpaceScale());
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PanelEntityImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PanelEntityImpl.java
index cab3f98..1026495 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PanelEntityImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PanelEntityImpl.java
@@ -38,12 +38,12 @@
  */
 final class PanelEntityImpl extends BasePanelEntity implements PanelEntity {
     private static final String TAG = "PanelEntity";
-    private final SurfaceControlViewHost surfaceControlViewHost;
+    private final SurfaceControlViewHost mSurfaceControlViewHost;
 
     // TODO(b/352630140): Create a static factory method for PanelEntityImpl and move the Extensions
     //                    init there (out of JxrPlatformAdapterAxr)
 
-    public PanelEntityImpl(
+    PanelEntityImpl(
             Node node,
             XrExtensions extensions,
             EntityManager entityManager,
@@ -55,7 +55,7 @@
         // Extensions
         // are initialized in the factory method. (ext.setWindowBounds, etc)
         super.setPixelDimensions(windowBoundsPx);
-        this.surfaceControlViewHost = surfaceControlViewHost;
+        mSurfaceControlViewHost = surfaceControlViewHost;
     }
 
     // TODO(b/352827267): Enforce minSDK API strategy - go/androidx-api-guidelines#compat-newapi
@@ -64,10 +64,10 @@
         super.setPixelDimensions(dimensions);
 
         SurfacePackage surfacePackage =
-                Objects.requireNonNull(surfaceControlViewHost.getSurfacePackage());
+                Objects.requireNonNull(mSurfaceControlViewHost.getSurfacePackage());
 
-        surfaceControlViewHost.relayout(dimensions.width, dimensions.height);
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
+        mSurfaceControlViewHost.relayout(dimensions.width, dimensions.height);
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
             transaction
                     .setWindowBounds(surfacePackage, dimensions.width, dimensions.height)
                     .apply();
@@ -79,7 +79,7 @@
     @Override
     public void dispose() {
         Log.i(TAG, "Disposing " + this);
-        surfaceControlViewHost.release();
+        mSurfaceControlViewHost.release();
         super.dispose();
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PanelShadowRenderer.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PanelShadowRenderer.java
index 9d5393e..f536a4f 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PanelShadowRenderer.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PanelShadowRenderer.java
@@ -42,19 +42,19 @@
     private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;
     private static final float CORNER_RADIUS = 20f;
     private static final float PANEL_BORDER_ADDED_MARGIN = 50f;
-    private final ActivitySpaceImpl activitySpaceImpl;
-    private final PerceptionSpaceActivityPoseImpl perceptionSpaceActivityPose;
-    private final XrExtensions extensions;
-    private SurfaceControlViewHost surfaceControlViewHost;
-    private final Handler handler;
-    private boolean isVisible;
-    private final Activity activity;
-    Node panelShadowNode;
+    private final ActivitySpaceImpl mActivitySpaceImpl;
+    private final PerceptionSpaceActivityPoseImpl mPerceptionSpaceActivityPose;
+    private final XrExtensions mExtensions;
+    private SurfaceControlViewHost mSurfaceControlViewHost;
+    private final Handler mHandler;
+    private boolean mIsVisible;
+    private final Activity mActivity;
+    Node mPanelShadowNode;
 
     /** PanelShadowView is a view with a blue border to enable the shadow effect. */
     private static class PanelShadowView extends View {
 
-        public PanelShadowView(Context context) {
+        PanelShadowView(Context context) {
             super(context);
         }
 
@@ -78,41 +78,41 @@
         }
     }
 
-    public PanelShadowRenderer(
+    PanelShadowRenderer(
             ActivitySpaceImpl activitySpaceImpl,
             PerceptionSpaceActivityPoseImpl perceptionSpaceActivityPose,
             Activity activity,
             XrExtensions extensions) {
-        this.activitySpaceImpl = activitySpaceImpl;
-        this.perceptionSpaceActivityPose = perceptionSpaceActivityPose;
-        this.extensions = extensions;
-        this.activity = activity;
-        this.handler = new Handler(Looper.getMainLooper());
+        mActivitySpaceImpl = activitySpaceImpl;
+        mPerceptionSpaceActivityPose = perceptionSpaceActivityPose;
+        mExtensions = extensions;
+        mActivity = activity;
+        mHandler = new Handler(Looper.getMainLooper());
     }
 
     void updatePanelPose(
             Pose openXrToProposedPanel, Pose openXrtoPlane, PanelEntityImpl panelEntity) {
         // If there is no panel shadow node, create it.
-        if (panelShadowNode == null) {
+        if (mPanelShadowNode == null) {
             createPanelShadow(openXrToProposedPanel, openXrtoPlane, panelEntity);
             return;
         }
 
         Pose panelPoseInActivitySpace =
                 getUpdatedPanelPoseInActivitySpace(openXrToProposedPanel, openXrtoPlane);
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-            if (!isVisible) {
-                transaction.setVisibility(panelShadowNode, true);
-                isVisible = true;
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
+            if (!mIsVisible) {
+                transaction.setVisibility(mPanelShadowNode, true);
+                mIsVisible = true;
             }
             transaction
                     .setPosition(
-                            panelShadowNode,
+                            mPanelShadowNode,
                             panelPoseInActivitySpace.getTranslation().getX(),
                             panelPoseInActivitySpace.getTranslation().getY(),
                             panelPoseInActivitySpace.getTranslation().getZ())
                     .setOrientation(
-                            panelShadowNode,
+                            mPanelShadowNode,
                             panelPoseInActivitySpace.getRotation().getX(),
                             panelPoseInActivitySpace.getRotation().getY(),
                             panelPoseInActivitySpace.getRotation().getZ(),
@@ -122,84 +122,84 @@
     }
 
     void hidePlane() {
-        if (!isVisible) {
+        if (!mIsVisible) {
             return;
         }
-        try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-            transaction.setVisibility(panelShadowNode, false).apply();
+        try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
+            transaction.setVisibility(mPanelShadowNode, false).apply();
         }
-        isVisible = false;
+        mIsVisible = false;
     }
 
     void destroy() {
-        if (surfaceControlViewHost != null) {
-            handler.post(() -> surfaceControlViewHost.release());
+        if (mSurfaceControlViewHost != null) {
+            mHandler.post(() -> mSurfaceControlViewHost.release());
         }
-        if (panelShadowNode != null) {
-            try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-                transaction.setParent(panelShadowNode, null).apply();
+        if (mPanelShadowNode != null) {
+            try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
+                transaction.setParent(mPanelShadowNode, null).apply();
             }
         }
-        panelShadowNode = null;
+        mPanelShadowNode = null;
     }
 
     private void createPanelShadow(
             Pose openXrToProposedPanel, Pose openXrtoPlane, PanelEntityImpl panelEntity) {
-        View view = new PanelShadowView(activity);
+        View view = new PanelShadowView(mActivity);
 
         // Scale the panel shadow to the size of the PanelEntity in the activity space.
         Vector3 entityScale = panelEntity.getWorldSpaceScale();
         float sizeX =
                 panelEntity.getPixelDimensions().width
                                 * entityScale.getX()
-                                / activitySpaceImpl.getWorldSpaceScale().getX()
+                                / mActivitySpaceImpl.getWorldSpaceScale().getX()
                         + PANEL_BORDER_ADDED_MARGIN;
         float sizeZ =
                 panelEntity.getPixelDimensions().height
                                 * entityScale.getZ()
-                                / activitySpaceImpl.getWorldSpaceScale().getX()
+                                / mActivitySpaceImpl.getWorldSpaceScale().getX()
                         + PANEL_BORDER_ADDED_MARGIN;
 
         Pose panelPoseInActivitySpace =
                 getUpdatedPanelPoseInActivitySpace(openXrToProposedPanel, openXrtoPlane);
 
-        panelShadowNode = extensions.createNode();
+        mPanelShadowNode = mExtensions.createNode();
 
         // The surfaceControlViewHost needs to be created on the main thread.
         // TODO(b/352827267): Enforce minSDK API strategy - go/androidx-api-guidelines#compat-newapi
-        handler.post(
+        mHandler.post(
                 () -> {
-                    surfaceControlViewHost =
+                    mSurfaceControlViewHost =
                             new SurfaceControlViewHost(
-                                    activity,
-                                    Objects.requireNonNull(activity.getDisplay()),
+                                    mActivity,
+                                    Objects.requireNonNull(mActivity.getDisplay()),
                                     new Binder());
-                    surfaceControlViewHost.setView(view, (int) sizeX, (int) sizeZ);
+                    mSurfaceControlViewHost.setView(view, (int) sizeX, (int) sizeZ);
                     SurfacePackage surfacePackage =
-                            Objects.requireNonNull(surfaceControlViewHost.getSurfacePackage());
-                    try (NodeTransaction transaction = extensions.createNodeTransaction()) {
+                            Objects.requireNonNull(mSurfaceControlViewHost.getSurfacePackage());
+                    try (NodeTransaction transaction = mExtensions.createNodeTransaction()) {
                         transaction
-                                .setName(panelShadowNode, "PanelRenderer")
-                                .setSurfacePackage(panelShadowNode, surfacePackage)
+                                .setName(mPanelShadowNode, "PanelRenderer")
+                                .setSurfacePackage(mPanelShadowNode, surfacePackage)
                                 .setWindowBounds(surfacePackage, (int) sizeX, (int) sizeZ)
-                                .setVisibility(panelShadowNode, true)
+                                .setVisibility(mPanelShadowNode, true)
                                 .setPosition(
-                                        panelShadowNode,
+                                        mPanelShadowNode,
                                         panelPoseInActivitySpace.getTranslation().getX(),
                                         panelPoseInActivitySpace.getTranslation().getY(),
                                         panelPoseInActivitySpace.getTranslation().getZ())
                                 .setOrientation(
-                                        panelShadowNode,
+                                        mPanelShadowNode,
                                         panelPoseInActivitySpace.getRotation().getX(),
                                         panelPoseInActivitySpace.getRotation().getY(),
                                         panelPoseInActivitySpace.getRotation().getZ(),
                                         panelPoseInActivitySpace.getRotation().getW())
-                                .setParent(panelShadowNode, activitySpaceImpl.getNode())
+                                .setParent(mPanelShadowNode, mActivitySpaceImpl.getNode())
                                 .apply();
                     }
                     surfacePackage.release();
                 });
-        isVisible = true;
+        mIsVisible = true;
     }
 
     private Pose getUpdatedPanelPoseInActivitySpace(
@@ -219,6 +219,6 @@
                                                 openXrToProposedPanel.getRotation(),
                                                 openXrtoPlane.getRotation())));
         Pose panelInOxr = openXrtoPlane.compose(planeToProjectedPanel);
-        return perceptionSpaceActivityPose.transformPoseTo(panelInOxr, activitySpaceImpl);
+        return mPerceptionSpaceActivityPose.transformPoseTo(panelInOxr, mActivitySpaceImpl);
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PerceptionSpaceActivityPoseImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PerceptionSpaceActivityPoseImpl.java
index 726f1f4..8b7c4c0 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PerceptionSpaceActivityPoseImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PerceptionSpaceActivityPoseImpl.java
@@ -25,28 +25,27 @@
 final class PerceptionSpaceActivityPoseImpl extends BaseActivityPose
         implements PerceptionSpaceActivityPose {
 
-    private final OpenXrActivityPoseHelper openXrActivityPoseHelper;
+    private final OpenXrActivityPoseHelper mOpenXrActivityPoseHelper;
 
-    public PerceptionSpaceActivityPoseImpl(
+    PerceptionSpaceActivityPoseImpl(
             ActivitySpaceImpl activitySpace, AndroidXrEntity activitySpaceRoot) {
-        this.openXrActivityPoseHelper =
-                new OpenXrActivityPoseHelper(activitySpace, activitySpaceRoot);
+        mOpenXrActivityPoseHelper = new OpenXrActivityPoseHelper(activitySpace, activitySpaceRoot);
     }
 
     @Override
     public Pose getPoseInActivitySpace() {
-        return openXrActivityPoseHelper.getPoseInActivitySpace(new Pose());
+        return mOpenXrActivityPoseHelper.getPoseInActivitySpace(new Pose());
     }
 
     @Override
     public Pose getActivitySpacePose() {
-        return openXrActivityPoseHelper.getActivitySpacePose(new Pose());
+        return mOpenXrActivityPoseHelper.getActivitySpacePose(new Pose());
     }
 
     @Override
     public Vector3 getActivitySpaceScale() {
         // This ActivityPose is assumed to always have a scale of 1.0f in the OpenXR reference
         // space.
-        return openXrActivityPoseHelper.getActivitySpaceScale(new Vector3(1f, 1f, 1f));
+        return mOpenXrActivityPoseHelper.getActivitySpaceScale(new Vector3(1f, 1f, 1f));
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PointerCaptureComponentImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PointerCaptureComponentImpl.java
index d16419b..b797897 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PointerCaptureComponentImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/PointerCaptureComponentImpl.java
@@ -27,34 +27,34 @@
 /** Implementation of PointerCaptureComponent. */
 final class PointerCaptureComponentImpl implements PointerCaptureComponent {
 
-    private final Executor executor;
-    private final StateListener stateListener;
-    private final InputEventListener inputListener;
+    private final Executor mExecutor;
+    private final StateListener mStateListener;
+    private final InputEventListener mInputListener;
 
-    private AndroidXrEntity attachedEntity;
+    private AndroidXrEntity mAttachedEntity;
 
-    public PointerCaptureComponentImpl(
+    PointerCaptureComponentImpl(
             @NonNull Executor executor,
             @NonNull StateListener stateListener,
             @NonNull InputEventListener inputListener) {
-        this.executor = executor;
-        this.stateListener = stateListener;
-        this.inputListener = inputListener;
+        mExecutor = executor;
+        mStateListener = stateListener;
+        mInputListener = inputListener;
     }
 
     @Override
     public boolean onAttach(Entity entity) {
-        if (!(entity instanceof AndroidXrEntity) || attachedEntity != null) {
+        if (!(entity instanceof AndroidXrEntity) || mAttachedEntity != null) {
             return false;
         }
 
-        attachedEntity = (AndroidXrEntity) entity;
-        return attachedEntity.requestPointerCapture(executor, inputListener, stateListener);
+        mAttachedEntity = (AndroidXrEntity) entity;
+        return mAttachedEntity.requestPointerCapture(mExecutor, mInputListener, mStateListener);
     }
 
     @Override
     public void onDetach(Entity entity) {
-        attachedEntity.stopPointerCapture();
-        attachedEntity = null;
+        mAttachedEntity.stopPointerCapture();
+        mAttachedEntity = null;
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ResizableComponentImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ResizableComponentImpl.java
index e7932e0..7c2e5f8 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ResizableComponentImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/ResizableComponentImpl.java
@@ -40,56 +40,60 @@
 
     private static final String TAG = "ResizableComponentImpl";
 
-    private final XrExtensions extensions;
-    private final ExecutorService executor;
-    private final ConcurrentHashMap<ResizeEventListener, Executor> resizeEventListenerMap =
+    private final XrExtensions mExtensions;
+    private final ExecutorService mExecutor;
+    private final ConcurrentHashMap<ResizeEventListener, Executor> mResizeEventListenerMap =
             new ConcurrentHashMap<>();
     // Visible for testing.
-    Consumer<ReformEvent> reformEventConsumer;
-    private Entity entity;
-    private Dimensions currentSize;
-    private Dimensions minSize;
-    private Dimensions maxSize;
-    private float fixedAspectRatio = 0.0f;
+    Consumer<ReformEvent> mReformEventConsumer;
+    private Entity mEntity;
+    private Dimensions mCurrentSize;
+    private Dimensions mMinSize;
+    private Dimensions mMaxSize;
+    private float mFixedAspectRatio = 0.0f;
+    private boolean mAutoHideContent = true;
+    private boolean mAutoUpdateSize = true;
+    private boolean mForceShowResizeOverlay = false;
 
-    public ResizableComponentImpl(
+    ResizableComponentImpl(
             ExecutorService executor,
             XrExtensions extensions,
             Dimensions minSize,
             Dimensions maxSize) {
-        this.minSize = minSize;
-        this.maxSize = maxSize;
-        this.extensions = extensions;
-        this.executor = executor;
+        mMinSize = minSize;
+        mMaxSize = maxSize;
+        mExtensions = extensions;
+        mExecutor = executor;
     }
 
     @Override
     public boolean onAttach(Entity entity) {
-        if (this.entity != null) {
-            Log.e(TAG, "Already attached to entity " + this.entity);
+        if (mEntity != null) {
+            Log.e(TAG, "Already attached to entity " + mEntity);
             return false;
         }
-        this.entity = entity;
+        mEntity = entity;
         ReformOptions reformOptions = ((AndroidXrEntity) entity).getReformOptions();
         reformOptions.setEnabledReform(
                 reformOptions.getEnabledReform() | ReformOptions.ALLOW_RESIZE);
 
         // Update the current size if it's not set.
         // TODO: b/348037292 - Remove this special case for PanelEntityImpl.
-        if (entity instanceof PanelEntityImpl && currentSize == null) {
-            currentSize = ((PanelEntityImpl) entity).getSize();
+        if (entity instanceof PanelEntityImpl && mCurrentSize == null) {
+            mCurrentSize = ((PanelEntityImpl) entity).getSize();
             // TODO: b/350563642 - Add checks that size is within minsize and maxsize.
         }
-        if (currentSize != null) {
+        if (mCurrentSize != null) {
             reformOptions.setCurrentSize(
-                    new Vec3(currentSize.width, currentSize.height, currentSize.depth));
+                    new Vec3(mCurrentSize.width, mCurrentSize.height, mCurrentSize.depth));
         }
-        reformOptions.setMinimumSize(new Vec3(minSize.width, minSize.height, minSize.depth));
-        reformOptions.setMaximumSize(new Vec3(maxSize.width, maxSize.height, maxSize.depth));
-        reformOptions.setFixedAspectRatio(fixedAspectRatio);
+        reformOptions.setMinimumSize(new Vec3(mMinSize.width, mMinSize.height, mMinSize.depth));
+        reformOptions.setMaximumSize(new Vec3(mMaxSize.width, mMaxSize.height, mMaxSize.depth));
+        reformOptions.setFixedAspectRatio(mFixedAspectRatio);
+        reformOptions.setForceShowResizeOverlay(mForceShowResizeOverlay);
         ((AndroidXrEntity) entity).updateReformOptions();
-        if (reformEventConsumer != null) {
-            ((AndroidXrEntity) entity).addReformEventConsumer(reformEventConsumer, executor);
+        if (mReformEventConsumer != null) {
+            ((AndroidXrEntity) entity).addReformEventConsumer(mReformEventConsumer, mExecutor);
         }
         return true;
     }
@@ -100,69 +104,91 @@
         reformOptions.setEnabledReform(
                 reformOptions.getEnabledReform() & ~ReformOptions.ALLOW_RESIZE);
         ((AndroidXrEntity) entity).updateReformOptions();
-        if (reformEventConsumer != null) {
-            ((AndroidXrEntity) entity).removeReformEventConsumer(reformEventConsumer);
+        if (mReformEventConsumer != null) {
+            ((AndroidXrEntity) entity).removeReformEventConsumer(mReformEventConsumer);
         }
-        this.entity = null;
+        mEntity = null;
     }
 
     @Override
     public void setSize(Dimensions size) {
         // TODO: b/350821054 - Implement synchronization policy around Entity/Component updates.
-        currentSize = size;
-        if (entity == null) {
+        mCurrentSize = size;
+        if (mEntity == null) {
             Log.e(TAG, "This component isn't attached to an entity.");
             return;
         }
-        ReformOptions reformOptions = ((AndroidXrEntity) entity).getReformOptions();
+        ReformOptions reformOptions = ((AndroidXrEntity) mEntity).getReformOptions();
         reformOptions.setCurrentSize(new Vec3(size.width, size.height, size.depth));
-        ((AndroidXrEntity) entity).updateReformOptions();
+        ((AndroidXrEntity) mEntity).updateReformOptions();
     }
 
     @Override
     public void setMinimumSize(Dimensions minSize) {
-        this.minSize = minSize;
-        if (entity == null) {
+        mMinSize = minSize;
+        if (mEntity == null) {
             Log.e(TAG, "This component isn't attached to an entity.");
             return;
         }
-        ReformOptions reformOptions = ((AndroidXrEntity) entity).getReformOptions();
+        ReformOptions reformOptions = ((AndroidXrEntity) mEntity).getReformOptions();
         reformOptions.setMinimumSize(new Vec3(minSize.width, minSize.height, minSize.depth));
-        ((AndroidXrEntity) entity).updateReformOptions();
+        ((AndroidXrEntity) mEntity).updateReformOptions();
     }
 
     @Override
     public void setMaximumSize(Dimensions maxSize) {
-        this.maxSize = maxSize;
-        if (entity == null) {
+        mMaxSize = maxSize;
+        if (mEntity == null) {
             Log.e(TAG, "This component isn't attached to an entity.");
             return;
         }
-        ReformOptions reformOptions = ((AndroidXrEntity) entity).getReformOptions();
+        ReformOptions reformOptions = ((AndroidXrEntity) mEntity).getReformOptions();
         reformOptions.setMaximumSize(new Vec3(maxSize.width, maxSize.height, maxSize.depth));
-        ((AndroidXrEntity) entity).updateReformOptions();
+        ((AndroidXrEntity) mEntity).updateReformOptions();
     }
 
     @Override
     public void setFixedAspectRatio(float fixedAspectRatio) {
-        this.fixedAspectRatio = fixedAspectRatio;
-        if (entity == null) {
+        mFixedAspectRatio = fixedAspectRatio;
+        if (mEntity == null) {
             Log.e(TAG, "This component isn't attached to an entity.");
             return;
         }
-        ReformOptions reformOptions = ((AndroidXrEntity) entity).getReformOptions();
+        ReformOptions reformOptions = ((AndroidXrEntity) mEntity).getReformOptions();
         reformOptions.setFixedAspectRatio(fixedAspectRatio);
-        ((AndroidXrEntity) entity).updateReformOptions();
+        ((AndroidXrEntity) mEntity).updateReformOptions();
+    }
+
+    @Override
+    public void setAutoHideContent(boolean autoHideContent) {
+        mAutoHideContent = autoHideContent;
+    }
+
+    @Override
+    public void setAutoUpdateSize(boolean autoUpdateSize) {
+        mAutoUpdateSize = autoUpdateSize;
+    }
+
+    @Override
+    public void setForceShowResizeOverlay(boolean show) {
+        mForceShowResizeOverlay = show;
+        if (mEntity == null) {
+            Log.e(TAG, "This component isn't attached to an entity.");
+            return;
+        }
+        ReformOptions reformOptions = ((AndroidXrEntity) mEntity).getReformOptions();
+        reformOptions.setForceShowResizeOverlay(show);
+        ((AndroidXrEntity) mEntity).updateReformOptions();
     }
 
     @Override
     public void addResizeEventListener(
             Executor resizeExecutor, ResizeEventListener resizeEventListener) {
-        resizeEventListenerMap.put(resizeEventListener, resizeExecutor);
-        if (reformEventConsumer != null) {
+        mResizeEventListenerMap.put(resizeEventListener, resizeExecutor);
+        if (mReformEventConsumer != null) {
             return;
         }
-        reformEventConsumer =
+        mReformEventConsumer =
                 reformEvent -> {
                     if (reformEvent.getType() != ReformEvent.REFORM_TYPE_RESIZE) {
                         return;
@@ -172,14 +198,19 @@
                     // entity content while it's being resized.
                     switch (reformEvent.getState()) {
                         case ReformEvent.REFORM_STATE_START:
-                            try (NodeTransaction transaction = extensions.createNodeTransaction()) {
-                                transaction
-                                        .setAlpha(((AndroidXrEntity) entity).getNode(), 0f)
-                                        .apply();
+                            if (mAutoHideContent) {
+                                try (NodeTransaction transaction =
+                                        mExtensions.createNodeTransaction()) {
+                                    transaction
+                                            .setAlpha(((AndroidXrEntity) mEntity).getNode(), 0f)
+                                            .apply();
+                                }
                             }
                             break;
                         case ReformEvent.REFORM_STATE_END:
-                            entity.setAlpha(entity.getAlpha());
+                            if (mAutoHideContent) {
+                                mEntity.setAlpha(mEntity.getAlpha());
+                            }
                             break;
                         default:
                             break;
@@ -189,9 +220,11 @@
                                     reformEvent.getProposedSize().x,
                                     reformEvent.getProposedSize().y,
                                     reformEvent.getProposedSize().z);
-                    // Update the resize affordance size.
-                    setSize(newSize);
-                    resizeEventListenerMap.forEach(
+                    if (mAutoUpdateSize) {
+                        // Update the resize affordance size.
+                        setSize(newSize);
+                    }
+                    mResizeEventListenerMap.forEach(
                             (listener, listenerExecutor) ->
                                     listenerExecutor.execute(
                                             () ->
@@ -203,18 +236,18 @@
                                                                                             .getState()),
                                                                     newSize))));
                 };
-        if (entity == null) {
+        if (mEntity == null) {
             Log.e(TAG, "This component isn't attached to an entity.");
             return;
         }
-        ((AndroidXrEntity) entity).addReformEventConsumer(reformEventConsumer, executor);
+        ((AndroidXrEntity) mEntity).addReformEventConsumer(mReformEventConsumer, mExecutor);
     }
 
     @Override
     public void removeResizeEventListener(ResizeEventListener resizeEventListener) {
-        resizeEventListenerMap.remove(resizeEventListener);
-        if (resizeEventListenerMap.isEmpty()) {
-            ((AndroidXrEntity) entity).removeReformEventConsumer(reformEventConsumer);
+        mResizeEventListenerMap.remove(resizeEventListener);
+        if (mResizeEventListenerMap.isEmpty()) {
+            ((AndroidXrEntity) mEntity).removeReformEventConsumer(mReformEventConsumer);
         }
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/SoundPoolExtensionsWrapperImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/SoundPoolExtensionsWrapperImpl.java
index 1bd0c5e..59bad36 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/SoundPoolExtensionsWrapperImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/SoundPoolExtensionsWrapperImpl.java
@@ -26,10 +26,10 @@
 /** Implementation of {@link SoundPoolExtensionsWrapper}. */
 final class SoundPoolExtensionsWrapperImpl implements SoundPoolExtensionsWrapper {
 
-    private final SoundPoolExtensions extensions;
+    private final SoundPoolExtensions mExtensions;
 
     SoundPoolExtensionsWrapperImpl(SoundPoolExtensions extensions) {
-        this.extensions = extensions;
+        mExtensions = extensions;
     }
 
     @Override
@@ -43,7 +43,7 @@
             float rate) {
         androidx.xr.extensions.media.PointSourceAttributes extAttributes =
                 MediaUtils.convertPointSourceAttributesToExtensions(attributes);
-        return extensions.playAsPointSource(
+        return mExtensions.playAsPointSource(
                 soundPool, soundId, extAttributes, volume, priority, loop, rate);
     }
 
@@ -59,13 +59,13 @@
         androidx.xr.extensions.media.SoundFieldAttributes extAttributes =
                 MediaUtils.convertSoundFieldAttributesToExtensions(attributes);
 
-        return extensions.playAsSoundField(
+        return mExtensions.playAsSoundField(
                 soundPool, soundId, extAttributes, volume, priority, loop, rate);
     }
 
     @Override
     public int getSpatialSourceType(SoundPool soundPool, int streamId) {
         return MediaUtils.convertExtensionsToSourceType(
-                extensions.getSpatialSourceType(soundPool, streamId));
+                mExtensions.getSpatialSourceType(soundPool, streamId));
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/SpatialEnvironmentImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/SpatialEnvironmentImpl.java
index 089f446..5a5a6bd 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/SpatialEnvironmentImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/SpatialEnvironmentImpl.java
@@ -59,72 +59,72 @@
     public static final String SKYBOX_NODE_NAME = "EnvironmentSkyboxNode";
     public static final String GEOMETRY_NODE_NAME = "EnvironmentGeometryNode";
     public static final String PASSTHROUGH_NODE_NAME = "EnvironmentPassthroughNode";
-    @VisibleForTesting final Node passthroughNode;
-    private final XrExtensions xrExtensions;
-    private final Node rootEnvironmentNode;
-    private final boolean useSplitEngine;
-    @Nullable private Activity activity;
+    @VisibleForTesting final Node mPassthroughNode;
+    private final XrExtensions mXrExtensions;
+    private final Node mRootEnvironmentNode;
+    private final boolean mUseSplitEngine;
+    @Nullable private Activity mActivity;
     // Used to represent the geometry
-    private Node geometryNode;
+    private Node mGeometryNode;
     // the "xrExtensions.setEnvironment" call effectively makes a node into a skybox
-    private Node skyboxNode;
-    private SubspaceNode geometrySubspaceSplitEngine;
-    private int geometrySubspaceImpressNode;
-    private boolean isSpatialEnvironmentPreferenceActive = false;
-    @Nullable private SpatialEnvironmentPreference spatialEnvironmentPreference = null;
+    private Node mSkyboxNode;
+    private SubspaceNode mGeometrySubspaceSplitEngine;
+    private int mGeometrySubspaceImpressNode;
+    private boolean mIsSpatialEnvironmentPreferenceActive = false;
+    @Nullable private SpatialEnvironmentPreference mSpatialEnvironmentPreference = null;
 
     // The active passthrough opacity value is updated with every opacity change event. A null value
     // indicates it has not yet been initialized and the value should be read from the
     // spatialStateProvider.
-    private Float activePassthroughOpacity = null;
+    private Float mActivePassthroughOpacity = null;
     // Initialized to null to let system control opacity until preference is explicitly set.
-    private Float passthroughOpacityPreference = null;
-    private SplitEngineSubspaceManager splitEngineSubspaceManager;
-    private ImpressApi impressApi;
-    private final Supplier<SpatialState> spatialStateProvider;
-    private SpatialState previousSpatialState = null;
+    private Float mPassthroughOpacityPreference = null;
+    private SplitEngineSubspaceManager mSplitEngineSubspaceManager;
+    private ImpressApi mImpressApi;
+    private final Supplier<SpatialState> mSpatialStateProvider;
+    private SpatialState mPreviousSpatialState = null;
 
-    private final Set<Consumer<Boolean>> onSpatialEnvironmentChangedListeners =
+    private final Set<Consumer<Boolean>> mOnSpatialEnvironmentChangedListeners =
             Collections.synchronizedSet(new HashSet<>());
 
-    private final Set<Consumer<Float>> onPassthroughOpacityChangedListeners =
+    private final Set<Consumer<Float>> mOnPassthroughOpacityChangedListeners =
             Collections.synchronizedSet(new HashSet<>());
 
-    public SpatialEnvironmentImpl(
+    SpatialEnvironmentImpl(
             @NonNull Activity activity,
             @NonNull XrExtensions xrExtensions,
             @NonNull Node rootSceneNode,
             @NonNull Supplier<SpatialState> spatialStateProvider,
             boolean useSplitEngine) {
-        this.activity = activity;
-        this.xrExtensions = xrExtensions;
-        this.passthroughNode = xrExtensions.createNode();
-        this.rootEnvironmentNode = xrExtensions.createNode();
-        this.geometryNode = xrExtensions.createNode();
-        this.skyboxNode = xrExtensions.createNode();
-        this.useSplitEngine = useSplitEngine;
-        this.spatialStateProvider = spatialStateProvider;
+        mActivity = activity;
+        mXrExtensions = xrExtensions;
+        mPassthroughNode = xrExtensions.createNode();
+        mRootEnvironmentNode = xrExtensions.createNode();
+        mGeometryNode = xrExtensions.createNode();
+        mSkyboxNode = xrExtensions.createNode();
+        mUseSplitEngine = useSplitEngine;
+        mSpatialStateProvider = spatialStateProvider;
 
         try (NodeTransaction transaction = xrExtensions.createNodeTransaction()) {
             transaction
-                    .setName(geometryNode, GEOMETRY_NODE_NAME)
-                    .setName(skyboxNode, SKYBOX_NODE_NAME)
-                    .setName(passthroughNode, PASSTHROUGH_NODE_NAME)
-                    .setParent(geometryNode, rootEnvironmentNode)
-                    .setParent(skyboxNode, rootEnvironmentNode)
-                    .setParent(passthroughNode, rootSceneNode)
+                    .setName(mGeometryNode, GEOMETRY_NODE_NAME)
+                    .setName(mSkyboxNode, SKYBOX_NODE_NAME)
+                    .setName(mPassthroughNode, PASSTHROUGH_NODE_NAME)
+                    .setParent(mGeometryNode, mRootEnvironmentNode)
+                    .setParent(mSkyboxNode, mRootEnvironmentNode)
+                    .setParent(mPassthroughNode, rootSceneNode)
                     .apply();
         }
     }
 
     // TODO: Remove these once we know the Equals() and Hashcode() methods are correct.
     boolean hasEnvironmentVisibilityChanged(@NonNull SpatialState spatialState) {
-        if (previousSpatialState == null) {
+        if (mPreviousSpatialState == null) {
             return true;
         }
 
         final EnvironmentVisibilityState previousEnvironmentVisibility =
-                previousSpatialState.getEnvironmentVisibility();
+                mPreviousSpatialState.getEnvironmentVisibility();
         final EnvironmentVisibilityState currentEnvironmentVisibility =
                 spatialState.getEnvironmentVisibility();
 
@@ -138,12 +138,12 @@
 
     // TODO: Remove these once we know the Equals() and Hashcode() methods are correct.
     boolean hasPassthroughVisibilityChanged(@NonNull SpatialState spatialState) {
-        if (previousSpatialState == null) {
+        if (mPreviousSpatialState == null) {
             return true;
         }
 
         final PassthroughVisibilityState previousPassthroughVisibility =
-                previousSpatialState.getPassthroughVisibility();
+                mPreviousSpatialState.getPassthroughVisibility();
         final PassthroughVisibilityState currentPassthroughVisibility =
                 spatialState.getPassthroughVisibility();
 
@@ -177,7 +177,7 @@
         boolean passthroughVisibilityChanged = hasPassthroughVisibilityChanged(spatialState);
         if (passthroughVisibilityChanged) {
             changedSpatialStates.add(ChangedSpatialStates.PASSTHROUGH_CHANGED);
-            this.activePassthroughOpacity =
+            mActivePassthroughOpacity =
                     RuntimeUtils.getPassthroughOpacity(spatialState.getPassthroughVisibility());
         }
 
@@ -187,29 +187,29 @@
         boolean environmentVisibilityChanged = hasEnvironmentVisibilityChanged(spatialState);
         if (environmentVisibilityChanged) {
             changedSpatialStates.add(ChangedSpatialStates.ENVIRONMENT_CHANGED);
-            this.isSpatialEnvironmentPreferenceActive =
+            mIsSpatialEnvironmentPreferenceActive =
                     RuntimeUtils.getIsSpatialEnvironmentPreferenceActive(
                             spatialState.getEnvironmentVisibility().getCurrentState());
         }
 
-        this.previousSpatialState = spatialState;
+        mPreviousSpatialState = spatialState;
         return changedSpatialStates;
     }
 
     /** Flushes passthrough Node state to XrExtensions. */
     private void applyPassthroughChange(float opacityVal) {
         if (opacityVal > 0.0f) {
-            try (NodeTransaction transaction = xrExtensions.createNodeTransaction()) {
+            try (NodeTransaction transaction = mXrExtensions.createNodeTransaction()) {
                 transaction
                         .setPassthroughState(
-                                passthroughNode, opacityVal, PassthroughState.PASSTHROUGH_MODE_MAX)
+                                mPassthroughNode, opacityVal, PassthroughState.PASSTHROUGH_MODE_MAX)
                         .apply();
             }
         } else {
-            try (NodeTransaction transaction = xrExtensions.createNodeTransaction()) {
+            try (NodeTransaction transaction = mXrExtensions.createNodeTransaction()) {
                 transaction
                         .setPassthroughState(
-                                passthroughNode,
+                                mPassthroughNode,
                                 /* passthroughOpacity= */ 0.0f,
                                 PassthroughState.PASSTHROUGH_MODE_OFF)
                         .apply();
@@ -233,24 +233,24 @@
                         ? null
                         : (opacity < 0.01f ? 0.0f : (opacity > 0.99f ? 1.0f : opacity));
 
-        if (Objects.equals(newPassthroughOpacityPreference, passthroughOpacityPreference)) {
+        if (Objects.equals(newPassthroughOpacityPreference, mPassthroughOpacityPreference)) {
             return SetPassthroughOpacityPreferenceResult.CHANGE_APPLIED;
         }
 
-        passthroughOpacityPreference = newPassthroughOpacityPreference;
+        mPassthroughOpacityPreference = newPassthroughOpacityPreference;
 
         // to this method when they are removed
 
         // Passthrough should be enabled only if the user has explicitly set the
         // PassthroughOpacityPreference to a non-null and non-zero value, otherwise disabled.
-        if (passthroughOpacityPreference != null && passthroughOpacityPreference != 0.0f) {
-            applyPassthroughChange(passthroughOpacityPreference.floatValue());
+        if (mPassthroughOpacityPreference != null && mPassthroughOpacityPreference != 0.0f) {
+            applyPassthroughChange(mPassthroughOpacityPreference.floatValue());
         } else {
             applyPassthroughChange(0.0f);
         }
 
         if (RuntimeUtils.convertSpatialCapabilities(
-                        spatialStateProvider.get().getSpatialCapabilities())
+                        mSpatialStateProvider.get().getSpatialCapabilities())
                 .hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_PASSTHROUGH_CONTROL)) {
             return SetPassthroughOpacityPreferenceResult.CHANGE_APPLIED;
         } else {
@@ -263,33 +263,33 @@
     // initialized previously.
     @Override
     public synchronized float getCurrentPassthroughOpacity() {
-        if (activePassthroughOpacity == null) {
-            setSpatialState(spatialStateProvider.get());
+        if (mActivePassthroughOpacity == null) {
+            setSpatialState(mSpatialStateProvider.get());
         }
-        return activePassthroughOpacity.floatValue();
+        return mActivePassthroughOpacity.floatValue();
     }
 
     @Override
     @Nullable
     public Float getPassthroughOpacityPreference() {
-        return passthroughOpacityPreference;
+        return mPassthroughOpacityPreference;
     }
 
     // This is called on the Activity's UI thread - so we should be careful to not block it.
     synchronized void firePassthroughOpacityChangedEvent(float opacity) {
-        for (Consumer<Float> listener : onPassthroughOpacityChangedListeners) {
+        for (Consumer<Float> listener : mOnPassthroughOpacityChangedListeners) {
             listener.accept(opacity);
         }
     }
 
     @Override
     public void addOnPassthroughOpacityChangedListener(Consumer<Float> listener) {
-        onPassthroughOpacityChangedListeners.add(listener);
+        mOnPassthroughOpacityChangedListeners.add(listener);
     }
 
     @Override
     public void removeOnPassthroughOpacityChangedListener(Consumer<Float> listener) {
-        onPassthroughOpacityChangedListeners.remove(listener);
+        mOnPassthroughOpacityChangedListeners.remove(listener);
     }
 
     /**
@@ -300,17 +300,17 @@
     private void applySkybox(@Nullable ExrImageResourceImpl skybox) {
         // We need to create a new node here because we can't re-use the old CPM node when changing
         // geometry and skybox.
-        try (NodeTransaction transaction = xrExtensions.createNodeTransaction()) {
-            transaction.setParent(skyboxNode, null).apply();
+        try (NodeTransaction transaction = mXrExtensions.createNodeTransaction()) {
+            transaction.setParent(mSkyboxNode, null).apply();
         }
 
-        this.skyboxNode = xrExtensions.createNode();
-        try (NodeTransaction transaction = xrExtensions.createNodeTransaction()) {
+        mSkyboxNode = mXrExtensions.createNode();
+        try (NodeTransaction transaction = mXrExtensions.createNodeTransaction()) {
             transaction
-                    .setName(skyboxNode, SKYBOX_NODE_NAME)
-                    .setParent(skyboxNode, rootEnvironmentNode);
+                    .setName(mSkyboxNode, SKYBOX_NODE_NAME)
+                    .setParent(mSkyboxNode, mRootEnvironmentNode);
             if (skybox != null) {
-                transaction.setEnvironment(skyboxNode, skybox.getToken());
+                transaction.setEnvironment(mSkyboxNode, skybox.getToken());
             }
             transaction.apply();
         }
@@ -324,16 +324,16 @@
     private void applyGeometryLegacy(@Nullable GltfModelResourceImpl geometry) {
         // We need to create a new node here because we can't re-use the old CPM node when changing
         // geometry and skybox.
-        try (NodeTransaction transaction = xrExtensions.createNodeTransaction()) {
-            transaction.setParent(geometryNode, null).apply();
+        try (NodeTransaction transaction = mXrExtensions.createNodeTransaction()) {
+            transaction.setParent(mGeometryNode, null).apply();
         }
-        this.geometryNode = xrExtensions.createNode();
-        try (NodeTransaction transaction = xrExtensions.createNodeTransaction()) {
+        mGeometryNode = mXrExtensions.createNode();
+        try (NodeTransaction transaction = mXrExtensions.createNodeTransaction()) {
             transaction
-                    .setName(geometryNode, GEOMETRY_NODE_NAME)
-                    .setParent(geometryNode, rootEnvironmentNode);
+                    .setName(mGeometryNode, GEOMETRY_NODE_NAME)
+                    .setParent(mGeometryNode, mRootEnvironmentNode);
             if (geometry != null) {
-                transaction.setGltfModel(geometryNode, geometry.getExtensionModelToken());
+                transaction.setGltfModel(mGeometryNode, geometry.getExtensionModelToken());
             }
             transaction.apply();
         }
@@ -353,45 +353,45 @@
 
         int prevGeometrySubspaceImpressNode = -1;
         SubspaceNode prevGeometrySubspaceSplitEngine = null;
-        if (geometrySubspaceSplitEngine != null) {
-            prevGeometrySubspaceSplitEngine = geometrySubspaceSplitEngine;
-            geometrySubspaceSplitEngine = null;
-            prevGeometrySubspaceImpressNode = geometrySubspaceImpressNode;
-            geometrySubspaceImpressNode = -1;
+        if (mGeometrySubspaceSplitEngine != null) {
+            prevGeometrySubspaceSplitEngine = mGeometrySubspaceSplitEngine;
+            mGeometrySubspaceSplitEngine = null;
+            prevGeometrySubspaceImpressNode = mGeometrySubspaceImpressNode;
+            mGeometrySubspaceImpressNode = -1;
         }
 
-        geometrySubspaceImpressNode = impressApi.createImpressNode();
-        String subspaceName = "geometry_subspace_" + geometrySubspaceImpressNode;
+        mGeometrySubspaceImpressNode = mImpressApi.createImpressNode();
+        String subspaceName = "geometry_subspace_" + mGeometrySubspaceImpressNode;
 
-        geometrySubspaceSplitEngine =
-                splitEngineSubspaceManager.createSubspace(
-                        subspaceName, geometrySubspaceImpressNode);
+        mGeometrySubspaceSplitEngine =
+                mSplitEngineSubspaceManager.createSubspace(
+                        subspaceName, mGeometrySubspaceImpressNode);
 
-        try (NodeTransaction transaction = xrExtensions.createNodeTransaction()) {
+        try (NodeTransaction transaction = mXrExtensions.createNodeTransaction()) {
             transaction
-                    .setName(geometrySubspaceSplitEngine.subspaceNode, GEOMETRY_NODE_NAME)
-                    .setParent(geometrySubspaceSplitEngine.subspaceNode, rootEnvironmentNode)
-                    .setPosition(geometrySubspaceSplitEngine.subspaceNode, 0.0f, 0.0f, 0.0f)
-                    .setScale(geometrySubspaceSplitEngine.subspaceNode, 1.0f, 1.0f, 1.0f)
+                    .setName(mGeometrySubspaceSplitEngine.subspaceNode, GEOMETRY_NODE_NAME)
+                    .setParent(mGeometrySubspaceSplitEngine.subspaceNode, mRootEnvironmentNode)
+                    .setPosition(mGeometrySubspaceSplitEngine.subspaceNode, 0.0f, 0.0f, 0.0f)
+                    .setScale(mGeometrySubspaceSplitEngine.subspaceNode, 1.0f, 1.0f, 1.0f)
                     .setOrientation(
-                            geometrySubspaceSplitEngine.subspaceNode, 0.0f, 0.0f, 0.0f, 1.0f)
+                            mGeometrySubspaceSplitEngine.subspaceNode, 0.0f, 0.0f, 0.0f, 1.0f)
                     .apply();
         }
 
         if (geometry != null) {
             int modelImpressNode =
-                    impressApi.instanceGltfModel(
+                    mImpressApi.instanceGltfModel(
                             geometry.getExtensionModelToken(), /* enableCollider= */ false);
-            impressApi.setImpressNodeParent(modelImpressNode, geometrySubspaceImpressNode);
+            mImpressApi.setImpressNodeParent(modelImpressNode, mGeometrySubspaceImpressNode);
         }
 
         if (prevGeometrySubspaceSplitEngine != null && prevGeometrySubspaceImpressNode != -1) {
             // Detach the previous geometry subspace from the root environment node.
-            try (NodeTransaction transaction = xrExtensions.createNodeTransaction()) {
+            try (NodeTransaction transaction = mXrExtensions.createNodeTransaction()) {
                 transaction.setParent(prevGeometrySubspaceSplitEngine.subspaceNode, null).apply();
             }
-            splitEngineSubspaceManager.deleteSubspace(prevGeometrySubspaceSplitEngine.subspaceId);
-            impressApi.destroyImpressNode(prevGeometrySubspaceImpressNode);
+            mSplitEngineSubspaceManager.deleteSubspace(prevGeometrySubspaceSplitEngine.subspaceId);
+            mImpressApi.destroyImpressNode(prevGeometrySubspaceImpressNode);
 
             prevGeometrySubspaceSplitEngine = null;
             prevGeometrySubspaceImpressNode = -1;
@@ -399,8 +399,8 @@
     }
 
     void onSplitEngineReady(SplitEngineSubspaceManager subspaceManager, ImpressApi api) {
-        this.splitEngineSubspaceManager = subspaceManager;
-        this.impressApi = api;
+        mSplitEngineSubspaceManager = subspaceManager;
+        mImpressApi = api;
     }
 
     @Override
@@ -410,25 +410,27 @@
             @Nullable SpatialEnvironmentPreference newPreference) {
         // TODO: b/378914007 This method is not safe for reentrant calls.
 
-        if (Objects.equals(newPreference, spatialEnvironmentPreference)) {
+        if (Objects.equals(newPreference, mSpatialEnvironmentPreference)) {
             return SetSpatialEnvironmentPreferenceResult.CHANGE_APPLIED;
         }
 
         GltfModelResource newGeometry = newPreference == null ? null : newPreference.geometry;
         GltfModelResource prevGeometry =
-                spatialEnvironmentPreference == null ? null : spatialEnvironmentPreference.geometry;
+                mSpatialEnvironmentPreference == null
+                        ? null
+                        : mSpatialEnvironmentPreference.geometry;
         ExrImageResource newSkybox = newPreference == null ? null : newPreference.skybox;
         ExrImageResource prevSkybox =
-                spatialEnvironmentPreference == null ? null : spatialEnvironmentPreference.skybox;
+                mSpatialEnvironmentPreference == null ? null : mSpatialEnvironmentPreference.skybox;
 
         // TODO(b/329907079): Map GltfModelResourceImplSplitEngine to GltfModelResource in Impl
         // Layer
         if (newGeometry != null) {
-            if (useSplitEngine && !(newGeometry instanceof GltfModelResourceImplSplitEngine)) {
+            if (mUseSplitEngine && !(newGeometry instanceof GltfModelResourceImplSplitEngine)) {
                 throw new IllegalArgumentException(
                         "SplitEngine is enabled but the prefererred geometry is not of type"
                                 + " GltfModelResourceImplSplitEngine.");
-            } else if (!useSplitEngine && !(newGeometry instanceof GltfModelResourceImpl)) {
+            } else if (!mUseSplitEngine && !(newGeometry instanceof GltfModelResourceImpl)) {
                 throw new IllegalArgumentException(
                         "SplitEngine is disabled but the prefererred geometry is not of type"
                                 + " GltfModelResourceImpl.");
@@ -443,7 +445,7 @@
 
         if (!Objects.equals(newGeometry, prevGeometry)) {
             // TODO: b/354711945 - Remove this check once we migrate completely to SplitEngine
-            if (useSplitEngine) {
+            if (mUseSplitEngine) {
                 applyGeometrySplitEngine((GltfModelResourceImplSplitEngine) newGeometry);
             } else {
                 applyGeometryLegacy((GltfModelResourceImpl) newGeometry);
@@ -458,25 +460,25 @@
             applySkybox((ExrImageResourceImpl) newSkybox);
         }
 
-        try (NodeTransaction transaction = xrExtensions.createNodeTransaction()) {
+        try (NodeTransaction transaction = mXrExtensions.createNodeTransaction()) {
             if (newSkybox == null && newGeometry == null) {
-                xrExtensions.detachSpatialEnvironment(
-                        activity,
+                mXrExtensions.detachSpatialEnvironment(
+                        mActivity,
                         (result) -> logXrExtensionResult("detachSpatialEnvironment", result),
                         Runnable::run);
             } else {
-                xrExtensions.attachSpatialEnvironment(
-                        activity,
-                        rootEnvironmentNode,
+                mXrExtensions.attachSpatialEnvironment(
+                        mActivity,
+                        mRootEnvironmentNode,
                         (result) -> logXrExtensionResult("attachSpatialEnvironment", result),
                         Runnable::run);
             }
         }
 
-        this.spatialEnvironmentPreference = newPreference;
+        mSpatialEnvironmentPreference = newPreference;
 
         if (RuntimeUtils.convertSpatialCapabilities(
-                        spatialStateProvider.get().getSpatialCapabilities())
+                        mSpatialStateProvider.get().getSpatialCapabilities())
                 .hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_APP_ENVIRONMENT)) {
             return SetSpatialEnvironmentPreferenceResult.CHANGE_APPLIED;
         } else {
@@ -507,30 +509,30 @@
     @Override
     @Nullable
     public SpatialEnvironmentPreference getSpatialEnvironmentPreference() {
-        return spatialEnvironmentPreference;
+        return mSpatialEnvironmentPreference;
     }
 
     @Override
     public boolean isSpatialEnvironmentPreferenceActive() {
-        return isSpatialEnvironmentPreferenceActive;
+        return mIsSpatialEnvironmentPreferenceActive;
     }
 
     // This is called on the Activity's UI thread - so we should be careful to not block it.
     synchronized void fireOnSpatialEnvironmentChangedEvent(
             boolean isSpatialEnvironmentPreferenceActive) {
-        for (Consumer<Boolean> listener : onSpatialEnvironmentChangedListeners) {
+        for (Consumer<Boolean> listener : mOnSpatialEnvironmentChangedListeners) {
             listener.accept(isSpatialEnvironmentPreferenceActive);
         }
     }
 
     @Override
     public void addOnSpatialEnvironmentChangedListener(Consumer<Boolean> listener) {
-        onSpatialEnvironmentChangedListeners.add(listener);
+        mOnSpatialEnvironmentChangedListeners.add(listener);
     }
 
     @Override
     public void removeOnSpatialEnvironmentChangedListener(Consumer<Boolean> listener) {
-        onSpatialEnvironmentChangedListeners.remove(listener);
+        mOnSpatialEnvironmentChangedListeners.remove(listener);
     }
 
     /**
@@ -539,36 +541,35 @@
      * <p>This should be called when the environment is no longer needed.
      */
     public void dispose() {
-        if (useSplitEngine) {
-            if (this.geometrySubspaceSplitEngine != null) {
-                try (NodeTransaction transaction = xrExtensions.createNodeTransaction()) {
-                    transaction.setParent(geometrySubspaceSplitEngine.subspaceNode, null).apply();
+        if (mUseSplitEngine) {
+            if (mGeometrySubspaceSplitEngine != null) {
+                try (NodeTransaction transaction = mXrExtensions.createNodeTransaction()) {
+                    transaction.setParent(mGeometrySubspaceSplitEngine.subspaceNode, null).apply();
                 }
-                this.splitEngineSubspaceManager.deleteSubspace(
-                        this.geometrySubspaceSplitEngine.subspaceId);
-                this.geometrySubspaceSplitEngine = null;
-                impressApi.destroyImpressNode(geometrySubspaceImpressNode);
+                mSplitEngineSubspaceManager.deleteSubspace(mGeometrySubspaceSplitEngine.subspaceId);
+                mGeometrySubspaceSplitEngine = null;
+                mImpressApi.destroyImpressNode(mGeometrySubspaceImpressNode);
             }
         }
-        this.activePassthroughOpacity = null;
-        this.passthroughOpacityPreference = null;
-        try (NodeTransaction transaction = xrExtensions.createNodeTransaction()) {
+        mActivePassthroughOpacity = null;
+        mPassthroughOpacityPreference = null;
+        try (NodeTransaction transaction = mXrExtensions.createNodeTransaction()) {
             transaction
-                    .setParent(skyboxNode, null)
-                    .setParent(geometryNode, null)
-                    .setParent(passthroughNode, null)
+                    .setParent(mSkyboxNode, null)
+                    .setParent(mGeometryNode, null)
+                    .setParent(mPassthroughNode, null)
                     .apply();
         }
-        this.geometrySubspaceSplitEngine = null;
-        this.geometrySubspaceImpressNode = 0;
-        this.splitEngineSubspaceManager = null;
-        this.impressApi = null;
-        this.spatialEnvironmentPreference = null;
-        this.isSpatialEnvironmentPreferenceActive = false;
-        this.onPassthroughOpacityChangedListeners.clear();
-        this.onSpatialEnvironmentChangedListeners.clear();
+        mGeometrySubspaceSplitEngine = null;
+        mGeometrySubspaceImpressNode = 0;
+        mSplitEngineSubspaceManager = null;
+        mImpressApi = null;
+        mSpatialEnvironmentPreference = null;
+        mIsSpatialEnvironmentPreferenceActive = false;
+        mOnPassthroughOpacityChangedListeners.clear();
+        mOnSpatialEnvironmentChangedListeners.clear();
         // TODO: b/376934871 - Check async results.
-        xrExtensions.detachSpatialEnvironment(activity, (result) -> {}, Runnable::run);
-        this.activity = null;
+        mXrExtensions.detachSpatialEnvironment(mActivity, (result) -> {}, Runnable::run);
+        mActivity = null;
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/StereoSurfaceEntityImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/StereoSurfaceEntityImpl.java
deleted file mode 100644
index 27584f0..0000000
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/StereoSurfaceEntityImpl.java
+++ /dev/null
@@ -1,75 +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.xr.scenecore.impl;
-
-import android.view.Surface;
-
-import androidx.xr.extensions.XrExtensions;
-import androidx.xr.scenecore.JxrPlatformAdapter.Dimensions;
-import androidx.xr.scenecore.JxrPlatformAdapter.Entity;
-import androidx.xr.scenecore.JxrPlatformAdapter.StereoSurfaceEntity;
-
-import java.util.concurrent.ScheduledExecutorService;
-
-/**
- * Implementation of a RealityCore StereoSurfaceEntityImpl.
- *
- * <p>Unimplemented, this requires split engine.
- */
-final class StereoSurfaceEntityImpl extends AndroidXrEntity implements StereoSurfaceEntity {
-    @StereoMode private int stereoMode;
-
-    public StereoSurfaceEntityImpl(
-            Entity parentEntity,
-            XrExtensions extensions,
-            EntityManager entityManager,
-            ScheduledExecutorService executor) {
-        super(extensions.createNode(), extensions, entityManager, executor);
-        throw new UnsupportedOperationException();
-    }
-
-    @SuppressWarnings("ObjectToString")
-    @Override
-    public void dispose() {
-        super.dispose();
-    }
-
-    @Override
-    public void setStereoMode(@StereoMode int mode) {
-        stereoMode = mode;
-    }
-
-    @Override
-    public int getStereoMode() {
-        return stereoMode;
-    }
-
-    @Override
-    public void setDimensions(Dimensions dimensions) {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Dimensions getDimensions() {
-        return new Dimensions(0.0f, 0.0f, 0.0f);
-    }
-
-    @Override
-    public Surface getSurface() {
-        throw new UnsupportedOperationException();
-    }
-}
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/StereoSurfaceEntitySplitEngineImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/StereoSurfaceEntitySplitEngineImpl.java
index 60286b6..c6f47d6 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/StereoSurfaceEntitySplitEngineImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/StereoSurfaceEntitySplitEngineImpl.java
@@ -38,17 +38,17 @@
  */
 final class StereoSurfaceEntitySplitEngineImpl extends AndroidXrEntity
         implements StereoSurfaceEntity {
-    private final ImpressApi impressApi;
-    private final SplitEngineSubspaceManager splitEngineSubspaceManager;
-    private final SubspaceNode subspace;
+    private final ImpressApi mImpressApi;
+    private final SplitEngineSubspaceManager mSplitEngineSubspaceManager;
+    private final SubspaceNode mSubspace;
     // TODO: b/362520810 - Wrap impress nodes w/ Java class.
-    private final int panelImpressNode;
-    private final int subspaceImpressNode;
-    @StereoMode private int stereoMode = StereoSurfaceEntity.StereoMode.SIDE_BY_SIDE;
+    private final int mPanelImpressNode;
+    private final int mSubspaceImpressNode;
+    @StereoMode private int mStereoMode = StereoSurfaceEntity.StereoMode.SIDE_BY_SIDE;
     // This are the default dimensions Impress starts with for the Quad mesh used as the canvas
-    private Dimensions dimensions = new Dimensions(2.0f, 2.0f, 2.0f);
+    private Dimensions mDimensions = new Dimensions(2.0f, 2.0f, 2.0f);
 
-    public StereoSurfaceEntitySplitEngineImpl(
+    StereoSurfaceEntitySplitEngineImpl(
             Entity parentEntity,
             ImpressApi impressApi,
             SplitEngineSubspaceManager splitEngineSubspaceManager,
@@ -57,28 +57,27 @@
             ScheduledExecutorService executor,
             @StereoMode int stereoMode) {
         super(extensions.createNode(), extensions, entityManager, executor);
-        this.impressApi = impressApi;
-        this.splitEngineSubspaceManager = splitEngineSubspaceManager;
-        this.stereoMode = stereoMode;
+        mImpressApi = impressApi;
+        mSplitEngineSubspaceManager = splitEngineSubspaceManager;
+        mStereoMode = stereoMode;
         setParent(parentEntity);
 
         // TODO(b/377906324): - Punt this logic to the UI thread, so that applications can create
         // StereoSurface entities from any thread.
 
         // System will only render Impress nodes that are parented by this subspace node.
-        this.subspaceImpressNode = impressApi.createImpressNode();
-        String subspaceName = "stereo_surface_panel_entity_subspace_" + subspaceImpressNode;
+        mSubspaceImpressNode = impressApi.createImpressNode();
+        String subspaceName = "stereo_surface_panel_entity_subspace_" + mSubspaceImpressNode;
 
-        this.subspace =
-                splitEngineSubspaceManager.createSubspace(subspaceName, subspaceImpressNode);
+        mSubspace = splitEngineSubspaceManager.createSubspace(subspaceName, mSubspaceImpressNode);
 
         try (NodeTransaction transaction = extensions.createNodeTransaction()) {
             // Make the Entity node a parent of the subspace node.
-            transaction.setParent(subspace.subspaceNode, this.node).apply();
+            transaction.setParent(mSubspace.subspaceNode, mNode).apply();
         }
         // The CPM node hierarchy is: Entity CPM node --- parent of ---> Subspace CPM node.
-        this.panelImpressNode = impressApi.createStereoSurface(stereoMode);
-        impressApi.setImpressNodeParent(panelImpressNode, subspaceImpressNode);
+        mPanelImpressNode = impressApi.createStereoSurface(stereoMode);
+        impressApi.setImpressNodeParent(mPanelImpressNode, mSubspaceImpressNode);
     }
 
     @SuppressWarnings("ObjectToString")
@@ -86,35 +85,35 @@
     public void dispose() {
         // TODO(b/377906324): - Punt this logic to the UI thread, so that applications can destroy
         // StereoSurface entities from any thread.
-        splitEngineSubspaceManager.deleteSubspace(subspace.subspaceId);
-        impressApi.destroyImpressNode(subspaceImpressNode);
+        mSplitEngineSubspaceManager.deleteSubspace(mSubspace.subspaceId);
+        mImpressApi.destroyImpressNode(mSubspaceImpressNode);
         super.dispose();
     }
 
     @Override
     public void setStereoMode(@StereoMode int mode) {
-        stereoMode = mode;
-        impressApi.setStereoModeForStereoSurface(panelImpressNode, mode);
+        mStereoMode = mode;
+        mImpressApi.setStereoModeForStereoSurface(mPanelImpressNode, mode);
     }
 
     @Override
     public void setDimensions(Dimensions dimensions) {
         // TODO(b/377906324): - Punt this logic to the UI thread, so that applications can call this
         // method from any thread.
-        this.dimensions = dimensions;
-        impressApi.setCanvasDimensionsForStereoSurface(
-                panelImpressNode, dimensions.width, dimensions.height);
+        mDimensions = dimensions;
+        mImpressApi.setCanvasDimensionsForStereoSurface(
+                mPanelImpressNode, dimensions.width, dimensions.height);
     }
 
     @Override
     public Dimensions getDimensions() {
-        return dimensions;
+        return mDimensions;
     }
 
     @Override
     @StereoMode
     public int getStereoMode() {
-        return stereoMode;
+        return mStereoMode;
     }
 
     @Override
@@ -122,6 +121,6 @@
         // TODO(b/377906324) - Either cache the surface in the constructor, or change this interface
         // to
         // return a Future.
-        return impressApi.getSurfaceFromStereoSurface(panelImpressNode);
+        return mImpressApi.getSurfaceFromStereoSurface(mPanelImpressNode);
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/SystemSpaceEntityImpl.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/SystemSpaceEntityImpl.java
index 7d6fe4d..43d1b28 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/SystemSpaceEntityImpl.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/SystemSpaceEntityImpl.java
@@ -38,14 +38,14 @@
 abstract class SystemSpaceEntityImpl extends AndroidXrEntity
         implements JxrPlatformAdapter.SystemSpaceEntity {
 
-    protected Pose openXrReferenceSpacePose;
-    protected Vector3 worldSpaceScale = new Vector3(1f, 1f, 1f);
+    protected Pose mOpenXrReferenceSpacePose;
+    protected Vector3 mWorldSpaceScale = new Vector3(1f, 1f, 1f);
     // Visible for testing.
-    Closeable nodeTransformCloseable;
-    private OnSpaceUpdatedListener spaceUpdatedListener;
-    private Executor spaceUpdatedExecutor;
+    Closeable mNodeTransformCloseable;
+    private OnSpaceUpdatedListener mSpaceUpdatedListener;
+    private Executor mSpaceUpdatedExecutor;
 
-    public SystemSpaceEntityImpl(
+    SystemSpaceEntityImpl(
             Node node,
             XrExtensions extensions,
             EntityManager entityManager,
@@ -60,8 +60,8 @@
 
     /** Called when the underlying space has changed. */
     public void onSpaceUpdated() {
-        if (spaceUpdatedListener != null) {
-            this.spaceUpdatedExecutor.execute(() -> spaceUpdatedListener.onSpaceUpdated());
+        if (mSpaceUpdatedListener != null) {
+            mSpaceUpdatedExecutor.execute(() -> mSpaceUpdatedListener.onSpaceUpdated());
         }
     }
 
@@ -69,8 +69,8 @@
     @Override
     public void setOnSpaceUpdatedListener(
             @Nullable OnSpaceUpdatedListener listener, @Nullable Executor executor) {
-        this.spaceUpdatedListener = listener;
-        this.spaceUpdatedExecutor = executor == null ? this.executor : executor;
+        mSpaceUpdatedListener = listener;
+        mSpaceUpdatedExecutor = executor == null ? mExecutor : executor;
     }
 
     /**
@@ -80,7 +80,7 @@
      * XrExtensions#getOpenXrActivitySpaceType()}
      */
     public Pose getPoseInOpenXrReferenceSpace() {
-        return openXrReferenceSpacePose;
+        return mOpenXrReferenceSpacePose;
     }
 
     /**
@@ -93,8 +93,7 @@
      */
     protected void setOpenXrReferenceSpacePose(Matrix4 openXrReferenceSpaceTransform) {
         // TODO: b/353511649 - Make SystemSpaceEntityImpl thread safe.
-        this.openXrReferenceSpacePose =
-                Matrix4Ext.getUnscaled(openXrReferenceSpaceTransform).getPose();
+        mOpenXrReferenceSpacePose = Matrix4Ext.getUnscaled(openXrReferenceSpaceTransform).getPose();
 
         // TODO: b/367780918 - Consider using Matrix4.scale when it is fixed.
         // Retrieve the scale from the matrix. The scale can be retrieved from the matrix by getting
@@ -106,7 +105,7 @@
         float data01 = openXrReferenceSpaceTransform.getData()[1];
         float data02 = openXrReferenceSpaceTransform.getData()[2];
         float scale = (float) Math.sqrt(data00 * data00 + data01 * data01 + data02 * data02);
-        this.worldSpaceScale = new Vector3(scale, scale, scale);
+        mWorldSpaceScale = new Vector3(scale, scale, scale);
         this.setScaleInternal(new Vector3(scale, scale, scale));
         onSpaceUpdated();
     }
@@ -119,7 +118,7 @@
      * @param executor The executor to run the callback on.
      */
     private void subscribeToNodeTransform(Node node, Executor executor) {
-        this.nodeTransformCloseable =
+        mNodeTransformCloseable =
                 node.subscribeToTransform(
                         (transform) ->
                                 setOpenXrReferenceSpacePose(
@@ -129,13 +128,13 @@
 
     @Override
     public Vector3 getWorldSpaceScale() {
-        return this.worldSpaceScale;
+        return mWorldSpaceScale;
     }
 
     /** Unsubscribes from the node's transform update events. */
     private void unsubscribeFromNodeTransform() {
         try {
-            this.nodeTransformCloseable.close();
+            mNodeTransformCloseable.close();
         } catch (Exception e) {
             Log.w(
                     "SystemSpaceEntity",
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Anchor.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Anchor.java
index fc6d89f..990af74 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Anchor.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Anchor.java
@@ -35,32 +35,32 @@
      * anchorId is an ID used as a reference to this anchor. It is equal to the XrSpace handle for
      * anchor in the OpenXR session managed by the perception library.
      */
-    private final long anchorId;
+    private final long mAnchorId;
 
     /**
      * anchorToken is a Binder reference of the anchor, it can be used to import the anchor by an
      * OpenXR session.
      */
-    private final IBinder anchorToken;
+    private final IBinder mAnchorToken;
 
     /* UUID of the anchor.*/
-    private UUID uuid;
+    private UUID mUuid;
 
     public Anchor(long anchorId, @NonNull IBinder anchorToken) {
-        this.anchorId = anchorId;
-        this.anchorToken = anchorToken;
-        this.uuid = null;
+        mAnchorId = anchorId;
+        mAnchorToken = anchorToken;
+        mUuid = null;
     }
 
     Anchor(AnchorData anchorData) {
-        this.anchorToken = anchorData.anchorToken;
-        this.anchorId = anchorData.anchorId;
-        this.uuid = null;
+        mAnchorToken = anchorData.mAnchorToken;
+        mAnchorId = anchorData.mAnchorId;
+        mUuid = null;
     }
 
     /** Returns the anchorId(native pointer) of the anchor. */
     public long getAnchorId() {
-        return anchorId;
+        return mAnchorId;
     }
 
     /**
@@ -69,7 +69,7 @@
      */
     @NonNull
     public IBinder getAnchorToken() {
-        return anchorToken;
+        return mAnchorToken;
     }
 
     /**
@@ -77,7 +77,7 @@
      * untracked.
      */
     public boolean detach() {
-        return detachAnchor(anchorId);
+        return detachAnchor(mAnchorId);
     }
 
     /**
@@ -90,15 +90,15 @@
      */
     @Nullable
     public UUID persist() {
-        byte[] uuidBytes = persistAnchor(anchorId);
+        byte[] uuidBytes = persistAnchor(mAnchorId);
         if (uuidBytes == null) {
             return null;
         }
         ByteBuffer byteBuffer = ByteBuffer.wrap(uuidBytes);
         long high = byteBuffer.getLong();
         long low = byteBuffer.getLong();
-        this.uuid = new UUID(high, low);
-        return this.uuid;
+        mUuid = new UUID(high, low);
+        return mUuid;
     }
 
     private native boolean detachAnchor(long anchorId);
@@ -114,11 +114,11 @@
      */
     @NonNull
     public PersistState getPersistState() {
-        if (uuid == null) {
+        if (mUuid == null) {
             return PersistState.PERSIST_NOT_REQUESTED;
         }
         PersistState state =
-                getPersistState(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits());
+                getPersistState(mUuid.getMostSignificantBits(), mUuid.getLeastSignificantBits());
         if (state == null) {
             return PersistState.NOT_VALID;
         }
@@ -137,7 +137,7 @@
 
     /** Data returned from native OpenXR layer when creating an anchor. */
     static class AnchorData {
-        long anchorId;
-        IBinder anchorToken;
+        long mAnchorId;
+        IBinder mAnchorToken;
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Fov.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Fov.java
index 0b6758e..11b7dd3 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Fov.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Fov.java
@@ -24,16 +24,16 @@
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 public final class Fov {
-    private final float angleLeft;
-    private final float angleRight;
-    private final float angleUp;
-    private final float angleDown;
+    private final float mAngleLeft;
+    private final float mAngleRight;
+    private final float mAngleUp;
+    private final float mAngleDown;
 
     public Fov(float angleLeft, float angleRight, float angleUp, float angleDown) {
-        this.angleLeft = angleLeft;
-        this.angleRight = angleRight;
-        this.angleUp = angleUp;
-        this.angleDown = angleDown;
+        mAngleLeft = angleLeft;
+        mAngleRight = angleRight;
+        mAngleUp = angleUp;
+        mAngleDown = angleDown;
     }
 
     /**
@@ -41,17 +41,17 @@
      * value is negative. *
      */
     public float getAngleLeft() {
-        return angleLeft;
+        return mAngleLeft;
     }
 
     /** Returns the angle of the right part of the field of view. */
     public float getAngleRight() {
-        return angleRight;
+        return mAngleRight;
     }
 
     /** Returns the angle of the top part of the field of view. */
     public float getAngleUp() {
-        return angleUp;
+        return mAngleUp;
     }
 
     /**
@@ -59,17 +59,17 @@
      * this value is negative. *
      */
     public float getAngleDown() {
-        return angleDown;
+        return mAngleDown;
     }
 
     @Override
     public boolean equals(Object object) {
         if (object instanceof Fov) {
             Fov that = (Fov) object;
-            return this.angleLeft == that.angleLeft
-                    && this.angleRight == that.angleRight
-                    && this.angleUp == that.angleUp
-                    && this.angleDown == that.angleDown;
+            return mAngleLeft == that.mAngleLeft
+                    && mAngleRight == that.mAngleRight
+                    && mAngleUp == that.mAngleUp
+                    && mAngleDown == that.mAngleDown;
         }
         return false;
     }
@@ -77,10 +77,10 @@
     @Override
     public int hashCode() {
         int result = 1;
-        result = 31 * result + Float.floatToIntBits(angleLeft);
-        result = 31 * result + Float.floatToIntBits(angleRight);
-        result = 31 * result + Float.floatToIntBits(angleUp);
-        result = 31 * result + Float.floatToIntBits(angleDown);
+        result = 31 * result + Float.floatToIntBits(mAngleLeft);
+        result = 31 * result + Float.floatToIntBits(mAngleRight);
+        result = 31 * result + Float.floatToIntBits(mAngleUp);
+        result = 31 * result + Float.floatToIntBits(mAngleDown);
         return result;
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/PerceptionLibrary.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/PerceptionLibrary.java
index 29dfaba..01143c1 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/PerceptionLibrary.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/PerceptionLibrary.java
@@ -41,19 +41,19 @@
     private static final String TAG = "PerceptionLibrary";
 
     private static final String NATIVE_LIBRARY_NAME = "androidx.xr.runtime.openxr";
-    private static final ConcurrentHashMap<Activity, Session> activitySessionMap =
+    private static final ConcurrentHashMap<Activity, Session> sActivitySessionMap =
             new ConcurrentHashMap<>();
 
     @SuppressWarnings("NonFinalStaticField")
-    private static volatile boolean libraryLoaded = false;
+    private static volatile boolean sLibraryLoaded = false;
 
-    private Session session = null;
+    private Session mSession = null;
 
     public PerceptionLibrary() {}
 
     @SuppressWarnings("VisiblySynchronized")
     protected static synchronized void loadLibraryAsync(@NonNull String nativeLibraryName) {
-        if (libraryLoaded) {
+        if (sLibraryLoaded) {
             return;
         }
         Log.i(TAG, "Loading native library: " + nativeLibraryName);
@@ -63,7 +63,7 @@
             Log.e(TAG, "Unable to load " + nativeLibraryName);
             return;
         }
-        libraryLoaded = true;
+        sLibraryLoaded = true;
     }
 
     /**
@@ -95,21 +95,21 @@
                 () -> {
                     // TODO: b/373922954 - Early out of some of these operations if the future is
                     // cancelled.
-                    if (!libraryLoaded) {
+                    if (!sLibraryLoaded) {
                         loadLibraryAsync(NATIVE_LIBRARY_NAME);
                     }
-                    if (!libraryLoaded) {
+                    if (!sLibraryLoaded) {
                         Log.i(TAG, "Cannot init session since the native library failed to load.");
                         future.setException(
                                 new LibraryLoadingException("Native library failed to load."));
                         return;
                     }
                     Log.i(TAG, stringFromJNI());
-                    if (this.session != null) {
+                    if (mSession != null) {
                         future.setException(new IllegalStateException("Session already exists."));
                         return;
                     }
-                    if (activitySessionMap.containsKey(activity)) {
+                    if (sActivitySessionMap.containsKey(activity)) {
                         future.setException(
                                 new IllegalStateException(
                                         "Session already exists for the provided activity."));
@@ -127,13 +127,13 @@
                     // Do another check to make sure another session wasn't created for this
                     // activity
                     // while we were initializing it.
-                    if (activitySessionMap.putIfAbsent(activity, session) != null) {
+                    if (sActivitySessionMap.putIfAbsent(activity, session) != null) {
                         future.setException(
                                 new IllegalStateException(
                                         "Session already exists for the provided activity."));
                     }
-                    this.session = session;
-                    future.set(this.session);
+                    mSession = session;
+                    future.set(mSession);
                 });
         return future;
     }
@@ -142,7 +142,7 @@
     @SuppressWarnings("VisiblySynchronized")
     @Nullable
     public synchronized Session getSession() {
-        return session;
+        return mSession;
     }
 
     /**
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Plane.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Plane.java
index 6c58b8d..8285205 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Plane.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Plane.java
@@ -32,15 +32,15 @@
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 public class Plane implements Trackable {
     private static final String TAG = "PerceptionPlane";
-    ArrayList<Anchor> attachedAnchors = new ArrayList<>();
-    Long planeId = 0L;
-    @PerceptionLibraryConstants.OpenXrSpaceType int referenceSpaceType = 0;
+    ArrayList<Anchor> mAttachedAnchors = new ArrayList<>();
+    Long mPlaneId = 0L;
+    @PerceptionLibraryConstants.OpenXrSpaceType int mReferenceSpaceType = 0;
 
     public Plane(
             @SuppressWarnings("AutoBoxing") @NonNull Long planeId,
             @PerceptionLibraryConstants.OpenXrSpaceType int referenceSpaceType) {
-        this.planeId = planeId;
-        this.referenceSpaceType = referenceSpaceType;
+        mPlaneId = planeId;
+        mReferenceSpaceType = referenceSpaceType;
     }
 
     /**
@@ -56,14 +56,14 @@
     public Anchor createAnchor(
             @NonNull Pose pose, @SuppressWarnings("AutoBoxing") @Nullable Long timeNs) {
         Anchor.AnchorData anchorData =
-                createAnchorOnPlane(planeId, pose, timeNs == null ? -1 : timeNs);
+                createAnchorOnPlane(mPlaneId, pose, timeNs == null ? -1 : timeNs);
         if (anchorData == null) {
             Log.i(TAG, "Failed to create an anchor.");
             return null;
         }
-        Log.i(TAG, "Creating an anchor result:" + anchorData.anchorToken);
+        Log.i(TAG, "Creating an anchor result:" + anchorData.mAnchorToken);
         Anchor anchor = new Anchor(anchorData);
-        attachedAnchors.add(anchor);
+        mAttachedAnchors.add(anchor);
         return anchor;
     }
 
@@ -76,14 +76,14 @@
      */
     @Nullable
     public PlaneData getData(@SuppressWarnings("AutoBoxing") @Nullable Long timeNs) {
-        return getPlaneData(planeId, referenceSpaceType, timeNs == null ? -1 : timeNs);
+        return getPlaneData(mPlaneId, mReferenceSpaceType, timeNs == null ? -1 : timeNs);
     }
 
     /** Returns all anchors attached to this trackable. */
     @NonNull
     @Override
     public List<Anchor> getAnchors() {
-        return attachedAnchors;
+        return mAttachedAnchors;
     }
 
     private native PlaneData getPlaneData(
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Pose.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Pose.java
index 48a5d40b..e0f7297 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Pose.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Pose.java
@@ -22,89 +22,92 @@
 /** A translation and rotation of an object (e.g. Trackable, Anchor). */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 public final class Pose {
-    private float tx;
-    private float ty;
-    private float tz;
-    private float qx;
-    private float qy;
-    private float qz;
-    private float qw;
+    private float mTx;
+    private float mTy;
+    private float mTz;
+    private float mQx;
+    private float mQy;
+    private float mQz;
+    private float mQw;
 
+    /** Constructor which sets all components of the pose. */
     public Pose(float tx, float ty, float tz, float qx, float qy, float qz, float qw) {
-        this.tx = tx;
-        this.ty = ty;
-        this.tz = tz;
-        this.qx = qx;
-        this.qy = qy;
-        this.qz = qz;
-        this.qw = qw;
+        mTx = tx;
+        mTy = ty;
+        mTz = tz;
+        mQx = qx;
+        mQy = qy;
+        mQz = qz;
+        mQw = qw;
     }
 
-    // A pose at zero position and orientation.
+    /** A pose at zero position and orientation. */
     @NonNull
     public static Pose identity() {
         return new Pose(0, 0, 0, 0, 0, 0, 1);
     }
 
+    /** Replaces the translation components of this pose without changing the rotation. */
     public void updateTranslation(float tx, float ty, float tz) {
-        this.tx = tx;
-        this.ty = ty;
-        this.tz = tz;
+        mTx = tx;
+        mTy = ty;
+        mTz = tz;
     }
 
+    /** Replaces the rotation components of this pose without changing the translation. */
     public void updateRotation(float qx, float qy, float qz, float qw) {
-        this.qx = qx;
-        this.qy = qy;
-        this.qz = qz;
-        this.qw = qw;
+        mQx = qx;
+        mQy = qy;
+        mQz = qz;
+        mQw = qw;
     }
 
     /** Returns the X components of this pose's translation. */
     public float tx() {
-        return tx;
+        return mTx;
     }
 
     /** Returns the Y components of this pose's translation. */
     public float ty() {
-        return ty;
+        return mTy;
     }
 
     /** Returns the Z components of this pose's translation. */
     public float tz() {
-        return tz;
+        return mTz;
     }
 
     /** Returns the X component of this pose's rotation quaternion. */
     public float qx() {
-        return qx;
+        return mQx;
     }
 
     /** Returns the Y component of this pose's rotation quaternion. */
     public float qy() {
-        return qy;
+        return mQy;
     }
 
     /** Returns the Z component of this pose's rotation quaternion. */
     public float qz() {
-        return qz;
+        return mQz;
     }
 
     /** Returns the W component of this pose's rotation quaternion. */
     public float qw() {
-        return qw;
+        return mQw;
     }
 
     @Override
     public boolean equals(Object object) {
         if (object instanceof Pose) {
             Pose that = (Pose) object;
-            return this.tx == that.tx
-                    && this.ty == that.ty
-                    && this.tz == that.tz
-                    && this.qx == that.qx
-                    && this.qy == that.qy
-                    && this.qz == that.qz
-                    && this.qw == that.qw;
+            return mTx == that.mTx
+                    && mTy == that.mTy
+                    && mTz == that.mTz
+                    && mQx == that.mQx
+                    && mQy == that.mQy
+                    && mQz == that.mQz
+                    && mQw == that.mQw;
         }
         return false;
     }
@@ -112,13 +115,13 @@
     @Override
     public int hashCode() {
         int result = 1;
-        result = 31 * result + Float.floatToIntBits(tx);
-        result = 31 * result + Float.floatToIntBits(ty);
-        result = 31 * result + Float.floatToIntBits(tz);
-        result = 31 * result + Float.floatToIntBits(qx);
-        result = 31 * result + Float.floatToIntBits(qy);
-        result = 31 * result + Float.floatToIntBits(qz);
-        result = 31 * result + Float.floatToIntBits(qw);
+        result = 31 * result + Float.floatToIntBits(mTx);
+        result = 31 * result + Float.floatToIntBits(mTy);
+        result = 31 * result + Float.floatToIntBits(mTz);
+        result = 31 * result + Float.floatToIntBits(mQx);
+        result = 31 * result + Float.floatToIntBits(mQy);
+        result = 31 * result + Float.floatToIntBits(mQz);
+        result = 31 * result + Float.floatToIntBits(mQw);
         return result;
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Session.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Session.java
index ff61a8f..67e87ca 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Session.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/Session.java
@@ -39,22 +39,22 @@
     public static final long XR_NULL_HANDLE = 0;
 
     private static final String TAG = "PerceptionSession";
-    Activity activity;
-    @PerceptionLibraryConstants.OpenXrSpaceType int openXrReferenceSpaceType;
-    Executor executor;
-    HashMap<Long, Plane> foundPlanes = new HashMap<>();
+    Activity mActivity;
+    @PerceptionLibraryConstants.OpenXrSpaceType int mOpenXrReferenceSpaceType;
+    Executor mExecutor;
+    HashMap<Long, Plane> mFoundPlanes = new HashMap<>();
 
     Session(
             Activity activity,
             @PerceptionLibraryConstants.OpenXrSpaceType int openXrReferenceSpaceType,
             Executor executor) {
-        this.activity = activity;
-        this.openXrReferenceSpaceType = openXrReferenceSpaceType;
-        this.executor = executor;
+        mActivity = activity;
+        mOpenXrReferenceSpaceType = openXrReferenceSpaceType;
+        mExecutor = executor;
     }
 
     boolean initSession() {
-        boolean xrLoaded = createOpenXrSession(activity, openXrReferenceSpaceType);
+        boolean xrLoaded = createOpenXrSession(mActivity, mOpenXrReferenceSpaceType);
         if (!xrLoaded) {
             Log.e(TAG, "Failed to load OpenXR session.");
             return false;
@@ -72,7 +72,7 @@
             Log.i(TAG, "Failed to create an anchor.");
             return null;
         }
-        Log.i(TAG, "Creating an anchor result:" + anchorData.anchorToken);
+        Log.i(TAG, "Creating an anchor result:" + anchorData.mAnchorToken);
         return new Anchor(anchorData);
     }
 
@@ -94,7 +94,7 @@
             Log.i(TAG, "Failed to create a persisted anchor.");
             return null;
         }
-        Log.i(TAG, "Creating a persisted anchor result:" + anchorData.anchorToken);
+        Log.i(TAG, "Creating a persisted anchor result:" + anchorData.mAnchorToken);
         return new Anchor(anchorData);
     }
 
@@ -107,9 +107,9 @@
         return getPlanes().stream()
                 .map(
                         nativeId ->
-                                foundPlanes.computeIfAbsent(
+                                mFoundPlanes.computeIfAbsent(
                                         nativeId,
-                                        id -> new Plane(nativeId, openXrReferenceSpaceType)))
+                                        id -> new Plane(nativeId, mOpenXrReferenceSpaceType)))
                 .collect(toCollection(ArrayList::new));
     }
 
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/ViewProjection.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/ViewProjection.java
index 6b61de7..f7245e7 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/ViewProjection.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/ViewProjection.java
@@ -25,37 +25,37 @@
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 public class ViewProjection {
-    private final Pose pose;
-    private final Fov fov;
+    private final Pose mPose;
+    private final Fov mFov;
 
     public ViewProjection(@NonNull Pose pose, @NonNull Fov fov) {
-        this.pose = pose;
-        this.fov = fov;
+        mPose = pose;
+        mFov = fov;
     }
 
     /** Returns the location and orientation of the camera/eye pose. */
     @NonNull
     public Pose getPose() {
-        return pose;
+        return mPose;
     }
 
     /** Returns the four sides of the projection / view frustum. */
     @NonNull
     public Fov getFov() {
-        return fov;
+        return mFov;
     }
 
     @Override
     public boolean equals(Object object) {
         if (object instanceof ViewProjection) {
             ViewProjection that = (ViewProjection) object;
-            return this.pose.equals(that.pose) && this.fov.equals(that.fov);
+            return mPose.equals(that.mPose) && mFov.equals(that.mFov);
         }
         return false;
     }
 
     @Override
     public int hashCode() {
-        return pose.hashCode() + fov.hashCode();
+        return mPose.hashCode() + mFov.hashCode();
     }
 }
diff --git a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/ViewProjections.java b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/ViewProjections.java
index 803e0e0..8ee9999 100644
--- a/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/ViewProjections.java
+++ b/xr/scenecore/scenecore/src/main/java/androidx/xr/scenecore/impl/perception/ViewProjections.java
@@ -22,37 +22,37 @@
 /** Contains the view projections for both eyes */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
 public final class ViewProjections {
-    private final ViewProjection leftEye;
-    private final ViewProjection rightEye;
+    private final ViewProjection mLeftEye;
+    private final ViewProjection mRightEye;
 
     public ViewProjections(@NonNull ViewProjection leftEye, @NonNull ViewProjection rightEye) {
-        this.leftEye = leftEye;
-        this.rightEye = rightEye;
+        mLeftEye = leftEye;
+        mRightEye = rightEye;
     }
 
     // Returns the left eye view projection.
     @NonNull
     public ViewProjection getLeftEye() {
-        return leftEye;
+        return mLeftEye;
     }
 
     // Returns the right eye view projection.
     @NonNull
     public ViewProjection getRightEye() {
-        return rightEye;
+        return mRightEye;
     }
 
     @Override
     public boolean equals(Object object) {
         if (object instanceof ViewProjections) {
             ViewProjections that = (ViewProjections) object;
-            return this.leftEye.equals(that.leftEye) && this.rightEye.equals(that.rightEye);
+            return mLeftEye.equals(that.mLeftEye) && mRightEye.equals(that.mRightEye);
         }
         return false;
     }
 
     @Override
     public int hashCode() {
-        return leftEye.hashCode() + rightEye.hashCode();
+        return mLeftEye.hashCode() + mRightEye.hashCode();
     }
 }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/EntityTest.kt b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/EntityTest.kt
index 24c74dd..493329b 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/EntityTest.kt
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/EntityTest.kt
@@ -47,7 +47,7 @@
 @RunWith(RobolectricTestRunner::class)
 class EntityTest {
     private val activity = Robolectric.buildActivity(Activity::class.java).create().start().get()
-    private val mockRuntime = mock<JxrPlatformAdapter>()
+    private val mockPlatformAdapter = mock<JxrPlatformAdapter>()
     private val mockGltfModelEntityImpl = mock<JxrPlatformAdapter.GltfEntity>()
     private val mockPanelEntityImpl = mock<JxrPlatformAdapter.PanelEntity>()
     private val mockAnchorEntityImpl = mock<JxrPlatformAdapter.AnchorEntity>()
@@ -197,34 +197,45 @@
 
     @Before
     fun setUp() {
-        whenever(mockRuntime.spatialEnvironment).thenReturn(mock())
-        whenever(mockRuntime.activitySpace).thenReturn(testActivitySpace)
-        whenever(mockRuntime.activitySpaceRootImpl).thenReturn(mock())
-        whenever(mockRuntime.headActivityPose).thenReturn(mock())
-        whenever(mockRuntime.perceptionSpaceActivityPose).thenReturn(mock())
-        whenever(mockRuntime.loadGltfByAssetNameSplitEngine(Mockito.anyString()))
+        whenever(mockPlatformAdapter.spatialEnvironment).thenReturn(mock())
+        whenever(mockPlatformAdapter.activitySpace).thenReturn(testActivitySpace)
+        whenever(mockPlatformAdapter.activitySpaceRootImpl).thenReturn(mock())
+        whenever(mockPlatformAdapter.headActivityPose).thenReturn(mock())
+        whenever(mockPlatformAdapter.perceptionSpaceActivityPose).thenReturn(mock())
+        whenever(mockPlatformAdapter.loadGltfByAssetNameSplitEngine(Mockito.anyString()))
             .thenReturn(Futures.immediateFuture(mock()))
-        whenever(mockRuntime.createGltfEntity(any(), any(), any()))
+        whenever(mockPlatformAdapter.createGltfEntity(any(), any(), any()))
             .thenReturn(mockGltfModelEntityImpl)
-        whenever(mockRuntime.createPanelEntity(any(), any(), any(), any(), any(), any(), any()))
+        whenever(
+                mockPlatformAdapter.createPanelEntity(
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any()
+                )
+            )
             .thenReturn(mockPanelEntityImpl)
-        whenever(mockRuntime.createAnchorEntity(any(), any(), any(), any()))
+        whenever(mockPlatformAdapter.createAnchorEntity(any(), any(), any(), any()))
             .thenReturn(mockAnchorEntityImpl)
         whenever(mockAnchorEntityImpl.state)
             .thenReturn(JxrPlatformAdapter.AnchorEntity.State.UNANCHORED)
         whenever(mockAnchorEntityImpl.persistState)
             .thenReturn(JxrPlatformAdapter.AnchorEntity.PersistState.PERSIST_NOT_REQUESTED)
-        whenever(mockRuntime.createActivityPanelEntity(any(), any(), any(), any(), any()))
+        whenever(mockPlatformAdapter.createActivityPanelEntity(any(), any(), any(), any(), any()))
             .thenReturn(mockActivityPanelEntity)
-        whenever(mockRuntime.createEntity(any(), any(), any())).thenReturn(mockContentlessEntity)
-        whenever(mockRuntime.getMainPanelEntity()).thenReturn(mockPanelEntityImpl)
-        session = Session.create(activity, mockRuntime)
-        activitySpace = ActivitySpace.create(mockRuntime, entityManager)
+        whenever(mockPlatformAdapter.createEntity(any(), any(), any()))
+            .thenReturn(mockContentlessEntity)
+        whenever(mockPlatformAdapter.getMainPanelEntity()).thenReturn(mockPanelEntityImpl)
+        session = Session.create(activity, mockPlatformAdapter)
+        activitySpace = ActivitySpace.create(mockPlatformAdapter, entityManager)
         gltfModel = session.createGltfResourceAsync("test.glb").get()
-        gltfModelEntity = GltfModelEntity.create(mockRuntime, entityManager, gltfModel)
+        gltfModelEntity = GltfModelEntity.create(mockPlatformAdapter, entityManager, gltfModel)
         panelEntity =
             PanelEntity.create(
-                mockRuntime,
+                mockPlatformAdapter,
                 entityManager = entityManager,
                 TextView(activity),
                 Dimensions(720f, 480f),
@@ -234,7 +245,7 @@
             )
         anchorEntity =
             AnchorEntity.create(
-                mockRuntime,
+                mockPlatformAdapter,
                 entityManager,
                 Dimensions(),
                 PlaneType.ANY,
@@ -243,22 +254,22 @@
             )
         activityPanelEntity =
             ActivityPanelEntity.create(
-                mockRuntime,
+                mockPlatformAdapter,
                 entityManager = entityManager,
                 PixelDimensions(640, 480),
                 "test",
                 activity,
             )
-        contentlessEntity = ContentlessEntity.create(mockRuntime, entityManager, "test")
+        contentlessEntity = ContentlessEntity.create(mockPlatformAdapter, entityManager, "test")
     }
 
     @Test
     fun anchorEntityCreateWithNullTimeout_passesNullToImpl() {
-        whenever(mockRuntime.createAnchorEntity(any(), any(), any(), any()))
+        whenever(mockPlatformAdapter.createAnchorEntity(any(), any(), any(), any()))
             .thenReturn(mockAnchorEntityImpl)
         anchorEntity =
             AnchorEntity.create(
-                mockRuntime,
+                mockPlatformAdapter,
                 entityManager,
                 Dimensions(),
                 PlaneType.ANY,
@@ -275,10 +286,10 @@
         anchorEntity.setParent(activitySpace)
         activityPanelEntity.setParent(activitySpace)
 
-        verify(mockPanelEntityImpl).parent = session.runtime.activitySpace
-        verify(mockGltfModelEntityImpl).parent = session.runtime.activitySpace
-        verify(mockAnchorEntityImpl).parent = session.runtime.activitySpace
-        verify(mockActivityPanelEntity).parent = session.runtime.activitySpace
+        verify(mockPanelEntityImpl).parent = session.platformAdapter.activitySpace
+        verify(mockGltfModelEntityImpl).parent = session.platformAdapter.activitySpace
+        verify(mockAnchorEntityImpl).parent = session.platformAdapter.activitySpace
+        verify(mockActivityPanelEntity).parent = session.platformAdapter.activitySpace
     }
 
     @Test
@@ -296,7 +307,7 @@
 
     @Test
     fun allEntityGetParent_callsRuntimeEntityImplGetParent() {
-        val rtActivitySpace = session.runtime.activitySpace
+        val rtActivitySpace = session.platformAdapter.activitySpace
         whenever(mockActivityPanelEntity.parent).thenReturn(rtActivitySpace)
         whenever(mockPanelEntityImpl.parent).thenReturn(mockActivityPanelEntity)
         whenever(mockGltfModelEntityImpl.parent).thenReturn(mockPanelEntityImpl)
@@ -683,7 +694,7 @@
 
     @Test
     fun activitySpaceGetBounds_callsImplGetBounds() {
-        val activitySpace = ActivitySpace.create(mockRuntime, entityManager)
+        val activitySpace = ActivitySpace.create(mockPlatformAdapter, entityManager)
         val bounds = activitySpace.getBounds()
         assertThat(bounds).isNotNull()
         assertThat(testActivitySpace.getBoundsCalled).isTrue()
@@ -691,7 +702,7 @@
 
     @Test
     fun activitySpaceSetBoundsListener_receivesBoundsChangedCallback() {
-        val activitySpace = ActivitySpace.create(mockRuntime, entityManager)
+        val activitySpace = ActivitySpace.create(mockPlatformAdapter, entityManager)
         var called = false
         val boundsChangedListener =
             Consumer<Dimensions> { newBounds ->
@@ -714,8 +725,8 @@
     @Test
     fun setOnSpaceUpdatedListener_withNullParams_callsRuntimeSetOnSpaceUpdatedListener() {
         val mockRtActivitySpace = mock<JxrPlatformAdapter.ActivitySpace>()
-        whenever(mockRuntime.activitySpace).thenReturn(mockRtActivitySpace)
-        val activitySpace = ActivitySpace.create(mockRuntime, entityManager)
+        whenever(mockPlatformAdapter.activitySpace).thenReturn(mockRtActivitySpace)
+        val activitySpace = ActivitySpace.create(mockPlatformAdapter, entityManager)
 
         activitySpace.setOnSpaceUpdatedListener(null)
         verify(mockRtActivitySpace).setOnSpaceUpdatedListener(null, null)
@@ -724,8 +735,8 @@
     @Test
     fun setOnSpaceUpdatedListener_receivesRuntimeSetOnSpaceUpdatedListenerCallbacks() {
         val mockRtActivitySpace = mock<JxrPlatformAdapter.ActivitySpace>()
-        whenever(mockRuntime.activitySpace).thenReturn(mockRtActivitySpace)
-        val activitySpace = ActivitySpace.create(mockRuntime, entityManager)
+        whenever(mockPlatformAdapter.activitySpace).thenReturn(mockRtActivitySpace)
+        val activitySpace = ActivitySpace.create(mockPlatformAdapter, entityManager)
 
         var listenerCalled = false
         val captor = argumentCaptor<JxrPlatformAdapter.SystemSpaceEntity.OnSpaceUpdatedListener>()
@@ -765,7 +776,7 @@
         val mainPanelEntity2 = session.mainPanelEntity
 
         assertThat(mainPanelEntity2).isSameInstanceAs(mainPanelEntity)
-        verify(mockRuntime, times(1)).mainPanelEntity
+        verify(mockPlatformAdapter, times(1)).mainPanelEntity
     }
 
     @Test
@@ -1041,9 +1052,10 @@
 
     @Test
     fun anchorEntity_createPersistAnchorSuccess() {
-        whenever(mockRuntime.createPersistedAnchorEntity(any(), any()))
+        whenever(mockPlatformAdapter.createPersistedAnchorEntity(any(), any()))
             .thenReturn(mockAnchorEntityImpl)
-        val persistAnchorEntity = AnchorEntity.create(mockRuntime, entityManager, UUID.randomUUID())
+        val persistAnchorEntity =
+            AnchorEntity.create(mockPlatformAdapter, entityManager, UUID.randomUUID())
         assertThat(persistAnchorEntity).isNotNull()
     }
 
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/InteractableComponentTest.kt b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/InteractableComponentTest.kt
index 03bcec5..9bca2ef 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/InteractableComponentTest.kt
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/InteractableComponentTest.kt
@@ -61,7 +61,7 @@
         whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
         val mockListener = mock<InputEventListener>()
         val executor = directExecutor()
-        val interactableComponent = session.createInteractableComponent(executor, mockListener)
+        val interactableComponent = InteractableComponent.create(session, executor, mockListener)
 
         assertThat(entity.addComponent(interactableComponent)).isTrue()
         verify(mockRuntime).createInteractableComponent(any(), anyOrNull())
@@ -76,7 +76,7 @@
         whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
         val mockListener = mock<InputEventListener>()
         val executor = directExecutor()
-        val interactableComponent = session.createInteractableComponent(executor, mockListener)
+        val interactableComponent = InteractableComponent.create(session, executor, mockListener)
 
         assertThat(entity.addComponent(interactableComponent)).isTrue()
 
@@ -93,7 +93,7 @@
         whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
         val mockListener = mock<InputEventListener>()
         val executor = directExecutor()
-        val interactableComponent = session.createInteractableComponent(executor, mockListener)
+        val interactableComponent = InteractableComponent.create(session, executor, mockListener)
 
         assertThat(entity.addComponent(interactableComponent)).isTrue()
         assertThat(entity2.addComponent(interactableComponent)).isFalse()
@@ -107,7 +107,7 @@
         whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
         val mockListener = mock<InputEventListener>()
         val executor = directExecutor()
-        val interactableComponent = session.createInteractableComponent(executor, mockListener)
+        val interactableComponent = InteractableComponent.create(session, executor, mockListener)
 
         assertThat(entity.addComponent(interactableComponent)).isTrue()
         entity.removeComponent(interactableComponent)
@@ -122,7 +122,7 @@
         whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
         val mockListener = mock<InputEventListener>()
         val interactableComponent =
-            session.createInteractableComponent(directExecutor(), mockListener)
+            InteractableComponent.create(session, directExecutor(), mockListener)
         assertThat(entity.addComponent(interactableComponent)).isTrue()
         val listenerCaptor = argumentCaptor<JxrPlatformAdapter.InputEventListener>()
         verify(mockRuntime).createInteractableComponent(any(), listenerCaptor.capture())
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/MovableComponentTest.kt b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/MovableComponentTest.kt
index f5c6a13..5255772 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/MovableComponentTest.kt
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/MovableComponentTest.kt
@@ -81,7 +81,8 @@
             AnchorPlacement.createForPlanes(setOf(PlaneType.HORIZONTAL), setOf(PlaneSemantic.WALL))
 
         val movableComponent =
-            session.createMovableComponent(
+            MovableComponent.create(
+                session,
                 systemMovable = false,
                 scaleInZ = false,
                 anchorPlacement = setOf(anchorPlacement),
@@ -99,7 +100,7 @@
         assertThat(entity).isNotNull()
         whenever(mockRuntime.createMovableComponent(any(), any(), any(), any())).thenReturn(mock())
         whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
-        val movableComponent = session.createMovableComponent()
+        val movableComponent = MovableComponent.create(session)
 
         assertThat(entity.addComponent(movableComponent)).isTrue()
         verify(mockRuntime)
@@ -118,7 +119,7 @@
         assertThat(entity).isNotNull()
         whenever(mockRuntime.createMovableComponent(any(), any(), any(), any())).thenReturn(mock())
         whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
-        val movableComponent = session.createMovableComponent()
+        val movableComponent = MovableComponent.create(session)
         assertThat(entity.addComponent(movableComponent)).isTrue()
 
         entity.removeComponent(movableComponent)
@@ -132,7 +133,7 @@
         assertThat(entity).isNotNull()
         whenever(mockRuntime.createMovableComponent(any(), any(), any(), any())).thenReturn(mock())
         whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
-        val movableComponent = session.createMovableComponent()
+        val movableComponent = MovableComponent.create(session)
 
         assertThat(entity.addComponent(movableComponent)).isTrue()
         assertThat(entity2.addComponent(movableComponent)).isFalse()
@@ -147,7 +148,7 @@
         whenever(mockRuntime.createMovableComponent(any(), any(), any(), any()))
             .thenReturn(mockRtMovableComponent)
         whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
-        val movableComponent = session.createMovableComponent()
+        val movableComponent = MovableComponent.create(session)
         assertThat(entity.addComponent(movableComponent)).isTrue()
 
         val testSize = Dimensions(2f, 2f, 0f)
@@ -165,7 +166,7 @@
         whenever(mockRuntime.createMovableComponent(any(), any(), any(), any()))
             .thenReturn(mockRtMovableComponent)
         whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
-        val movableComponent = session.createMovableComponent()
+        val movableComponent = MovableComponent.create(session)
         assertThat(entity.addComponent(movableComponent)).isTrue()
         val mockMoveListener = mock<MoveListener>()
         movableComponent.addMoveListener(directExecutor(), mockMoveListener)
@@ -233,7 +234,7 @@
         whenever(mockRuntime.createMovableComponent(any(), any(), any(), any()))
             .thenReturn(mockRtMovableComponent)
         whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
-        val movableComponent = session.createMovableComponent()
+        val movableComponent = MovableComponent.create(session)
         assertThat(entity.addComponent(movableComponent)).isTrue()
         val mockMoveListener = mock<MoveListener>()
         movableComponent.addMoveListener(directExecutor(), mockMoveListener)
@@ -273,7 +274,7 @@
         whenever(mockRuntime.createMovableComponent(any(), any(), any(), any()))
             .thenReturn(mockRtMovableComponent)
         whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
-        val movableComponent = session.createMovableComponent()
+        val movableComponent = MovableComponent.create(session)
         assertThat(entity.addComponent(movableComponent)).isTrue()
         val mockMoveListener = mock<MoveListener>()
         movableComponent.addMoveListener(directExecutor(), mockMoveListener)
@@ -322,7 +323,7 @@
         assertThat(entity).isNotNull()
         whenever(mockRuntime.createMovableComponent(any(), any(), any(), any())).thenReturn(mock())
         whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
-        val movableComponent = session.createMovableComponent()
+        val movableComponent = MovableComponent.create(session)
 
         assertThat(entity.addComponent(movableComponent)).isTrue()
         entity.removeComponent(movableComponent)
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/ResizableComponentTest.kt b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/ResizableComponentTest.kt
index 4ce3987..8784dbe 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/ResizableComponentTest.kt
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/ResizableComponentTest.kt
@@ -186,6 +186,87 @@
     }
 
     @Test
+    fun resizableComponent_setFixedAspectRatioInvokesRuntimeResizableComponentSetFixedAspectRatio() {
+        val entity = session.createEntity("test")
+        assertThat(entity).isNotNull()
+
+        val mockRtResizableComponent = mock<JxrPlatformAdapter.ResizableComponent>()
+        whenever(mockRuntime.createResizableComponent(any(), any()))
+            .thenReturn(mockRtResizableComponent)
+        whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
+        val resizableComponent = ResizableComponent.create(mockRuntime)
+        assertThat(entity.addComponent(resizableComponent)).isTrue()
+
+        val testAspectRatio = 1.23f
+        resizableComponent.fixedAspectRatio = testAspectRatio
+
+        assertThat(resizableComponent.fixedAspectRatio).isEqualTo(testAspectRatio)
+        val captor = ArgumentCaptor.forClass(Float::class.java)
+        verify(mockRtResizableComponent).setFixedAspectRatio(captor.capture())
+        assertThat(captor.value).isEqualTo(testAspectRatio)
+    }
+
+    @Test
+    fun resizableComponent_setAutoHideContentInvokesRuntimeResizableComponentSetAutoHideContent() {
+        val entity = session.createEntity("test")
+        assertThat(entity).isNotNull()
+
+        val mockRtResizableComponent = mock<JxrPlatformAdapter.ResizableComponent>()
+        whenever(mockRuntime.createResizableComponent(any(), any()))
+            .thenReturn(mockRtResizableComponent)
+        whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
+        val resizableComponent = ResizableComponent.create(mockRuntime)
+        assertThat(entity.addComponent(resizableComponent)).isTrue()
+
+        resizableComponent.autoHideContent = false // default is true
+
+        assertThat(resizableComponent.autoHideContent).isFalse()
+        val captor = ArgumentCaptor.forClass(Boolean::class.java)
+        verify(mockRtResizableComponent).setAutoHideContent(captor.capture())
+        assertThat(captor.value).isFalse()
+    }
+
+    @Test
+    fun resizableComponent_setAutoUpdateSizeInvokesRuntimeResizableComponentSetAutoUpdateSize() {
+        val entity = session.createEntity("test")
+        assertThat(entity).isNotNull()
+
+        val mockRtResizableComponent = mock<JxrPlatformAdapter.ResizableComponent>()
+        whenever(mockRuntime.createResizableComponent(any(), any()))
+            .thenReturn(mockRtResizableComponent)
+        whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
+        val resizableComponent = ResizableComponent.create(mockRuntime)
+        assertThat(entity.addComponent(resizableComponent)).isTrue()
+
+        resizableComponent.autoUpdateSize = false // default is true
+
+        assertThat(resizableComponent.autoUpdateSize).isFalse()
+        val captor = ArgumentCaptor.forClass(Boolean::class.java)
+        verify(mockRtResizableComponent).setAutoUpdateSize(captor.capture())
+        assertThat(captor.value).isFalse()
+    }
+
+    @Test
+    fun resizableComponent_setForceShowResizeOverlayInvokesRuntimeResizableComponentSetForceShowResizeOverlay() {
+        val entity = session.createEntity("test")
+        assertThat(entity).isNotNull()
+
+        val mockRtResizableComponent = mock<JxrPlatformAdapter.ResizableComponent>()
+        whenever(mockRuntime.createResizableComponent(any(), any()))
+            .thenReturn(mockRtResizableComponent)
+        whenever(mockContentlessEntity.addComponent(any())).thenReturn(true)
+        val resizableComponent = ResizableComponent.create(mockRuntime)
+        assertThat(entity.addComponent(resizableComponent)).isTrue()
+
+        resizableComponent.forceShowResizeOverlay = true // default is false
+
+        assertThat(resizableComponent.forceShowResizeOverlay).isTrue()
+        val captor = ArgumentCaptor.forClass(Boolean::class.java)
+        verify(mockRtResizableComponent).setForceShowResizeOverlay(captor.capture())
+        assertThat(captor.value).isTrue()
+    }
+
+    @Test
     fun addResizeListener_invokesRuntimeAddResizeEventListener() {
         val entity = session.createEntity("test")
         assertThat(entity).isNotNull()
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/SessionTest.kt b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/SessionTest.kt
index e46350b..bdf872b 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/SessionTest.kt
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/SessionTest.kt
@@ -51,84 +51,82 @@
 class SessionTest {
     private val activityController = Robolectric.buildActivity(Activity::class.java)
     private val activity = activityController.create().start().get()
-    private val mockRuntime = mock<JxrPlatformAdapter>()
+    private val mockPlatformAdapter = mock<JxrPlatformAdapter>()
     private val mockAnchorEntity = mock<JxrPlatformAdapter.AnchorEntity>()
     lateinit var session: Session
 
     @Before
     fun setUp() {
-        whenever(mockRuntime.spatialEnvironment).thenReturn(mock())
+        whenever(mockPlatformAdapter.spatialEnvironment).thenReturn(mock())
         val mockActivitySpace = mock<JxrPlatformAdapter.ActivitySpace>()
-        whenever(mockRuntime.activitySpace).thenReturn(mockActivitySpace)
-        whenever(mockRuntime.headActivityPose).thenReturn(mock())
-        whenever(mockRuntime.activitySpaceRootImpl).thenReturn(mockActivitySpace)
-        whenever(mockRuntime.mainPanelEntity).thenReturn(mock())
-        whenever(mockRuntime.perceptionSpaceActivityPose).thenReturn(mock())
+        whenever(mockPlatformAdapter.activitySpace).thenReturn(mockActivitySpace)
+        whenever(mockPlatformAdapter.headActivityPose).thenReturn(mock())
+        whenever(mockPlatformAdapter.activitySpaceRootImpl).thenReturn(mockActivitySpace)
+        whenever(mockPlatformAdapter.mainPanelEntity).thenReturn(mock())
+        whenever(mockPlatformAdapter.perceptionSpaceActivityPose).thenReturn(mock())
         whenever(mockAnchorEntity.state)
             .thenReturn(JxrPlatformAdapter.AnchorEntity.State.UNANCHORED)
         whenever(mockAnchorEntity.persistState)
             .thenReturn(JxrPlatformAdapter.AnchorEntity.PersistState.PERSIST_NOT_REQUESTED)
-        session = Session.create(activity, mockRuntime)
-    }
-
-    @Test
-    fun requestFullSpaceMode_callsThrough() {
-        session.requestFullSpaceMode()
-        verify(mockRuntime).requestFullSpaceMode()
-    }
-
-    @Test
-    fun requestHomeSpaceMode_callsThrough() {
-        session.requestHomeSpaceMode()
-        verify(mockRuntime).requestHomeSpaceMode()
+        session = Session.create(activity, mockPlatformAdapter)
     }
 
     @Test
     fun createSession_runtimeProvided_createsSessionWithProvidedRuntime() {
         assertThat(session).isNotNull()
-        assertThat(session.runtime).isNotNull()
-        assertThat(session.runtime).isEqualTo(mockRuntime)
+        assertThat(session.platformAdapter).isNotNull()
+        assertThat(session.platformAdapter).isEqualTo(mockPlatformAdapter)
     }
 
     @Test
     fun createSession_twiceFromSameActivity_returnsSameInstance() {
-        val newSession = Session.create(activity, mockRuntime)
+        val newSession = Session.create(activity, mockPlatformAdapter)
         assertThat(session).isEqualTo(newSession)
     }
 
     @Test
     fun createSession_differentActivities_returnsUniqueInstances() {
         val newActivity = Robolectric.buildActivity(Activity::class.java).create().start().get()
-        val newSession = Session.create(newActivity, mockRuntime)
+        val newSession = Session.create(newActivity, mockPlatformAdapter)
         assertThat(session).isNotEqualTo(newSession)
     }
 
     @Test
     fun createGltfResourceAsync_callsRuntimeLoadGltf() {
         val mockGltfModelResource = mock<GltfModelResource>()
-        whenever(mockRuntime.loadGltfByAssetNameSplitEngine(anyString()))
+        whenever(mockPlatformAdapter.loadGltfByAssetNameSplitEngine(anyString()))
             .thenReturn(Futures.immediateFuture(mockGltfModelResource))
         val unused = session.createGltfResourceAsync("test.glb")
 
-        verify(mockRuntime).loadGltfByAssetNameSplitEngine("test.glb")
+        verify(mockPlatformAdapter).loadGltfByAssetNameSplitEngine("test.glb")
     }
 
     @Test
     fun createGltfEntity_callsRuntimeCreateGltfEntity() {
-        whenever(mockRuntime.loadGltfByAssetNameSplitEngine(anyString()))
+        whenever(mockPlatformAdapter.loadGltfByAssetNameSplitEngine(anyString()))
             .thenReturn(Futures.immediateFuture(mock()))
-        whenever(mockRuntime.createGltfEntity(any(), any(), any())).thenReturn(mock())
+        whenever(mockPlatformAdapter.createGltfEntity(any(), any(), any())).thenReturn(mock())
         val gltfModelFuture = session.createGltfResourceAsync("test.glb")
         val unused = session.createGltfEntity(gltfModelFuture.get())
 
-        verify(mockRuntime).loadGltfByAssetNameSplitEngine(eq("test.glb"))
-        verify(mockRuntime).createGltfEntity(any(), any(), any())
+        verify(mockPlatformAdapter).loadGltfByAssetNameSplitEngine(eq("test.glb"))
+        verify(mockPlatformAdapter).createGltfEntity(any(), any(), any())
     }
 
     @Test
     fun createPanelEntity_callsRuntimeCreatePanelEntity() {
         val view = TextView(activity)
-        whenever(mockRuntime.createPanelEntity(any(), any(), any(), any(), any(), any(), any()))
+        whenever(
+                mockPlatformAdapter.createPanelEntity(
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any()
+                )
+            )
             .thenReturn(mock())
         val unused =
             session.createPanelEntity(
@@ -138,16 +136,17 @@
                 "test"
             )
 
-        verify(mockRuntime).createPanelEntity(any(), any(), any(), any(), any(), any(), any())
+        verify(mockPlatformAdapter)
+            .createPanelEntity(any(), any(), any(), any(), any(), any(), any())
     }
 
     @Test
     fun createAnchorEntity_callsRuntimeCreateAnchorEntity() {
-        whenever(mockRuntime.createAnchorEntity(any(), any(), any(), anyOrNull()))
+        whenever(mockPlatformAdapter.createAnchorEntity(any(), any(), any(), anyOrNull()))
             .thenReturn(mockAnchorEntity)
         val unused = session.createAnchorEntity(Dimensions(), PlaneType.ANY, PlaneSemantic.ANY)
 
-        verify(mockRuntime).createAnchorEntity(any(), any(), any(), anyOrNull())
+        verify(mockPlatformAdapter).createAnchorEntity(any(), any(), any(), anyOrNull())
     }
 
     @Test
@@ -204,11 +203,11 @@
 
     @Test
     fun createActivityPanelEntity_callsRuntimeCreateActivityPanelEntity() {
-        whenever(mockRuntime.createActivityPanelEntity(any(), any(), any(), any(), any()))
+        whenever(mockPlatformAdapter.createActivityPanelEntity(any(), any(), any(), any(), any()))
             .thenReturn(mock())
         val unused = session.createActivityPanelEntity(Rect(0, 0, 640, 480), "test")
 
-        verify(mockRuntime).createActivityPanelEntity(any(), any(), any(), any(), any())
+        verify(mockPlatformAdapter).createActivityPanelEntity(any(), any(), any(), any(), any())
     }
 
     @Test
@@ -216,40 +215,51 @@
         val unused = session.mainPanelEntity
         val unusedAgain = session.mainPanelEntity
 
-        verify(mockRuntime, times(1)).mainPanelEntity
+        verify(mockPlatformAdapter, times(1)).mainPanelEntity
     }
 
     @Test
     fun createPersistedAnchorEntity_callsRuntimecreatePersistedAnchorEntity() {
-        whenever(mockRuntime.createPersistedAnchorEntity(any(), any())).thenReturn(mockAnchorEntity)
+        whenever(mockPlatformAdapter.createPersistedAnchorEntity(any(), any()))
+            .thenReturn(mockAnchorEntity)
         val unused = session.createPersistedAnchorEntity(UUID.randomUUID())
 
-        verify(mockRuntime).createPersistedAnchorEntity(any(), any())
+        verify(mockPlatformAdapter).createPersistedAnchorEntity(any(), any())
     }
 
     @Test
     fun unpersistAnchor_callsRuntimeunpersistAnchor_returnsTrue() {
         val uuid = UUID.randomUUID()
-        whenever(mockRuntime.unpersistAnchor(uuid)).thenReturn(true)
+        whenever(mockPlatformAdapter.unpersistAnchor(uuid)).thenReturn(true)
         assertThat(session.unpersistAnchor(uuid)).isTrue()
-        verify(mockRuntime).unpersistAnchor(uuid)
+        verify(mockPlatformAdapter).unpersistAnchor(uuid)
     }
 
     fun unpersistAnchor_callsRuntimeunpersistAnchor_returnsFalse() {
         val uuid = UUID.randomUUID()
-        whenever(mockRuntime.unpersistAnchor(uuid)).thenReturn(false)
+        whenever(mockPlatformAdapter.unpersistAnchor(uuid)).thenReturn(false)
         assertThat(session.unpersistAnchor(uuid)).isFalse()
-        verify(mockRuntime).unpersistAnchor(uuid)
+        verify(mockPlatformAdapter).unpersistAnchor(uuid)
     }
 
     @Test
     fun createInteractableComponent_callsRuntimeCreateInteractableComponent() {
-        whenever(mockRuntime.createInteractableComponent(any(), any())).thenReturn(mock())
+        whenever(mockPlatformAdapter.createInteractableComponent(any(), any())).thenReturn(mock())
 
-        val interactableComponent = session.createInteractableComponent(directExecutor(), mock())
+        val interactableComponent = InteractableComponent.create(session, directExecutor(), mock())
         val view = TextView(activity)
         val mockPanelEntity = mock<JxrPlatformAdapter.PanelEntity>()
-        whenever(mockRuntime.createPanelEntity(any(), any(), any(), any(), any(), any(), any()))
+        whenever(
+                mockPlatformAdapter.createPanelEntity(
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any()
+                )
+            )
             .thenReturn(mockPanelEntity)
         whenever(mockPanelEntity.addComponent(any())).thenReturn(true)
         val panelEntity =
@@ -261,17 +271,28 @@
             )
         assertThat(panelEntity.addComponent(interactableComponent)).isTrue()
 
-        verify(mockRuntime).createInteractableComponent(any(), anyOrNull())
+        verify(mockPlatformAdapter).createInteractableComponent(any(), anyOrNull())
     }
 
     @Test
     fun createMovableComponent_callsRuntimeCreateMovableComponent() {
-        whenever(mockRuntime.createMovableComponent(any(), any(), any(), any())).thenReturn(mock())
+        whenever(mockPlatformAdapter.createMovableComponent(any(), any(), any(), any()))
+            .thenReturn(mock())
 
-        val movableComponent = session.createMovableComponent()
+        val movableComponent = MovableComponent.create(session)
         val view = TextView(activity)
         val mockRtPanelEntity = mock<JxrPlatformAdapter.PanelEntity>()
-        whenever(mockRuntime.createPanelEntity(any(), any(), any(), any(), any(), any(), any()))
+        whenever(
+                mockPlatformAdapter.createPanelEntity(
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any()
+                )
+            )
             .thenReturn(mockRtPanelEntity)
         whenever(mockRtPanelEntity.addComponent(any())).thenReturn(true)
         val panelEntity =
@@ -283,18 +304,28 @@
             )
         assertThat(panelEntity.addComponent(movableComponent)).isTrue()
 
-        verify(mockRuntime).createMovableComponent(any(), any(), any(), any())
+        verify(mockPlatformAdapter).createMovableComponent(any(), any(), any(), any())
     }
 
     @Test
     fun createResizableComponent_callsRuntimeCreateResizableComponent() {
-        whenever(mockRuntime.createResizableComponent(any(), any())).thenReturn(mock())
+        whenever(mockPlatformAdapter.createResizableComponent(any(), any())).thenReturn(mock())
 
-        val resizableComponent = session.createResizableComponent()
+        val resizableComponent = ResizableComponent.create(session)
         val view = TextView(activity)
         val mockRtPanelEntity = mock<JxrPlatformAdapter.PanelEntity>()
         whenever(mockRtPanelEntity.getSize()).thenReturn(JxrPlatformAdapter.Dimensions(1f, 1f, 1f))
-        whenever(mockRuntime.createPanelEntity(any(), any(), any(), any(), any(), any(), any()))
+        whenever(
+                mockPlatformAdapter.createPanelEntity(
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any()
+                )
+            )
             .thenReturn(mockRtPanelEntity)
         whenever(mockRtPanelEntity.addComponent(any())).thenReturn(true)
         val panelEntity =
@@ -306,41 +337,52 @@
             )
         assertThat(panelEntity.addComponent(resizableComponent)).isTrue()
 
-        verify(mockRuntime).createResizableComponent(any(), any())
+        verify(mockPlatformAdapter).createResizableComponent(any(), any())
     }
 
     @Test
     fun setFullSpaceMode_callsThrough() {
         // Test that Session calls into the runtime.
         val bundle = Bundle().apply { putString("testkey", "testval") }
-        whenever(mockRuntime.setFullSpaceMode(any())).thenReturn(bundle)
+        whenever(mockPlatformAdapter.setFullSpaceMode(any())).thenReturn(bundle)
         val unused = session.setFullSpaceMode(bundle)
-        verify(mockRuntime).setFullSpaceMode(bundle)
+        verify(mockPlatformAdapter).setFullSpaceMode(bundle)
     }
 
     @Test
     fun setFullSpaceModeWithEnvironmentInherited_callsThrough() {
         // Test that Session calls into the runtime.
         val bundle = Bundle().apply { putString("testkey", "testval") }
-        whenever(mockRuntime.setFullSpaceModeWithEnvironmentInherited(any())).thenReturn(bundle)
+        whenever(mockPlatformAdapter.setFullSpaceModeWithEnvironmentInherited(any()))
+            .thenReturn(bundle)
         val unused = session.setFullSpaceModeWithEnvironmentInherited(bundle)
-        verify(mockRuntime).setFullSpaceModeWithEnvironmentInherited(bundle)
+        verify(mockPlatformAdapter).setFullSpaceModeWithEnvironmentInherited(bundle)
     }
 
     @Test
     fun setPreferredAspectRatio_callsThrough() {
         // Test that Session calls into the runtime.
         session.setPreferredAspectRatio(activity, 1.23f)
-        verify(mockRuntime).setPreferredAspectRatio(activity, 1.23f)
+        verify(mockPlatformAdapter).setPreferredAspectRatio(activity, 1.23f)
     }
 
     @Test
     fun getPanelEntityType_returnsAllPanelEntities() {
         val mockPanelEntity1 = mock<JxrPlatformAdapter.PanelEntity>()
         val mockActivityPanelEntity = mock<JxrPlatformAdapter.ActivityPanelEntity>()
-        whenever(mockRuntime.createPanelEntity(any(), any(), any(), any(), any(), any(), any()))
+        whenever(
+                mockPlatformAdapter.createPanelEntity(
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any()
+                )
+            )
             .thenReturn(mockPanelEntity1)
-        whenever(mockRuntime.createActivityPanelEntity(any(), any(), any(), any(), any()))
+        whenever(mockPlatformAdapter.createActivityPanelEntity(any(), any(), any(), any(), any()))
             .thenReturn(mockActivityPanelEntity)
         val panelEntity =
             session.createPanelEntity(
@@ -358,9 +400,19 @@
     @Test
     fun getEntitiesBaseType_returnsAllEntities() {
         val mockPanelEntity = mock<JxrPlatformAdapter.PanelEntity>()
-        whenever(mockRuntime.createPanelEntity(any(), any(), any(), any(), any(), any(), any()))
+        whenever(
+                mockPlatformAdapter.createPanelEntity(
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any(),
+                    any()
+                )
+            )
             .thenReturn(mockPanelEntity)
-        whenever(mockRuntime.createAnchorEntity(any(), any(), any(), any()))
+        whenever(mockPlatformAdapter.createAnchorEntity(any(), any(), any(), any()))
             .thenReturn(mockAnchorEntity)
         val panelEntity =
             session.createPanelEntity(
@@ -380,14 +432,14 @@
     fun addAndRemoveSpatialCapabilitiesChangedListener_callsRuntimeAddAndRemove() {
         val listener = Consumer<SpatialCapabilities> { _ -> }
         session.addSpatialCapabilitiesChangedListener(listener = listener)
-        verify(mockRuntime).addSpatialCapabilitiesChangedListener(any(), any())
+        verify(mockPlatformAdapter).addSpatialCapabilitiesChangedListener(any(), any())
         session.removeSpatialCapabilitiesChangedListener(listener)
-        verify(mockRuntime).removeSpatialCapabilitiesChangedListener(any())
+        verify(mockPlatformAdapter).removeSpatialCapabilitiesChangedListener(any())
     }
 
     @Test
     fun onDestroy_callsRuntimeDispose() {
         activityController.destroy()
-        verify(mockRuntime).dispose()
+        verify(mockPlatformAdapter).dispose()
     }
 }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/SpatialEnvironmentTest.kt b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/SpatialEnvironmentTest.kt
index 1297b37..78e239a 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/SpatialEnvironmentTest.kt
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/SpatialEnvironmentTest.kt
@@ -315,4 +315,16 @@
         verify(mockRtEnvironment!!).removeOnSpatialEnvironmentChangedListener(captor.capture())
         assertThat(listener).isEqualTo(captor.firstValue)
     }
+
+    @Test
+    fun requestFullSpaceMode_callsThrough() {
+        environment!!.requestFullSpaceMode()
+        verify(mockRuntime).requestFullSpaceMode()
+    }
+
+    @Test
+    fun requestHomeSpaceMode_callsThrough() {
+        environment!!.requestHomeSpaceMode()
+        verify(mockRuntime).requestHomeSpaceMode()
+    }
 }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/ActivityPanelEntityImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/ActivityPanelEntityImplTest.java
index d7c711b..ffae103 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/ActivityPanelEntityImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/ActivityPanelEntityImplTest.java
@@ -51,38 +51,42 @@
 
 @RunWith(RobolectricTestRunner.class)
 public class ActivityPanelEntityImplTest {
-    private final FakeXrExtensions fakeExtensions = new FakeXrExtensions();
-    private final FakeImpressApi fakeImpressApi = new FakeImpressApi();
-    private final ActivityController<Activity> activityController =
+    private final FakeXrExtensions mFakeExtensions = new FakeXrExtensions();
+    private final FakeImpressApi mFakeImpressApi = new FakeImpressApi();
+    private final ActivityController<Activity> mActivityController =
             Robolectric.buildActivity(Activity.class);
-    private final Activity hostActivity = activityController.create().start().get();
-    private final PixelDimensions windowBoundsPx = new PixelDimensions(640, 480);
-    private final FakeScheduledExecutorService fakeExecutor = new FakeScheduledExecutorService();
-    private final PerceptionLibrary perceptionLibrary = Mockito.mock(PerceptionLibrary.class);
-    private final SplitEngineSubspaceManager splitEngineSubspaceManager =
+    private final Activity mHostActivity = mActivityController.create().start().get();
+    private final PixelDimensions mWindowBoundsPx = new PixelDimensions(640, 480);
+    private final FakeScheduledExecutorService mFakeExecutor = new FakeScheduledExecutorService();
+    private final PerceptionLibrary mPerceptionLibrary = Mockito.mock(PerceptionLibrary.class);
+    private final SplitEngineSubspaceManager mSplitEngineSubspaceManager =
             Mockito.mock(SplitEngineSubspaceManager.class);
-    private final ImpSplitEngineRenderer splitEngineRenderer =
+    private final ImpSplitEngineRenderer mSplitEngineRenderer =
             Mockito.mock(ImpSplitEngineRenderer.class);
 
     private ActivityPanelEntity createActivityPanelEntity() {
-        when(perceptionLibrary.initSession(eq(hostActivity), anyInt(), eq(fakeExecutor)))
+        when(mPerceptionLibrary.initSession(eq(mHostActivity), anyInt(), eq(mFakeExecutor)))
                 .thenReturn(immediateFuture(Mockito.mock(Session.class)));
 
         JxrPlatformAdapter fakeRuntime =
                 JxrPlatformAdapterAxr.create(
-                        hostActivity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
+                        mHostActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
                         new EntityManager(),
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         /* useSplitEngine= */ false);
-        Pose pose = new Pose();
+        Pose mPose = new Pose();
 
         return fakeRuntime.createActivityPanelEntity(
-                pose, windowBoundsPx, "test", hostActivity, fakeRuntime.getActivitySpaceRootImpl());
+                mPose,
+                mWindowBoundsPx,
+                "test",
+                mHostActivity,
+                fakeRuntime.getActivitySpaceRootImpl());
     }
 
     @Test
@@ -95,28 +99,28 @@
     @Test
     public void activityPanelEntityLaunchActivity_callsActivityPanel() {
         ActivityPanelEntity activityPanelEntity = createActivityPanelEntity();
-        Intent launchIntent = activityController.getIntent();
+        Intent launchIntent = mActivityController.getIntent();
         activityPanelEntity.launchActivity(launchIntent, null);
 
-        FakeActivityPanel fakePanel = fakeExtensions.getActivityPanelForHost(hostActivity);
+        FakeActivityPanel fakePanel = mFakeExtensions.getActivityPanelForHost(mHostActivity);
 
         assertThat(fakePanel.getLaunchIntent()).isEqualTo(launchIntent);
         assertThat(fakePanel.getBundle()).isNull();
         assertThat(fakePanel.getBounds())
-                .isEqualTo(new Rect(0, 0, windowBoundsPx.width, windowBoundsPx.height));
+                .isEqualTo(new Rect(0, 0, mWindowBoundsPx.width, mWindowBoundsPx.height));
     }
 
     @Test
     public void activityPanelEntityMoveActivity_callActivityPanel() {
         ActivityPanelEntity activityPanelEntity = createActivityPanelEntity();
-        activityPanelEntity.moveActivity(hostActivity);
+        activityPanelEntity.moveActivity(mHostActivity);
 
-        FakeActivityPanel fakePanel = fakeExtensions.getActivityPanelForHost(hostActivity);
+        FakeActivityPanel fakePanel = mFakeExtensions.getActivityPanelForHost(mHostActivity);
 
-        assertThat(fakePanel.getActivity()).isEqualTo(hostActivity);
+        assertThat(fakePanel.getActivity()).isEqualTo(mHostActivity);
 
         assertThat(fakePanel.getBounds())
-                .isEqualTo(new Rect(0, 0, windowBoundsPx.width, windowBoundsPx.height));
+                .isEqualTo(new Rect(0, 0, mWindowBoundsPx.width, mWindowBoundsPx.height));
     }
 
     @Test
@@ -125,7 +129,7 @@
         Dimensions dimensions = new Dimensions(400f, 300f, 0f);
         activityPanelEntity.setSize(dimensions);
 
-        FakeActivityPanel fakePanel = fakeExtensions.getActivityPanelForHost(hostActivity);
+        FakeActivityPanel fakePanel = mFakeExtensions.getActivityPanelForHost(mHostActivity);
 
         assertThat(fakePanel.getBounds())
                 .isEqualTo(new Rect(0, 0, (int) dimensions.width, (int) dimensions.height));
@@ -142,7 +146,7 @@
         PixelDimensions dimensions = new PixelDimensions(400, 300);
         activityPanelEntity.setPixelDimensions(dimensions);
 
-        FakeActivityPanel fakePanel = fakeExtensions.getActivityPanelForHost(hostActivity);
+        FakeActivityPanel fakePanel = mFakeExtensions.getActivityPanelForHost(mHostActivity);
 
         assertThat(fakePanel.getBounds())
                 .isEqualTo(new Rect(0, 0, dimensions.width, dimensions.height));
@@ -157,7 +161,7 @@
         ActivityPanelEntity activityPanelEntity = createActivityPanelEntity();
         activityPanelEntity.dispose();
 
-        FakeActivityPanel fakePanel = fakeExtensions.getActivityPanelForHost(hostActivity);
+        FakeActivityPanel fakePanel = mFakeExtensions.getActivityPanelForHost(mHostActivity);
 
         assertThat(fakePanel.isDeleted()).isTrue();
     }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/ActivitySpaceImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/ActivitySpaceImplTest.java
index 5238b8fb..3ca7ccdf 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/ActivitySpaceImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/ActivitySpaceImplTest.java
@@ -58,84 +58,84 @@
 public final class ActivitySpaceImplTest extends SystemSpaceEntityImplTest {
     // TODO(b/329902726): Move this boilerplate for creating a TestJxrPlatformAdapter into a test
     // util
-    private final ActivityController<Activity> activityController =
+    private final ActivityController<Activity> mActivityController =
             Robolectric.buildActivity(Activity.class);
-    private final Activity activity = activityController.create().start().get();
-    private final FakeScheduledExecutorService fakeExecutor = new FakeScheduledExecutorService();
-    private final PerceptionLibrary perceptionLibrary = Mockito.mock(PerceptionLibrary.class);
-    private final SplitEngineSubspaceManager splitEngineSubspaceManager =
+    private final Activity mActivity = mActivityController.create().start().get();
+    private final FakeScheduledExecutorService mFakeExecutor = new FakeScheduledExecutorService();
+    private final PerceptionLibrary mPerceptionLibrary = Mockito.mock(PerceptionLibrary.class);
+    private final SplitEngineSubspaceManager mSplitEngineSubspaceManager =
             Mockito.mock(SplitEngineSubspaceManager.class);
-    private final ImpSplitEngineRenderer splitEngineRenderer =
+    private final ImpSplitEngineRenderer mSplitEngineRenderer =
             Mockito.mock(ImpSplitEngineRenderer.class);
 
-    private FakeXrExtensions fakeExtensions;
-    private FakeImpressApi fakeImpressApi;
-    private JxrPlatformAdapter testRuntime;
-    private ActivitySpace activitySpace;
+    private FakeXrExtensions mFakeExtensions;
+    private FakeImpressApi mFakeImpressApi;
+    private JxrPlatformAdapter mTestRuntime;
+    private ActivitySpace mActivitySpace;
 
     @Before
     public void setUp() {
-        fakeExtensions = new FakeXrExtensions();
-        fakeImpressApi = new FakeImpressApi();
-        when(perceptionLibrary.initSession(eq(activity), anyInt(), eq(fakeExecutor)))
+        mFakeExtensions = new FakeXrExtensions();
+        mFakeImpressApi = new FakeImpressApi();
+        when(mPerceptionLibrary.initSession(eq(mActivity), anyInt(), eq(mFakeExecutor)))
                 .thenReturn(immediateFuture(Mockito.mock(Session.class)));
 
-        testRuntime =
+        mTestRuntime =
                 JxrPlatformAdapterAxr.create(
-                        activity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
+                        mActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
                         new EntityManager(),
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         /* useSplitEngine= */ false);
 
-        activitySpace = testRuntime.getActivitySpace();
+        mActivitySpace = mTestRuntime.getActivitySpace();
 
         // This is slightly hacky. We're grabbing the singleton instance of the ActivitySpaceImpl
         // that
         // was created by the RuntimeImpl. Ideally we'd have an interface to inject the
         // ActivitySpace
         // for testing.  For now this is fine since there isn't an interface difference (yet).
-        assertThat(activitySpace).isInstanceOf(ActivitySpaceImpl.class);
-        assertThat(activitySpace).isNotNull();
+        assertThat(mActivitySpace).isInstanceOf(ActivitySpaceImpl.class);
+        assertThat(mActivitySpace).isNotNull();
     }
 
     @Override
     protected SystemSpaceEntityImpl getSystemSpaceEntityImpl() {
-        return (SystemSpaceEntityImpl) activitySpace;
+        return (SystemSpaceEntityImpl) mActivitySpace;
     }
 
     @Override
     protected FakeScheduledExecutorService getDefaultFakeExecutor() {
-        return fakeExecutor;
+        return mFakeExecutor;
     }
 
     @Override
     protected AndroidXrEntity createChildAndroidXrEntity() {
-        return (AndroidXrEntity) testRuntime.createEntity(new Pose(), "child", activitySpace);
+        return (AndroidXrEntity) mTestRuntime.createEntity(new Pose(), "child", mActivitySpace);
     }
 
     @Override
     protected ActivitySpaceImpl getActivitySpaceEntity() {
-        return (ActivitySpaceImpl) activitySpace;
+        return (ActivitySpaceImpl) mActivitySpace;
     }
 
     @Test
     public void getBounds_returnsBounds() {
-        assertThat(activitySpace.getBounds().width).isPositiveInfinity();
-        assertThat(activitySpace.getBounds().height).isPositiveInfinity();
-        assertThat(activitySpace.getBounds().depth).isPositiveInfinity();
+        assertThat(mActivitySpace.getBounds().width).isPositiveInfinity();
+        assertThat(mActivitySpace.getBounds().height).isPositiveInfinity();
+        assertThat(mActivitySpace.getBounds().depth).isPositiveInfinity();
 
         FakeSpatialState spatialState = new FakeSpatialState();
         spatialState.setBounds(new Bounds(100.0f, 200.0f, 300.0f));
-        fakeExtensions.sendSpatialState(spatialState);
+        mFakeExtensions.sendSpatialState(spatialState);
 
-        assertThat(activitySpace.getBounds().width).isEqualTo(100f);
-        assertThat(activitySpace.getBounds().height).isEqualTo(200f);
-        assertThat(activitySpace.getBounds().depth).isEqualTo(300f);
+        assertThat(mActivitySpace.getBounds().width).isEqualTo(100f);
+        assertThat(mActivitySpace.getBounds().height).isEqualTo(200f);
+        assertThat(mActivitySpace.getBounds().depth).isEqualTo(300f);
     }
 
     @Test
@@ -145,8 +145,8 @@
 
         FakeSpatialState spatialState = new FakeSpatialState();
         spatialState.setBounds(new Bounds(100.0f, 200.0f, 300.0f));
-        activitySpace.addOnBoundsChangedListener(listener);
-        fakeExtensions.sendSpatialState(spatialState);
+        mActivitySpace.addOnBoundsChangedListener(listener);
+        mFakeExtensions.sendSpatialState(spatialState);
 
         verify(listener).onBoundsChanged(Mockito.refEq(new Dimensions(100.0f, 200.0f, 300.0f)));
     }
@@ -156,25 +156,25 @@
         JxrPlatformAdapter.ActivitySpace.OnBoundsChangedListener listener =
                 Mockito.mock(JxrPlatformAdapter.ActivitySpace.OnBoundsChangedListener.class);
 
-        activitySpace.addOnBoundsChangedListener(listener);
-        activitySpace.removeOnBoundsChangedListener(listener);
+        mActivitySpace.addOnBoundsChangedListener(listener);
+        mActivitySpace.removeOnBoundsChangedListener(listener);
         FakeSpatialState spatialState = new FakeSpatialState();
         spatialState.setBounds(new Bounds(100.0f, 200.0f, 300.0f));
-        fakeExtensions.sendSpatialState(spatialState);
+        mFakeExtensions.sendSpatialState(spatialState);
 
         verify(listener, Mockito.never()).onBoundsChanged(Mockito.any());
     }
 
     @Test
     public void getPoseInActivitySpace_returnsIdentity() {
-        ActivitySpaceImpl activitySpaceImpl = (ActivitySpaceImpl) activitySpace;
+        ActivitySpaceImpl activitySpaceImpl = (ActivitySpaceImpl) mActivitySpace;
 
         assertPose(activitySpaceImpl.getPoseInActivitySpace(), new Pose());
     }
 
     @Test
     public void getActivitySpaceScale_returnsUnitScale() {
-        ActivitySpaceImpl activitySpaceImpl = (ActivitySpaceImpl) activitySpace;
+        ActivitySpaceImpl activitySpaceImpl = (ActivitySpaceImpl) mActivitySpace;
         activitySpaceImpl.setOpenXrReferenceSpacePose(Matrix4.fromScale(5f));
         assertVector3(activitySpaceImpl.getActivitySpaceScale(), new Vector3(1f, 1f, 1f));
     }
@@ -182,12 +182,12 @@
     @Test
     public void setScale_doesNothing() throws Exception {
         Vector3 scale = new Vector3(1, 1, 9999);
-        activitySpace.setScale(scale);
+        mActivitySpace.setScale(scale);
 
         // The returned scale(s) here should be the identity scale despite the setScale call.
-        assertThat(activitySpace.getScale().getX()).isWithin(1e-5f).of(1.0f);
-        assertThat(activitySpace.getScale().getY()).isWithin(1e-5f).of(1.0f);
-        assertThat(activitySpace.getScale().getZ()).isWithin(1e-5f).of(1.0f);
+        assertThat(mActivitySpace.getScale().getX()).isWithin(1e-5f).of(1.0f);
+        assertThat(mActivitySpace.getScale().getY()).isWithin(1e-5f).of(1.0f);
+        assertThat(mActivitySpace.getScale().getZ()).isWithin(1e-5f).of(1.0f);
 
         // Note that there's no exception thrown.
     }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/AnchorEntityImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/AnchorEntityImplTest.java
index 84b93bb..e2edc73 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/AnchorEntityImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/AnchorEntityImplTest.java
@@ -73,12 +73,12 @@
 @RunWith(RobolectricTestRunner.class)
 public final class AnchorEntityImplTest extends SystemSpaceEntityImplTest {
     private static class FakeExportableAnchor implements ExportableAnchor {
-        private final long nativePointer;
-        private final IBinder anchorToken;
-        private final Pose pose;
-        private final TrackingState trackingState;
-        private final PersistenceState persistenceState;
-        private final UUID uuid;
+        private final long mNativePointer;
+        private final IBinder mAnchorToken;
+        private final Pose mPose;
+        private final TrackingState mTrackingState;
+        private final PersistenceState mPersistenceState;
+        private final UUID mUuid;
 
         public FakeExportableAnchor(
                 long nativePointer,
@@ -87,42 +87,42 @@
                 TrackingState trackingState,
                 PersistenceState persistenceState,
                 UUID uuid) {
-            this.nativePointer = nativePointer;
-            this.anchorToken = anchorToken;
-            this.pose = pose;
-            this.trackingState = trackingState;
-            this.persistenceState = persistenceState;
-            this.uuid = uuid;
+            mNativePointer = nativePointer;
+            mAnchorToken = anchorToken;
+            mPose = pose;
+            mTrackingState = trackingState;
+            mPersistenceState = persistenceState;
+            mUuid = uuid;
         }
 
         @Override
         public long getNativePointer() {
-            return nativePointer;
+            return mNativePointer;
         }
 
         @Override
         public IBinder getAnchorToken() {
-            return anchorToken;
+            return mAnchorToken;
         }
 
         @Override
         public Pose getPose() {
-            return pose;
+            return mPose;
         }
 
         @Override
         public TrackingState getTrackingState() {
-            return trackingState;
+            return mTrackingState;
         }
 
         @Override
         public PersistenceState getPersistenceState() {
-            return persistenceState;
+            return mPersistenceState;
         }
 
         @Override
         public UUID getUuid() {
-            return uuid;
+            return mUuid;
         }
 
         @Override
@@ -136,38 +136,38 @@
     private static final Plane.Type PLANE_TYPE = Plane.Type.VERTICAL;
     private static final Plane.Label PLANE_LABEL = Plane.Label.WALL;
     private static final long NATIVE_POINTER = 1234567890L;
-    private final AndroidXrEntity activitySpaceRoot = Mockito.mock(AndroidXrEntity.class);
-    private final FakeXrExtensions fakeExtensions = new FakeXrExtensions();
-    private final PerceptionLibrary perceptionLibrary = Mockito.mock(PerceptionLibrary.class);
-    private final Session session = Mockito.mock(Session.class);
-    private final Plane plane = mock(Plane.class);
-    private final Anchor anchor = Mockito.mock(Anchor.class);
-    private final OnStateChangedListener anchorStateListener =
+    private final AndroidXrEntity mActivitySpaceRoot = Mockito.mock(AndroidXrEntity.class);
+    private final FakeXrExtensions mFakeExtensions = new FakeXrExtensions();
+    private final PerceptionLibrary mPerceptionLibrary = Mockito.mock(PerceptionLibrary.class);
+    private final Session mSession = Mockito.mock(Session.class);
+    private final Plane mPlane = mock(Plane.class);
+    private final Anchor mAnchor = Mockito.mock(Anchor.class);
+    private final OnStateChangedListener mAnchorStateListener =
             Mockito.mock(OnStateChangedListener.class);
-    private final IBinder sharedAnchorToken = Mockito.mock(IBinder.class);
-    private final FakeScheduledExecutorService executor = new FakeScheduledExecutorService();
-    private final EntityManager entityManager = new EntityManager();
-    private final PersistStateChangeListener persistStateChangeListener =
+    private final IBinder mSharedAnchorToken = Mockito.mock(IBinder.class);
+    private final FakeScheduledExecutorService mExecutor = new FakeScheduledExecutorService();
+    private final EntityManager mEntityManager = new EntityManager();
+    private final PersistStateChangeListener mPersistStateChangeListener =
             Mockito.mock(PersistStateChangeListener.class);
-    private final androidx.xr.scenecore.impl.perception.Pose perceptionIdentityPose =
+    private final androidx.xr.scenecore.impl.perception.Pose mPerceptionIdentityPose =
             androidx.xr.scenecore.impl.perception.Pose.identity();
-    private long currentTimeMillis = 1000000000L;
-    private ActivitySpaceImpl activitySpace;
+    private long mCurrentTimeMillis = 1000000000L;
+    private ActivitySpaceImpl mActivitySpace;
 
     @Before
     public void doBeforeEachTest() {
-        Node taskNode = fakeExtensions.createNode();
-        this.activitySpace =
+        Node taskNode = mFakeExtensions.createNode();
+        mActivitySpace =
                 new ActivitySpaceImpl(
                         taskNode,
-                        fakeExtensions,
-                        entityManager,
-                        () -> fakeExtensions.fakeSpatialState,
-                        executor);
-        SystemClock.setCurrentTimeMillis(currentTimeMillis);
+                        mFakeExtensions,
+                        mEntityManager,
+                        () -> mFakeExtensions.fakeSpatialState,
+                        mExecutor);
+        SystemClock.setCurrentTimeMillis(mCurrentTimeMillis);
 
         // By default, set the activity space to the root of the underlying OpenXR reference space.
-        this.activitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
     }
 
     /**
@@ -181,7 +181,7 @@
 
     @Override
     protected FakeScheduledExecutorService getDefaultFakeExecutor() {
-        return executor;
+        return mExecutor;
     }
 
     @Override
@@ -191,16 +191,16 @@
 
     @Override
     protected ActivitySpaceImpl getActivitySpaceEntity() {
-        return this.activitySpace;
+        return mActivitySpace;
     }
 
     // Advances the clock and the executor. The fake executor is not based on the clock because we
     // are
     // using the SystemClock but they can be advanced together.
     void advanceClock(Duration duration) {
-        currentTimeMillis += duration.toMillis();
-        SystemClock.setCurrentTimeMillis(currentTimeMillis);
-        executor.simulateSleepExecutingAllTasks(duration);
+        mCurrentTimeMillis += duration.toMillis();
+        SystemClock.setCurrentTimeMillis(mCurrentTimeMillis);
+        mExecutor.simulateSleepExecutingAllTasks(duration);
     }
 
     /** Creates an AnchorEntityImpl instance. */
@@ -210,19 +210,19 @@
 
     /** Creates an AnchorEntityImpl instance with a timeout. */
     private AnchorEntityImpl createAnchorEntityWithTimeout(Duration anchorSearchTimeout) {
-        Node node = fakeExtensions.createNode();
+        Node node = mFakeExtensions.createNode();
         return AnchorEntityImpl.createSemanticAnchor(
                 node,
                 ANCHOR_DIMENSIONS,
                 PlaneType.VERTICAL,
                 PlaneSemantic.WALL,
                 anchorSearchTimeout,
-                activitySpace,
-                activitySpaceRoot,
-                fakeExtensions,
-                entityManager,
-                executor,
-                perceptionLibrary);
+                mActivitySpace,
+                mActivitySpaceRoot,
+                mFakeExtensions,
+                mEntityManager,
+                mExecutor,
+                mPerceptionLibrary);
     }
 
     /**
@@ -231,126 +231,127 @@
      */
     private AnchorEntityImpl createPersistedAnchorEntityWithTimeout(
             UUID uuid, Duration anchorSearchTimeout) {
-        Node node = fakeExtensions.createNode();
+        Node node = mFakeExtensions.createNode();
         return AnchorEntityImpl.createPersistedAnchor(
                 node,
                 uuid,
                 anchorSearchTimeout,
-                activitySpace,
-                activitySpaceRoot,
-                fakeExtensions,
-                entityManager,
-                executor,
-                perceptionLibrary);
+                mActivitySpace,
+                mActivitySpaceRoot,
+                mFakeExtensions,
+                mEntityManager,
+                mExecutor,
+                mPerceptionLibrary);
     }
 
     /** Creates an AnchorEntityImpl instance and initializes it with a persisted anchor. */
     private AnchorEntityImpl createInitializedPersistedAnchorEntity(Anchor anchor, UUID uuid) {
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.createAnchorFromUuid(uuid)).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.createAnchorFromUuid(uuid)).thenReturn(anchor);
+        when(anchor.getAnchorToken()).thenReturn(mSharedAnchorToken);
 
-        Node node = fakeExtensions.createNode();
+        Node node = mFakeExtensions.createNode();
         return AnchorEntityImpl.createPersistedAnchor(
                 node,
                 uuid,
                 /* anchorSearchTimeout= */ null,
-                activitySpace,
-                activitySpaceRoot,
-                fakeExtensions,
-                entityManager,
-                executor,
-                perceptionLibrary);
+                mActivitySpace,
+                mActivitySpaceRoot,
+                mFakeExtensions,
+                mEntityManager,
+                mExecutor,
+                mPerceptionLibrary);
     }
 
     /**
      * Creates an AnchorEntityImpl and initializes it with an anchor from the perception library.
      */
     private AnchorEntityImpl createAndInitAnchorEntity() {
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
-        when(plane.getData(any()))
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.getAllPlanes()).thenReturn(ImmutableList.of(mPlane));
+        when(mPlane.getData(any()))
                 .thenReturn(
                         new Plane.PlaneData(
-                                perceptionIdentityPose,
+                                mPerceptionIdentityPose,
                                 ANCHOR_DIMENSIONS.width,
                                 ANCHOR_DIMENSIONS.height,
                                 PLANE_TYPE.intValue,
                                 PLANE_LABEL.intValue));
-        when(plane.createAnchor(eq(perceptionIdentityPose), any())).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
+        when(mPlane.createAnchor(eq(mPerceptionIdentityPose), any())).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(mSharedAnchorToken);
 
         return createSemanticAnchorEntity();
     }
 
     private AnchorEntityImpl createInitAndPersistAnchorEntity() {
-        when(anchor.persist()).thenReturn(UUID.randomUUID());
+        when(mAnchor.persist()).thenReturn(UUID.randomUUID());
         AnchorEntityImpl anchorEntity = createAndInitAnchorEntity();
-        anchorEntity.registerPersistStateChangeListener(persistStateChangeListener);
+        anchorEntity.registerPersistStateChangeListener(mPersistStateChangeListener);
         UUID unused = anchorEntity.persist();
         return anchorEntity;
     }
 
     private AnchorEntityImpl createAnchorEntityFromPlane() {
-        when(anchor.persist()).thenReturn(UUID.randomUUID());
+        when(mAnchor.persist()).thenReturn(UUID.randomUUID());
 
-        Node node = fakeExtensions.createNode();
+        Node node = mFakeExtensions.createNode();
         return AnchorEntityImpl.createAnchorFromPlane(
                 node,
-                plane,
+                mPlane,
                 new Pose(),
-                MILLISECONDS.toNanos(currentTimeMillis),
-                activitySpace,
-                activitySpaceRoot,
-                fakeExtensions,
-                entityManager,
-                executor,
-                perceptionLibrary);
+                MILLISECONDS.toNanos(mCurrentTimeMillis),
+                mActivitySpace,
+                mActivitySpaceRoot,
+                mFakeExtensions,
+                mEntityManager,
+                mExecutor,
+                mPerceptionLibrary);
     }
 
     private AnchorEntityImpl createAnchorEntityFromPerceptionAnchor(
             androidx.xr.arcore.Anchor perceptionAnchor) {
-        Node node = fakeExtensions.createNode();
+        Node node = mFakeExtensions.createNode();
 
         return AnchorEntityImpl.createAnchorFromPerceptionAnchor(
                 node,
                 perceptionAnchor,
-                activitySpace,
-                activitySpaceRoot,
-                fakeExtensions,
-                entityManager,
-                executor,
-                perceptionLibrary);
+                mActivitySpace,
+                mActivitySpaceRoot,
+                mFakeExtensions,
+                mEntityManager,
+                mExecutor,
+                mPerceptionLibrary);
     }
 
     /** Creates a generic glTF entity. */
     private GltfEntityImpl createGltfEntity() {
         FakeGltfModelToken modelToken = new FakeGltfModelToken("model");
         GltfModelResourceImpl model = new GltfModelResourceImpl(modelToken);
-        return new GltfEntityImpl(model, activitySpace, fakeExtensions, entityManager, executor);
+        return new GltfEntityImpl(
+                model, mActivitySpace, mFakeExtensions, mEntityManager, mExecutor);
     }
 
     @Test
     public void createAnchorEntityWithPersistedAnchor_returnsAnchored() throws Exception {
         AnchorEntityImpl anchorEntity =
-                createInitializedPersistedAnchorEntity(anchor, UUID.randomUUID());
+                createInitializedPersistedAnchorEntity(mAnchor, UUID.randomUUID());
         assertThat(anchorEntity).isNotNull();
         assertThat(anchorEntity.getState()).isEqualTo(State.ANCHORED);
         assertThat(((FakeNode) anchorEntity.getNode()).getName())
                 .isEqualTo(AnchorEntityImpl.ANCHOR_NODE_NAME);
-        assertThat(((FakeNode) anchorEntity.getNode()).getAnchorId()).isEqualTo(sharedAnchorToken);
+        assertThat(((FakeNode) anchorEntity.getNode()).getAnchorId()).isEqualTo(mSharedAnchorToken);
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSISTED);
     }
 
     @Test
     public void createAnchorEntityWithPersistedAnchor_persistAnchor_returnsUuid() throws Exception {
         UUID uuid = UUID.randomUUID();
-        AnchorEntityImpl anchorEntity = createInitializedPersistedAnchorEntity(anchor, uuid);
+        AnchorEntityImpl anchorEntity = createInitializedPersistedAnchorEntity(mAnchor, uuid);
         assertThat(anchorEntity).isNotNull();
         assertThat(anchorEntity.getState()).isEqualTo(State.ANCHORED);
         assertThat(((FakeNode) anchorEntity.getNode()).getName())
                 .isEqualTo(AnchorEntityImpl.ANCHOR_NODE_NAME);
-        assertThat(((FakeNode) anchorEntity.getNode()).getAnchorId()).isEqualTo(sharedAnchorToken);
+        assertThat(((FakeNode) anchorEntity.getNode()).getAnchorId()).isEqualTo(mSharedAnchorToken);
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSISTED);
 
         UUID returnedUuid = anchorEntity.persist();
@@ -359,7 +360,7 @@
 
     @Test
     public void createPersistedAnchorEntity_sessionNotReady_keepUnanchored() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(null);
+        when(mPerceptionLibrary.getSession()).thenReturn(null);
         AnchorEntityImpl anchorEntity =
                 createPersistedAnchorEntityWithTimeout(
                         UUID.randomUUID(), /* anchorSearchTimeout= */ null);
@@ -372,8 +373,8 @@
     public void createPersistedAnchorEntity_persistedAnchorNotFound_keepUnanchored()
             throws Exception {
         UUID uuid = UUID.randomUUID();
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.createAnchorFromUuid(uuid)).thenReturn(null);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.createAnchorFromUuid(uuid)).thenReturn(null);
         AnchorEntityImpl anchorEntity =
                 createPersistedAnchorEntityWithTimeout(uuid, /* anchorSearchTimeout= */ null);
 
@@ -387,9 +388,9 @@
     public void createPersistedAnchorEntity_persistedAnchorHasNoToken_keepUnanchored()
             throws Exception {
         UUID uuid = UUID.randomUUID();
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.createAnchorFromUuid(uuid)).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(null);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.createAnchorFromUuid(uuid)).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(null);
         AnchorEntityImpl anchorEntity =
                 createPersistedAnchorEntityWithTimeout(uuid, /* anchorSearchTimeout= */ null);
 
@@ -400,23 +401,23 @@
     @Test
     public void createPersistedAnchorEntity_delayedSession_callsCallback() throws Exception {
         // This will return an error on the first attempt so will need to be called twice.
-        when(perceptionLibrary.getSession()).thenReturn(null).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(null).thenReturn(mSession);
         UUID uuid = UUID.randomUUID();
-        when(session.createAnchorFromUuid(uuid)).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
+        when(mSession.createAnchorFromUuid(uuid)).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(mSharedAnchorToken);
 
         AnchorEntityImpl anchorEntity =
                 createPersistedAnchorEntityWithTimeout(uuid, /* anchorSearchTimeout= */ null);
-        anchorEntity.setOnStateChangedListener(anchorStateListener);
+        anchorEntity.setOnStateChangedListener(mAnchorStateListener);
 
-        verify(anchorStateListener, never()).onStateChanged(State.ANCHORED);
+        verify(mAnchorStateListener, never()).onStateChanged(State.ANCHORED);
         assertThat(anchorEntity).isNotNull();
         assertThat(anchorEntity.getState()).isEqualTo(State.UNANCHORED);
 
         // The anchor starts as unanchored. Advance the executor to try again successfully and get a
         // callback for the anchor to be anchored.
         advanceClock(AnchorEntityImpl.ANCHOR_SEARCH_DELAY);
-        verify(anchorStateListener).onStateChanged(State.ANCHORED);
+        verify(mAnchorStateListener).onStateChanged(State.ANCHORED);
         assertThat(anchorEntity.getState()).isEqualTo(State.ANCHORED);
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSISTED);
     }
@@ -424,23 +425,23 @@
     @Test
     public void createPersistedAnchorEntity_delayedAnchor_callsCallback() throws Exception {
         // This will return an error on the first attempt so will need to be called twice.
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
         UUID uuid = UUID.randomUUID();
-        when(session.createAnchorFromUuid(uuid)).thenReturn(anchor).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(null).thenReturn(sharedAnchorToken);
+        when(mSession.createAnchorFromUuid(uuid)).thenReturn(mAnchor).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(null).thenReturn(mSharedAnchorToken);
 
         AnchorEntityImpl anchorEntity =
                 createPersistedAnchorEntityWithTimeout(uuid, /* anchorSearchTimeout= */ null);
-        anchorEntity.setOnStateChangedListener(anchorStateListener);
+        anchorEntity.setOnStateChangedListener(mAnchorStateListener);
 
-        verify(anchorStateListener, never()).onStateChanged(State.ANCHORED);
+        verify(mAnchorStateListener, never()).onStateChanged(State.ANCHORED);
         assertThat(anchorEntity).isNotNull();
         assertThat(anchorEntity.getState()).isEqualTo(State.UNANCHORED);
 
         // The anchor starts as unanchored. Advance the executor to try again successfully and get a
         // callback for the anchor to be anchored.
         advanceClock(AnchorEntityImpl.ANCHOR_SEARCH_DELAY);
-        verify(anchorStateListener).onStateChanged(State.ANCHORED);
+        verify(mAnchorStateListener).onStateChanged(State.ANCHORED);
         assertThat(anchorEntity.getState()).isEqualTo(State.ANCHORED);
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSISTED);
     }
@@ -448,20 +449,20 @@
     @Test
     public void createPersistedAnchorEntity_delayedSession_timeout_noCallback() throws Exception {
         // This will return an error on the first attempt so will need to be called twice.
-        when(perceptionLibrary.getSession()).thenReturn(null).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(null).thenReturn(mSession);
         UUID uuid = UUID.randomUUID();
-        when(session.createAnchorFromUuid(uuid)).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
+        when(mSession.createAnchorFromUuid(uuid)).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(mSharedAnchorToken);
 
         AnchorEntityImpl anchorEntity =
                 createPersistedAnchorEntityWithTimeout(
                         uuid, AnchorEntityImpl.ANCHOR_SEARCH_DELAY.dividedBy(2));
-        anchorEntity.setOnStateChangedListener(anchorStateListener);
+        anchorEntity.setOnStateChangedListener(mAnchorStateListener);
 
         advanceClock(AnchorEntityImpl.ANCHOR_SEARCH_DELAY);
 
-        verify(anchorStateListener, never()).onStateChanged(State.ANCHORED);
-        verify(anchorStateListener).onStateChanged(State.TIMED_OUT);
+        verify(mAnchorStateListener, never()).onStateChanged(State.ANCHORED);
+        verify(mAnchorStateListener).onStateChanged(State.TIMED_OUT);
         assertThat(anchorEntity).isNotNull();
         assertThat(anchorEntity.getState()).isEqualTo(State.TIMED_OUT);
     }
@@ -482,13 +483,13 @@
         assertThat(anchorEntity.getState()).isEqualTo(State.ANCHORED);
         assertThat(((FakeNode) anchorEntity.getNode()).getName())
                 .isEqualTo(AnchorEntityImpl.ANCHOR_NODE_NAME);
-        assertThat(((FakeNode) anchorEntity.getNode()).getAnchorId()).isEqualTo(sharedAnchorToken);
+        assertThat(((FakeNode) anchorEntity.getNode()).getAnchorId()).isEqualTo(mSharedAnchorToken);
     }
 
     @Test
     public void createAndInitAnchor_noPlanes_remainsUnanchored() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.getAllPlanes()).thenReturn(ImmutableList.of());
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.getAllPlanes()).thenReturn(ImmutableList.of());
 
         AnchorEntityImpl anchorEntity = createSemanticAnchorEntity();
 
@@ -499,12 +500,12 @@
 
     @Test
     public void createAndInitAnchor_noViablePlane_remainsUnanchored() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
-        when(plane.getData(any()))
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.getAllPlanes()).thenReturn(ImmutableList.of(mPlane));
+        when(mPlane.getData(any()))
                 .thenReturn(
                         new Plane.PlaneData(
-                                perceptionIdentityPose,
+                                mPerceptionIdentityPose,
                                 ANCHOR_DIMENSIONS.width - 1,
                                 ANCHOR_DIMENSIONS.height,
                                 PLANE_TYPE.intValue,
@@ -520,62 +521,62 @@
     @Test
     public void createAndInitAnchor_delayedSession_callsCallback() throws Exception {
         // This will return an error on the first attempt so will need to be called twice.
-        when(perceptionLibrary.getSession()).thenReturn(null).thenReturn(session);
-        when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
-        when(plane.getData(any()))
+        when(mPerceptionLibrary.getSession()).thenReturn(null).thenReturn(mSession);
+        when(mSession.getAllPlanes()).thenReturn(ImmutableList.of(mPlane));
+        when(mPlane.getData(any()))
                 .thenReturn(
                         new Plane.PlaneData(
-                                perceptionIdentityPose,
+                                mPerceptionIdentityPose,
                                 ANCHOR_DIMENSIONS.width,
                                 ANCHOR_DIMENSIONS.height,
                                 PLANE_TYPE.intValue,
                                 PLANE_LABEL.intValue));
-        when(plane.createAnchor(eq(perceptionIdentityPose), any())).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
+        when(mPlane.createAnchor(eq(mPerceptionIdentityPose), any())).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(mSharedAnchorToken);
 
         AnchorEntityImpl anchorEntity = createSemanticAnchorEntity();
-        anchorEntity.setOnStateChangedListener(anchorStateListener);
+        anchorEntity.setOnStateChangedListener(mAnchorStateListener);
 
-        verify(anchorStateListener, never()).onStateChanged(State.ANCHORED);
+        verify(mAnchorStateListener, never()).onStateChanged(State.ANCHORED);
         assertThat(anchorEntity).isNotNull();
         assertThat(anchorEntity.getState()).isEqualTo(State.UNANCHORED);
 
         // The anchor starts as unanchored. Advance the executor to try again successfully and get a
         // callback for the anchor to be anchored.
         advanceClock(AnchorEntityImpl.ANCHOR_SEARCH_DELAY);
-        verify(anchorStateListener).onStateChanged(State.ANCHORED);
+        verify(mAnchorStateListener).onStateChanged(State.ANCHORED);
         assertThat(anchorEntity.getState()).isEqualTo(State.ANCHORED);
     }
 
     @Test
     public void createAndInitAnchor_delayedAnchor_callsCallback() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
         // This will return no planes on the first attempt so will need to be called twice.
-        when(session.getAllPlanes())
+        when(mSession.getAllPlanes())
                 .thenReturn(ImmutableList.of())
-                .thenReturn(ImmutableList.of(plane));
-        when(plane.getData(any()))
+                .thenReturn(ImmutableList.of(mPlane));
+        when(mPlane.getData(any()))
                 .thenReturn(
                         new Plane.PlaneData(
-                                perceptionIdentityPose,
+                                mPerceptionIdentityPose,
                                 ANCHOR_DIMENSIONS.width,
                                 ANCHOR_DIMENSIONS.height,
                                 PLANE_TYPE.intValue,
                                 PLANE_LABEL.intValue));
-        when(plane.createAnchor(eq(perceptionIdentityPose), any())).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
+        when(mPlane.createAnchor(eq(mPerceptionIdentityPose), any())).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(mSharedAnchorToken);
 
         AnchorEntityImpl anchorEntity = createSemanticAnchorEntity();
-        anchorEntity.setOnStateChangedListener(anchorStateListener);
+        anchorEntity.setOnStateChangedListener(mAnchorStateListener);
 
-        verify(anchorStateListener, never()).onStateChanged(State.ANCHORED);
+        verify(mAnchorStateListener, never()).onStateChanged(State.ANCHORED);
         assertThat(anchorEntity).isNotNull();
         assertThat(anchorEntity.getState()).isEqualTo(State.UNANCHORED);
 
         // The anchor starts as unanchored. Advance the executor to try again successfully and get a
         // callback for the anchor to be anchored.
         advanceClock(AnchorEntityImpl.ANCHOR_SEARCH_DELAY);
-        verify(anchorStateListener).onStateChanged(State.ANCHORED);
+        verify(mAnchorStateListener).onStateChanged(State.ANCHORED);
         assertThat(anchorEntity.getState()).isEqualTo(State.ANCHORED);
     }
 
@@ -583,28 +584,28 @@
     public void createAndInitAnchor_delayedSessionAndAnchor_callsCallback() throws Exception {
         // This will return an error on the first attempt then it will find no planes on the
         // second attempt. So it will need to be called three times.
-        when(perceptionLibrary.getSession())
+        when(mPerceptionLibrary.getSession())
                 .thenReturn(null)
-                .thenReturn(session)
-                .thenReturn(session);
-        when(session.getAllPlanes())
+                .thenReturn(mSession)
+                .thenReturn(mSession);
+        when(mSession.getAllPlanes())
                 .thenReturn(ImmutableList.of())
-                .thenReturn(ImmutableList.of(plane));
-        when(plane.getData(any()))
+                .thenReturn(ImmutableList.of(mPlane));
+        when(mPlane.getData(any()))
                 .thenReturn(
                         new Plane.PlaneData(
-                                perceptionIdentityPose,
+                                mPerceptionIdentityPose,
                                 ANCHOR_DIMENSIONS.width,
                                 ANCHOR_DIMENSIONS.height,
                                 PLANE_TYPE.intValue,
                                 PLANE_LABEL.intValue));
-        when(plane.createAnchor(eq(perceptionIdentityPose), any())).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
+        when(mPlane.createAnchor(eq(mPerceptionIdentityPose), any())).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(mSharedAnchorToken);
 
         AnchorEntityImpl anchorEntity = createSemanticAnchorEntity();
-        anchorEntity.setOnStateChangedListener(anchorStateListener);
+        anchorEntity.setOnStateChangedListener(mAnchorStateListener);
 
-        verify(anchorStateListener, never()).onStateChanged(State.ANCHORED);
+        verify(mAnchorStateListener, never()).onStateChanged(State.ANCHORED);
         assertThat(anchorEntity).isNotNull();
         assertThat(anchorEntity.getState()).isEqualTo(State.UNANCHORED);
 
@@ -616,24 +617,24 @@
         // anchor
         // to be anchored.
         advanceClock(AnchorEntityImpl.ANCHOR_SEARCH_DELAY);
-        verify(anchorStateListener).onStateChanged(State.ANCHORED);
+        verify(mAnchorStateListener).onStateChanged(State.ANCHORED);
         assertThat(anchorEntity.getState()).isEqualTo(State.ANCHORED);
     }
 
     @Test
     public void createAndInitAnchor_noToken_returnsUnanchored() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
-        when(plane.getData(any()))
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.getAllPlanes()).thenReturn(ImmutableList.of(mPlane));
+        when(mPlane.getData(any()))
                 .thenReturn(
                         new Plane.PlaneData(
-                                perceptionIdentityPose,
+                                mPerceptionIdentityPose,
                                 ANCHOR_DIMENSIONS.width,
                                 ANCHOR_DIMENSIONS.height,
                                 PLANE_TYPE.intValue,
                                 PLANE_LABEL.intValue));
-        when(plane.createAnchor(eq(perceptionIdentityPose), any())).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(null);
+        when(mPlane.createAnchor(eq(mPerceptionIdentityPose), any())).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(null);
 
         AnchorEntityImpl anchorEntity = createSemanticAnchorEntity();
 
@@ -645,38 +646,38 @@
     public void createAndInitAnchor_withinTimeout_success() throws Exception {
         // The anchor creation will return an error so that it is called again on the executor. The
         // timeout will happen after the second attempt so it will still succeed.
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.getAllPlanes())
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.getAllPlanes())
                 .thenReturn(ImmutableList.of())
-                .thenReturn(ImmutableList.of(plane));
-        when(plane.getData(any()))
+                .thenReturn(ImmutableList.of(mPlane));
+        when(mPlane.getData(any()))
                 .thenReturn(
                         new Plane.PlaneData(
-                                perceptionIdentityPose,
+                                mPerceptionIdentityPose,
                                 ANCHOR_DIMENSIONS.width,
                                 ANCHOR_DIMENSIONS.height,
                                 PLANE_TYPE.intValue,
                                 PLANE_LABEL.intValue));
-        when(plane.createAnchor(eq(perceptionIdentityPose), any())).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
+        when(mPlane.createAnchor(eq(mPerceptionIdentityPose), any())).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(mSharedAnchorToken);
 
         // Create an anchor entity with a timeout of 1ms above the normal search delay.
         Duration timeout = AnchorEntityImpl.ANCHOR_SEARCH_DELAY.plusMillis(1);
         AnchorEntityImpl anchorEntity = createAnchorEntityWithTimeout(timeout);
-        anchorEntity.setOnStateChangedListener(anchorStateListener);
+        anchorEntity.setOnStateChangedListener(mAnchorStateListener);
 
-        verify(anchorStateListener, never()).onStateChanged(State.ANCHORED);
+        verify(mAnchorStateListener, never()).onStateChanged(State.ANCHORED);
         assertThat(anchorEntity).isNotNull();
         assertThat(anchorEntity.getState()).isEqualTo(State.UNANCHORED);
 
         // Advance the executor to try again it should now be anchored.
         advanceClock(AnchorEntityImpl.ANCHOR_SEARCH_DELAY);
-        verify(anchorStateListener).onStateChanged(State.ANCHORED);
+        verify(mAnchorStateListener).onStateChanged(State.ANCHORED);
         assertThat(anchorEntity.getState()).isEqualTo(State.ANCHORED);
 
         // Advance the clock past the timeout and verify that nothing changed.
         advanceClock(timeout.minus(AnchorEntityImpl.ANCHOR_SEARCH_DELAY));
-        verify(anchorStateListener, never()).onStateChanged(State.TIMED_OUT);
+        verify(mAnchorStateListener, never()).onStateChanged(State.TIMED_OUT);
         assertThat(anchorEntity.getState()).isEqualTo(State.ANCHORED);
     }
 
@@ -684,16 +685,16 @@
     public void createAndInitAnchor_passedTimeout_error() throws Exception {
         // The anchor creation will return an error so that it is called again on the executor. The
         // timeout will happen before the next call.
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.getAllPlanes()).thenReturn(ImmutableList.of());
-        when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.getAllPlanes()).thenReturn(ImmutableList.of());
+        when(mAnchor.getAnchorToken()).thenReturn(mSharedAnchorToken);
 
         // Create an anchor entity with a timeout of 1ms below the normal search delay.
         Duration timeout = AnchorEntityImpl.ANCHOR_SEARCH_DELAY.minusMillis(1);
         AnchorEntityImpl anchorEntity = createAnchorEntityWithTimeout(timeout);
-        anchorEntity.setOnStateChangedListener(anchorStateListener);
+        anchorEntity.setOnStateChangedListener(mAnchorStateListener);
 
-        verify(anchorStateListener, never()).onStateChanged(State.ERROR);
+        verify(mAnchorStateListener, never()).onStateChanged(State.ERROR);
         assertThat(anchorEntity).isNotNull();
         assertThat(anchorEntity.getState()).isEqualTo(State.UNANCHORED);
 
@@ -711,17 +712,17 @@
         // The anchor creation will return an error so that it is called again on the executor. The
         // timeout will happen after the second attempt so it will still succeed.
         int anchorAttempts = 100;
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.getAllPlanes()).thenReturn(ImmutableList.of());
-        when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.getAllPlanes()).thenReturn(ImmutableList.of());
+        when(mAnchor.getAnchorToken()).thenReturn(mSharedAnchorToken);
 
         // Create an anchor entity with a zero duration it should be search for indefinitely..
         AnchorEntityImpl anchorEntity = createAnchorEntityWithTimeout(Duration.ZERO);
-        anchorEntity.setOnStateChangedListener(anchorStateListener);
+        anchorEntity.setOnStateChangedListener(mAnchorStateListener);
 
         for (int i = 0; i < anchorAttempts - 1; i++) {
             advanceClock(AnchorEntityImpl.ANCHOR_SEARCH_DELAY);
-            verify(anchorStateListener, never()).onStateChanged(any());
+            verify(mAnchorStateListener, never()).onStateChanged(any());
             assertThat(anchorEntity).isNotNull();
             assertThat(anchorEntity.getState()).isEqualTo(State.UNANCHORED);
         }
@@ -780,7 +781,7 @@
     @Test
     public void anchorEntityGetActivitySpaceScale_returnsInverseOfActivitySpace() throws Exception {
         float activitySpaceScale = 5f;
-        this.activitySpace.setOpenXrReferenceSpacePose(Matrix4.fromScale(activitySpaceScale));
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.fromScale(activitySpaceScale));
         AnchorEntityImpl anchorEntity = createSemanticAnchorEntity();
         assertVector3(
                 anchorEntity.getActivitySpaceScale(),
@@ -791,7 +792,7 @@
     public void getPoseInActivitySpace_unanchored_returnsIdentityPose() {
         AnchorEntityImpl anchorEntity = createSemanticAnchorEntity();
         Pose pose = new Pose(new Vector3(1, 1, 1), new Quaternion(0, 1, 0, 1));
-        activitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
         anchorEntity.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
 
         assertPose(anchorEntity.getPoseInActivitySpace(), new Pose());
@@ -802,7 +803,7 @@
             getPoseInActivitySpace_noActivitySpaceOpenXrReferenceSpacePose_returnsIdentityPose() {
         AnchorEntityImpl anchorEntity = createAndInitAnchorEntity();
         Pose pose = new Pose(new Vector3(1, 1, 1), new Quaternion(0, 1, 0, 1));
-        activitySpace.openXrReferenceSpacePose = null;
+        mActivitySpace.mOpenXrReferenceSpacePose = null;
         anchorEntity.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
         assertPose(anchorEntity.getPoseInActivitySpace(), new Pose());
     }
@@ -811,7 +812,7 @@
     public void getPoseInActivitySpace_noAnchorOpenXrReferenceSpacePose_returnsIdentityPose() {
         AnchorEntityImpl anchorEntity = createAndInitAnchorEntity();
         Pose pose = new Pose(new Vector3(1, 1, 1), new Quaternion(0, 1, 0, 1));
-        activitySpace.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
         // anchorEntity.setOpenXrReferenceSpacePose(..) is not called to set the underlying pose.
 
         assertPose(anchorEntity.getPoseInActivitySpace(), new Pose());
@@ -821,7 +822,7 @@
     public void getPoseInActivitySpace_whenAtSamePose_returnsIdentityPose() {
         AnchorEntityImpl anchorEntity = createAndInitAnchorEntity();
         Pose pose = new Pose(new Vector3(1, 1, 1), new Quaternion(0, 1, 0, 1).toNormalized());
-        activitySpace.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
         anchorEntity.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
 
         assertPose(anchorEntity.getPoseInActivitySpace(), new Pose());
@@ -831,7 +832,7 @@
     public void getPoseInActivitySpace_returnsDifferencePose() {
         AnchorEntityImpl anchorEntity = createAndInitAnchorEntity();
         Pose pose = new Pose(new Vector3(1, 1, 1), new Quaternion(0, 1, 0, 1).toNormalized());
-        activitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
         anchorEntity.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
 
         assertPose(anchorEntity.getPoseInActivitySpace(), pose);
@@ -839,7 +840,7 @@
 
     @Test
     public void getPoseInActivitySpace_withNoActivitySpace_throwsException() throws Exception {
-        Node node = fakeExtensions.createNode();
+        Node node = mFakeExtensions.createNode();
         AnchorEntityImpl anchorEntity =
                 AnchorEntityImpl.createSemanticAnchor(
                         node,
@@ -848,11 +849,11 @@
                         /* planeSemantic= */ null,
                         /* anchorSearchTimeout= */ null,
                         /* activitySpace= */ null,
-                        activitySpaceRoot,
-                        fakeExtensions,
-                        entityManager,
-                        executor,
-                        perceptionLibrary);
+                        mActivitySpaceRoot,
+                        mFakeExtensions,
+                        mEntityManager,
+                        mExecutor,
+                        mPerceptionLibrary);
 
         assertThat(anchorEntity.getState()).isEqualTo(State.ERROR);
         assertThrows(IllegalStateException.class, anchorEntity::getPoseInActivitySpace);
@@ -862,7 +863,7 @@
     public void getActivitySpacePose_whenAtSamePose_returnsIdentityPose() {
         AnchorEntityImpl anchorEntity = createAndInitAnchorEntity();
         Pose pose = new Pose(new Vector3(1, 1, 1), new Quaternion(0, 1, 0, 1).toNormalized());
-        when(activitySpaceRoot.getPoseInActivitySpace()).thenReturn(pose);
+        when(mActivitySpaceRoot.getPoseInActivitySpace()).thenReturn(pose);
 
         anchorEntity.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
 
@@ -873,7 +874,7 @@
     public void getActivitySpacePose_returnsDifferencePose() {
         AnchorEntityImpl anchorEntity = createAndInitAnchorEntity();
         Pose pose = new Pose(new Vector3(1, 1, 1), new Quaternion(0, 1, 0, 1).toNormalized());
-        when(activitySpaceRoot.getPoseInActivitySpace()).thenReturn(new Pose());
+        when(mActivitySpaceRoot.getPoseInActivitySpace()).thenReturn(new Pose());
 
         anchorEntity.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
 
@@ -883,7 +884,7 @@
     @Test
     public void getActivitySpacePose_withNonAndroidXrActivitySpaceRoot_throwsException()
             throws Exception {
-        Node node = fakeExtensions.createNode();
+        Node node = mFakeExtensions.createNode();
         AnchorEntityImpl anchorEntity =
                 AnchorEntityImpl.createSemanticAnchor(
                         node,
@@ -891,12 +892,12 @@
                         /* planeType= */ null,
                         /* planeSemantic= */ null,
                         /* anchorSearchTimeout= */ null,
-                        activitySpace,
+                        mActivitySpace,
                         /* activitySpaceRoot= */ null,
-                        fakeExtensions,
-                        entityManager,
-                        executor,
-                        perceptionLibrary);
+                        mFakeExtensions,
+                        mEntityManager,
+                        mExecutor,
+                        mPerceptionLibrary);
 
         assertThat(anchorEntity.getState()).isEqualTo(State.ERROR);
         assertThrows(IllegalStateException.class, anchorEntity::getActivitySpacePose);
@@ -906,14 +907,14 @@
     public void transformPoseTo_withActivitySpace_returnsTransformedPose() {
         AnchorEntityImpl anchorEntity = createAndInitAnchorEntity();
         Pose pose = new Pose(new Vector3(1f, 2f, 3f), Quaternion.Identity);
-        activitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
         anchorEntity.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
 
         Pose anchorOffset =
                 new Pose(
                         new Vector3(10f, 0f, 0f),
                         Quaternion.fromEulerAngles(new Vector3(0f, 0f, 90f)));
-        Pose transformedPose = anchorEntity.transformPoseTo(anchorOffset, activitySpace);
+        Pose transformedPose = anchorEntity.transformPoseTo(anchorOffset, mActivitySpace);
 
         assertPose(
                 transformedPose,
@@ -929,13 +930,13 @@
         Pose pose = new Pose(new Vector3(1f, 2f, 3f), Quaternion.Identity);
         Pose childPose = new Pose(new Vector3(-1f, -2f, -3f), Quaternion.Identity);
 
-        activitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
-        activitySpace.addChild(childEntity1);
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
+        mActivitySpace.addChild(childEntity1);
         childEntity1.setPose(childPose);
         anchorEntity.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
 
         assertPose(
-                activitySpace.transformPoseTo(new Pose(), anchorEntity),
+                mActivitySpace.transformPoseTo(new Pose(), anchorEntity),
                 new Pose(new Vector3(-1f, -2f, -3f), Quaternion.Identity));
 
         Pose transformedPose = childEntity1.transformPoseTo(new Pose(), anchorEntity);
@@ -945,25 +946,25 @@
     @Test
     public void anchorEntity_setsParentAfterAnchoring() throws Exception {
         // This will return an error on the first attempt so will need to be called twice.
-        when(perceptionLibrary.getSession()).thenReturn(null).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(null).thenReturn(mSession);
 
-        when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
-        when(plane.getData(any()))
+        when(mSession.getAllPlanes()).thenReturn(ImmutableList.of(mPlane));
+        when(mPlane.getData(any()))
                 .thenReturn(
                         new Plane.PlaneData(
-                                perceptionIdentityPose,
+                                mPerceptionIdentityPose,
                                 ANCHOR_DIMENSIONS.width,
                                 ANCHOR_DIMENSIONS.height,
                                 PLANE_TYPE.intValue,
                                 PLANE_LABEL.intValue));
-        when(plane.createAnchor(eq(perceptionIdentityPose), any())).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
+        when(mPlane.createAnchor(eq(mPerceptionIdentityPose), any())).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(mSharedAnchorToken);
 
         AnchorEntityImpl anchorEntity = createSemanticAnchorEntity();
         assertThat(anchorEntity.getState()).isEqualTo(State.UNANCHORED);
 
         FakeNode anchorNode = (FakeNode) anchorEntity.getNode();
-        FakeNode rootNode = (FakeNode) activitySpace.getNode();
+        FakeNode rootNode = (FakeNode) mActivitySpace.getNode();
         assertThat(anchorNode.getParent()).isNull();
 
         // The anchor starts as unanchored. Advance the executor to wait for it to become anchored
@@ -976,22 +977,22 @@
 
     @Test
     public void disposeAnchor_detachesAnchor() throws Exception {
-        when(anchor.detach()).thenReturn(true);
+        when(mAnchor.detach()).thenReturn(true);
         AnchorEntityImpl anchorEntity = createAndInitAnchorEntity();
-        anchorEntity.setOnStateChangedListener(anchorStateListener);
-        verify(anchorStateListener, never()).onStateChanged(State.ERROR);
+        anchorEntity.setOnStateChangedListener(mAnchorStateListener);
+        verify(mAnchorStateListener, never()).onStateChanged(State.ERROR);
         assertThat(anchorEntity.getState()).isEqualTo(State.ANCHORED);
 
         // Verify the parent of the anchor is the root node (ActivitySpace) before disposing it.
         FakeNode anchorNode = (FakeNode) anchorEntity.getNode();
-        FakeNode rootNode = (FakeNode) activitySpace.getNode();
+        FakeNode rootNode = (FakeNode) mActivitySpace.getNode();
         assertThat(anchorNode.getParent()).isEqualTo(rootNode);
-        assertThat(anchorNode.getAnchorId()).isEqualTo(sharedAnchorToken);
+        assertThat(anchorNode.getAnchorId()).isEqualTo(mSharedAnchorToken);
 
         // Dispose the entity and verify that the state was updated.
         anchorEntity.dispose();
 
-        verify(anchorStateListener).onStateChanged(State.ERROR);
+        verify(mAnchorStateListener).onStateChanged(State.ERROR);
         assertThat(anchorEntity.getState()).isEqualTo(State.ERROR);
         assertThat(anchorNode.getParent()).isNull();
         assertThat(anchorNode.getAnchorId()).isNull();
@@ -999,13 +1000,13 @@
 
     @Test
     public void disposeAnchorUnanchered_stopsSearching() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(null);
+        when(mPerceptionLibrary.getSession()).thenReturn(null);
 
         AnchorEntityImpl anchorEntity = createSemanticAnchorEntity();
-        anchorEntity.setOnStateChangedListener(anchorStateListener);
+        anchorEntity.setOnStateChangedListener(mAnchorStateListener);
 
-        verify(perceptionLibrary).getSession();
-        verify(anchorStateListener, never()).onStateChanged(State.ERROR);
+        verify(mPerceptionLibrary).getSession();
+        verify(mAnchorStateListener, never()).onStateChanged(State.ERROR);
         assertThat(anchorEntity.getState()).isEqualTo(State.UNANCHORED);
 
         // Dispose the anchor entity before it was anchored.
@@ -1018,25 +1019,25 @@
         // again
         // once disposed.
         advanceClock(AnchorEntityImpl.ANCHOR_SEARCH_DELAY);
-        verify(perceptionLibrary).getSession();
+        verify(mPerceptionLibrary).getSession();
     }
 
     @Test
     public void disposeAnchorTwice_callsCalbackOnce() throws Exception {
-        when(anchor.detach()).thenReturn(true);
+        when(mAnchor.detach()).thenReturn(true);
         AnchorEntityImpl anchorEntity = createAndInitAnchorEntity();
-        anchorEntity.setOnStateChangedListener(anchorStateListener);
-        verify(anchorStateListener, never()).onStateChanged(State.ERROR);
+        anchorEntity.setOnStateChangedListener(mAnchorStateListener);
+        verify(mAnchorStateListener, never()).onStateChanged(State.ERROR);
 
         // Dispose the entity and verify that the state was updated.
         anchorEntity.dispose();
 
-        verify(anchorStateListener).onStateChanged(State.ERROR);
+        verify(mAnchorStateListener).onStateChanged(State.ERROR);
 
         // Dispose anchor again and verify onStateChanged was called only once.
         anchorEntity.dispose();
 
-        verify(anchorStateListener).onStateChanged(State.ERROR);
+        verify(mAnchorStateListener).onStateChanged(State.ERROR);
     }
 
     @Test
@@ -1057,29 +1058,29 @@
     @Test
     public void persistAnchor_returnsUuid() throws Exception {
         AnchorEntityImpl anchorEntity = createAndInitAnchorEntity();
-        when(anchor.persist()).thenReturn(UUID.randomUUID());
-        anchorEntity.registerPersistStateChangeListener(persistStateChangeListener);
+        when(mAnchor.persist()).thenReturn(UUID.randomUUID());
+        anchorEntity.registerPersistStateChangeListener(mPersistStateChangeListener);
         assertThat(anchorEntity.persist()).isNotNull();
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSIST_PENDING);
-        verify(persistStateChangeListener).onPersistStateChanged(PersistState.PERSIST_PENDING);
+        verify(mPersistStateChangeListener).onPersistStateChanged(PersistState.PERSIST_PENDING);
     }
 
     @Test
     public void persistAnchor_returnsNull() throws Exception {
         AnchorEntityImpl anchorEntity = createAndInitAnchorEntity();
-        when(anchor.persist()).thenReturn(null);
-        anchorEntity.registerPersistStateChangeListener(persistStateChangeListener);
+        when(mAnchor.persist()).thenReturn(null);
+        anchorEntity.registerPersistStateChangeListener(mPersistStateChangeListener);
         assertThat(anchorEntity.persist()).isNull();
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSIST_NOT_REQUESTED);
-        verify(persistStateChangeListener, never()).onPersistStateChanged(any());
+        verify(mPersistStateChangeListener, never()).onPersistStateChanged(any());
     }
 
     @Test
     public void persistAnchor_secondPersist_returnsSameUuid_updatesPersistStateOnce()
             throws Exception {
         AnchorEntityImpl anchorEntity = createAndInitAnchorEntity();
-        when(anchor.persist()).thenReturn(UUID.randomUUID());
-        anchorEntity.registerPersistStateChangeListener(persistStateChangeListener);
+        when(mAnchor.persist()).thenReturn(UUID.randomUUID());
+        anchorEntity.registerPersistStateChangeListener(mPersistStateChangeListener);
         UUID firstUuid = anchorEntity.persist();
         assertThat(firstUuid).isNotNull();
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSIST_PENDING);
@@ -1087,34 +1088,34 @@
         UUID secondUuid = anchorEntity.persist();
         assertThat(firstUuid).isEquivalentAccordingToCompareTo(secondUuid);
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSIST_PENDING);
-        verify(persistStateChangeListener).onPersistStateChanged(PersistState.PERSIST_PENDING);
+        verify(mPersistStateChangeListener).onPersistStateChanged(PersistState.PERSIST_PENDING);
     }
 
     @Test
     public void persistAnchor_updatesPersistStateToPersisted() throws Exception {
         AnchorEntityImpl anchorEntity = createInitAndPersistAnchorEntity();
-        when(anchor.getPersistState()).thenReturn(Anchor.PersistState.PERSISTED);
+        when(mAnchor.getPersistState()).thenReturn(Anchor.PersistState.PERSISTED);
 
-        executor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
+        mExecutor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSISTED);
-        verify(persistStateChangeListener).onPersistStateChanged(PersistState.PERSISTED);
+        verify(mPersistStateChangeListener).onPersistStateChanged(PersistState.PERSISTED);
     }
 
     @Test
     public void updatePersistState_delayedPersistedState_callsCallback() throws Exception {
         AnchorEntityImpl anchorEntity = createInitAndPersistAnchorEntity();
 
-        when(anchor.getPersistState())
+        when(mAnchor.getPersistState())
                 .thenReturn(Anchor.PersistState.PERSIST_PENDING)
                 .thenReturn(Anchor.PersistState.PERSISTED);
-        verify(persistStateChangeListener, never()).onPersistStateChanged(PersistState.PERSISTED);
+        verify(mPersistStateChangeListener, never()).onPersistStateChanged(PersistState.PERSISTED);
 
-        executor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
-        verify(persistStateChangeListener, never()).onPersistStateChanged(PersistState.PERSISTED);
+        mExecutor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
+        verify(mPersistStateChangeListener, never()).onPersistStateChanged(PersistState.PERSISTED);
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSIST_PENDING);
 
-        executor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
-        verify(persistStateChangeListener).onPersistStateChanged(PersistState.PERSISTED);
+        mExecutor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
+        verify(mPersistStateChangeListener).onPersistStateChanged(PersistState.PERSISTED);
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSISTED);
     }
 
@@ -1122,40 +1123,40 @@
     public void updatePersistState_noCallbackAfterStateBecomesPersisted() throws Exception {
         AnchorEntityImpl anchorEntity = createInitAndPersistAnchorEntity();
 
-        when(anchor.getPersistState()).thenReturn(Anchor.PersistState.PERSISTED);
-        executor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
+        when(mAnchor.getPersistState()).thenReturn(Anchor.PersistState.PERSISTED);
+        mExecutor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
 
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSISTED);
-        verify(persistStateChangeListener).onPersistStateChanged(PersistState.PERSISTED);
-        Mockito.clearInvocations(anchor);
-        Mockito.clearInvocations(persistStateChangeListener);
+        verify(mPersistStateChangeListener).onPersistStateChanged(PersistState.PERSISTED);
+        Mockito.clearInvocations(mAnchor);
+        Mockito.clearInvocations(mPersistStateChangeListener);
 
-        executor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
-        verify(anchor, never()).getPersistState();
-        verify(persistStateChangeListener, never()).onPersistStateChanged(any());
+        mExecutor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
+        verify(mAnchor, never()).getPersistState();
+        verify(mPersistStateChangeListener, never()).onPersistStateChanged(any());
     }
 
     @Test
     public void updatePersistState_noQueryForPersistStateAfterDispose() throws Exception {
         AnchorEntityImpl anchorEntity = createInitAndPersistAnchorEntity();
-        when(anchor.getPersistState()).thenReturn(Anchor.PersistState.PERSIST_PENDING);
-        executor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
-        verify(anchor).getPersistState();
+        when(mAnchor.getPersistState()).thenReturn(Anchor.PersistState.PERSIST_PENDING);
+        mExecutor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
+        verify(mAnchor).getPersistState();
 
-        executor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
-        verify(anchor, times(2)).getPersistState();
+        mExecutor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
+        verify(mAnchor, times(2)).getPersistState();
 
-        Mockito.clearInvocations(anchor);
+        Mockito.clearInvocations(mAnchor);
         anchorEntity.dispose();
-        executor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
-        verify(anchor, never()).getPersistState();
+        mExecutor.simulateSleepExecutingAllTasks(AnchorEntityImpl.PERSIST_STATE_CHECK_DELAY);
+        verify(mAnchor, never()).getPersistState();
     }
 
     @Test
     public void createAnchorEntityFromPlane_returnsAnchorEntity() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(plane.createAnchor(any(), any())).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mPlane.createAnchor(any(), any())).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(mSharedAnchorToken);
 
         AnchorEntityImpl anchorEntity = createAnchorEntityFromPlane();
 
@@ -1163,16 +1164,16 @@
         assertThat(anchorEntity.getState()).isEqualTo(State.ANCHORED);
         assertThat(((FakeNode) anchorEntity.getNode()).getName())
                 .isEqualTo(AnchorEntityImpl.ANCHOR_NODE_NAME);
-        assertThat(((FakeNode) anchorEntity.getNode()).getAnchorId()).isEqualTo(sharedAnchorToken);
+        assertThat(((FakeNode) anchorEntity.getNode()).getAnchorId()).isEqualTo(mSharedAnchorToken);
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSIST_NOT_REQUESTED);
         assertThat(((FakeNode) anchorEntity.getNode()).getParent())
-                .isEqualTo(activitySpace.getNode());
+                .isEqualTo(mActivitySpace.getNode());
     }
 
     @Test
     public void createAnchorEntityFromPlane_failureToAnchor_hasErrorState() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(plane.createAnchor(any(), any())).thenReturn(null);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mPlane.createAnchor(any(), any())).thenReturn(null);
 
         AnchorEntityImpl anchorEntity = createAnchorEntityFromPlane();
         assertThat(anchorEntity).isNotNull();
@@ -1182,11 +1183,11 @@
 
     @Test
     public void createAnchorEntityFromPerceptionAnchor_nativePointerMatches() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
         FakeExportableAnchor fakeAnchor =
                 new FakeExportableAnchor(
                         NATIVE_POINTER,
-                        sharedAnchorToken,
+                        mSharedAnchorToken,
                         new Pose(),
                         TrackingState.Tracking,
                         PersistenceState.NotPersisted,
@@ -1201,12 +1202,12 @@
 
     @Test
     public void createAnchorEntityFromPerceptionAnchor_returnsAnchorEntity() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
 
         FakeExportableAnchor fakeAnchor =
                 new FakeExportableAnchor(
                         NATIVE_POINTER,
-                        sharedAnchorToken,
+                        mSharedAnchorToken,
                         new Pose(),
                         TrackingState.Tracking,
                         PersistenceState.NotPersisted,
@@ -1218,16 +1219,16 @@
         assertThat(anchorEntity.getState()).isEqualTo(State.ANCHORED);
         assertThat(((FakeNode) anchorEntity.getNode()).getName())
                 .isEqualTo(AnchorEntityImpl.ANCHOR_NODE_NAME);
-        assertThat(((FakeNode) anchorEntity.getNode()).getAnchorId()).isEqualTo(sharedAnchorToken);
+        assertThat(((FakeNode) anchorEntity.getNode()).getAnchorId()).isEqualTo(mSharedAnchorToken);
         assertThat(anchorEntity.getPersistState()).isEqualTo(PersistState.PERSIST_NOT_REQUESTED);
         assertThat(((FakeNode) anchorEntity.getNode()).getParent())
-                .isEqualTo(activitySpace.getNode());
+                .isEqualTo(mActivitySpace.getNode());
     }
 
     @Test
     public void createAnchorEntityFromPerceptionAnchor_failureToAnchor_hasErrorState()
             throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
 
         FakeExportableAnchor fakeAnchor =
                 new FakeExportableAnchor(
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/AudioTrackExtensionsWrapperImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/AudioTrackExtensionsWrapperImplTest.java
index a782e82..4ac6d31 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/AudioTrackExtensionsWrapperImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/AudioTrackExtensionsWrapperImplTest.java
@@ -43,23 +43,23 @@
 @RunWith(RobolectricTestRunner.class)
 public class AudioTrackExtensionsWrapperImplTest {
 
-    FakeXrExtensions fakeXrExtensions;
-    FakeSpatialAudioExtensions fakeSpatialAudioExtensions;
-    FakeAudioTrackExtensions fakeAudioTrackExtensions;
+    FakeXrExtensions mFakeXrExtensions;
+    FakeSpatialAudioExtensions mFakeSpatialAudioExtensions;
+    FakeAudioTrackExtensions mFakeAudioTrackExtensions;
 
-    private EntityManager entityManager;
+    private EntityManager mEntityManager;
 
-    @Mock private AudioTrack.Builder builder;
+    @Mock private AudioTrack.Builder mBuilder;
 
     @Before
     public void setUp() {
-        fakeXrExtensions = new FakeXrExtensions();
-        fakeSpatialAudioExtensions = fakeXrExtensions.fakeSpatialAudioExtensions;
-        fakeAudioTrackExtensions = new FakeAudioTrackExtensions();
+        mFakeXrExtensions = new FakeXrExtensions();
+        mFakeSpatialAudioExtensions = mFakeXrExtensions.fakeSpatialAudioExtensions;
+        mFakeAudioTrackExtensions = new FakeAudioTrackExtensions();
 
-        fakeSpatialAudioExtensions.setFakeAudioTrackExtensions(fakeAudioTrackExtensions);
+        mFakeSpatialAudioExtensions.setFakeAudioTrackExtensions(mFakeAudioTrackExtensions);
 
-        entityManager = new EntityManager();
+        mEntityManager = new EntityManager();
     }
 
     @Test
@@ -72,11 +72,11 @@
                 new JxrPlatformAdapter.PointSourceAttributes(entity);
 
         AudioTrackExtensionsWrapper wrapper =
-                new AudioTrackExtensionsWrapperImpl(fakeAudioTrackExtensions, entityManager);
-        AudioTrack.Builder actual = wrapper.setPointSourceAttributes(builder, expectedRtAttr);
+                new AudioTrackExtensionsWrapperImpl(mFakeAudioTrackExtensions, mEntityManager);
+        AudioTrack.Builder actual = wrapper.setPointSourceAttributes(mBuilder, expectedRtAttr);
 
-        assertThat(actual).isEqualTo(builder);
-        assertThat(fakeAudioTrackExtensions.getPointSourceAttributes().getNode())
+        assertThat(actual).isEqualTo(mBuilder);
+        assertThat(mFakeAudioTrackExtensions.getPointSourceAttributes().getNode())
                 .isEqualTo(fakeNode);
     }
 
@@ -88,12 +88,12 @@
                         JxrPlatformAdapter.SpatializerConstants.AMBISONICS_ORDER_THIRD_ORDER);
 
         AudioTrackExtensionsWrapper wrapper =
-                new AudioTrackExtensionsWrapperImpl(fakeAudioTrackExtensions, entityManager);
+                new AudioTrackExtensionsWrapperImpl(mFakeAudioTrackExtensions, mEntityManager);
 
-        AudioTrack.Builder actual = wrapper.setSoundFieldAttributes(builder, expectedRtAttr);
+        AudioTrack.Builder actual = wrapper.setSoundFieldAttributes(mBuilder, expectedRtAttr);
 
-        assertThat(actual).isEqualTo(builder);
-        assertThat(fakeAudioTrackExtensions.getSoundFieldAttributes().getAmbisonicsOrder())
+        assertThat(actual).isEqualTo(mBuilder);
+        assertThat(mFakeAudioTrackExtensions.getSoundFieldAttributes().getAmbisonicsOrder())
                 .isEqualTo(expectedAmbisonicOrder);
     }
 
@@ -104,15 +104,15 @@
         Node fakeNode = new FakeXrExtensions().createNode();
         AndroidXrEntity entity = mock(AndroidXrEntity.class);
         when(entity.getNode()).thenReturn(fakeNode);
-        entityManager.setEntityForNode(fakeNode, entity);
+        mEntityManager.setEntityForNode(fakeNode, entity);
 
-        fakeAudioTrackExtensions.setPointSourceAttributes(
+        mFakeAudioTrackExtensions.setPointSourceAttributes(
                 new PointSourceAttributes.Builder().setNode(fakeNode).build());
 
         JxrPlatformAdapter.PointSourceAttributes expectedRtAttr =
                 new JxrPlatformAdapter.PointSourceAttributes(entity);
         AudioTrackExtensionsWrapper wrapper =
-                new AudioTrackExtensionsWrapperImpl(fakeAudioTrackExtensions, entityManager);
+                new AudioTrackExtensionsWrapperImpl(mFakeAudioTrackExtensions, mEntityManager);
 
         JxrPlatformAdapter.PointSourceAttributes actual = wrapper.getPointSourceAttributes(track);
 
@@ -124,7 +124,7 @@
         AudioTrack track = mock(AudioTrack.class);
 
         AudioTrackExtensionsWrapper wrapper =
-                new AudioTrackExtensionsWrapperImpl(fakeAudioTrackExtensions, entityManager);
+                new AudioTrackExtensionsWrapperImpl(mFakeAudioTrackExtensions, mEntityManager);
 
         JxrPlatformAdapter.PointSourceAttributes actual = wrapper.getPointSourceAttributes(track);
 
@@ -135,7 +135,7 @@
     public void getSoundFieldAttributes_callsExtensionsGetSoundFieldAttributes() {
         AudioTrack track = mock(AudioTrack.class);
 
-        fakeAudioTrackExtensions.setSoundFieldAttributes(
+        mFakeAudioTrackExtensions.setSoundFieldAttributes(
                 new SoundFieldAttributes.Builder()
                         .setAmbisonicsOrder(SpatializerExtensions.AMBISONICS_ORDER_THIRD_ORDER)
                         .build());
@@ -144,7 +144,7 @@
                 new JxrPlatformAdapter.SoundFieldAttributes(
                         SpatializerConstants.AMBISONICS_ORDER_THIRD_ORDER);
         AudioTrackExtensionsWrapper wrapper =
-                new AudioTrackExtensionsWrapperImpl(fakeAudioTrackExtensions, entityManager);
+                new AudioTrackExtensionsWrapperImpl(mFakeAudioTrackExtensions, mEntityManager);
 
         JxrPlatformAdapter.SoundFieldAttributes actual = wrapper.getSoundFieldAttributes(track);
 
@@ -156,7 +156,7 @@
         AudioTrack track = mock(AudioTrack.class);
 
         AudioTrackExtensionsWrapper wrapper =
-                new AudioTrackExtensionsWrapperImpl(fakeAudioTrackExtensions, entityManager);
+                new AudioTrackExtensionsWrapperImpl(mFakeAudioTrackExtensions, mEntityManager);
 
         JxrPlatformAdapter.SoundFieldAttributes actual = wrapper.getSoundFieldAttributes(track);
 
@@ -169,9 +169,9 @@
 
         int expected = SpatializerConstants.SOURCE_TYPE_SOUND_FIELD;
 
-        fakeAudioTrackExtensions.setSourceType(expected);
+        mFakeAudioTrackExtensions.setSourceType(expected);
         AudioTrackExtensionsWrapper wrapper =
-                new AudioTrackExtensionsWrapperImpl(fakeAudioTrackExtensions, entityManager);
+                new AudioTrackExtensionsWrapperImpl(mFakeAudioTrackExtensions, mEntityManager);
 
         int actualSourceType = wrapper.getSpatialSourceType(track);
         assertThat(actualSourceType).isEqualTo(expected);
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/CameraViewActivityPoseImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/CameraViewActivityPoseImplTest.java
index b837469..171e604 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/CameraViewActivityPoseImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/CameraViewActivityPoseImplTest.java
@@ -45,23 +45,23 @@
 @RunWith(RobolectricTestRunner.class)
 public final class CameraViewActivityPoseImplTest {
 
-    private final AndroidXrEntity activitySpaceRoot = Mockito.mock(AndroidXrEntity.class);
-    private final FakeXrExtensions fakeExtensions = new FakeXrExtensions();
-    private final PerceptionLibrary perceptionLibrary = Mockito.mock(PerceptionLibrary.class);
-    private final Session session = Mockito.mock(Session.class);
-    private final FakeScheduledExecutorService executor = new FakeScheduledExecutorService();
-    private final ActivitySpaceImpl activitySpace =
+    private final AndroidXrEntity mActivitySpaceRoot = Mockito.mock(AndroidXrEntity.class);
+    private final FakeXrExtensions mFakeExtensions = new FakeXrExtensions();
+    private final PerceptionLibrary mPerceptionLibrary = Mockito.mock(PerceptionLibrary.class);
+    private final Session mSession = Mockito.mock(Session.class);
+    private final FakeScheduledExecutorService mExecutor = new FakeScheduledExecutorService();
+    private final ActivitySpaceImpl mActivitySpace =
             new ActivitySpaceImpl(
-                    fakeExtensions.createNode(),
-                    fakeExtensions,
+                    mFakeExtensions.createNode(),
+                    mFakeExtensions,
                     new EntityManager(),
-                    () -> fakeExtensions.fakeSpatialState,
-                    executor);
+                    () -> mFakeExtensions.fakeSpatialState,
+                    mExecutor);
 
     /** Creates a CameraViewActivityPoseImpl. */
     private CameraViewActivityPoseImpl createCameraViewActivityPose(@CameraType int cameraType) {
         return new CameraViewActivityPoseImpl(
-                cameraType, activitySpace, activitySpaceRoot, perceptionLibrary);
+                cameraType, mActivitySpace, mActivitySpaceRoot, mPerceptionLibrary);
     }
 
     @Test
@@ -82,7 +82,7 @@
         Fov fovLeft = new Fov(1, 2, 3, 4);
         Fov fovRight = new Fov(5, 6, 7, 8);
 
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
         ViewProjection viewProjectionLeft =
                 new ViewProjection(
                         RuntimeUtils.poseToPerceptionPose(new Pose()),
@@ -91,7 +91,7 @@
                 new ViewProjection(
                         RuntimeUtils.poseToPerceptionPose(new Pose()),
                         RuntimeUtils.perceptionFovFromFov(fovRight));
-        when(session.getStereoViews())
+        when(mSession.getStereoViews())
                 .thenReturn(new ViewProjections(viewProjectionLeft, viewProjectionRight));
 
         CameraViewActivityPoseImpl cameraActivityPoseLeft =
@@ -112,12 +112,12 @@
     @Test
     public void transformPoseTo_returnsCorrectPose() {
         // Set the activity space to the root of the underlying OpenXR reference space.
-        this.activitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
         Pose poseLeft = new Pose(new Vector3(1, 2, 3), new Quaternion(1, 0, 0, 0));
         Pose poseRight = new Pose(new Vector3(4, 5, 6), new Quaternion(0, 1, 0, 0));
         Fov fov = new Fov(0, 0, 0, 0);
 
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
         ViewProjection viewProjectionLeft =
                 new ViewProjection(
                         RuntimeUtils.poseToPerceptionPose(poseLeft),
@@ -126,24 +126,24 @@
                 new ViewProjection(
                         RuntimeUtils.poseToPerceptionPose(poseRight),
                         RuntimeUtils.perceptionFovFromFov(fov));
-        when(session.getStereoViews())
+        when(mSession.getStereoViews())
                 .thenReturn(new ViewProjections(viewProjectionLeft, viewProjectionRight));
 
         CameraViewActivityPoseImpl cameraActivityPoseLeft =
                 createCameraViewActivityPose(CameraViewActivityPose.CAMERA_TYPE_LEFT_EYE);
 
-        assertPose(cameraActivityPoseLeft.transformPoseTo(new Pose(), activitySpace), poseLeft);
+        assertPose(cameraActivityPoseLeft.transformPoseTo(new Pose(), mActivitySpace), poseLeft);
 
         CameraViewActivityPoseImpl cameraActivityPoseRight =
                 createCameraViewActivityPose(CameraViewActivityPose.CAMERA_TYPE_RIGHT_EYE);
 
-        assertPose(cameraActivityPoseRight.transformPoseTo(new Pose(), activitySpace), poseRight);
+        assertPose(cameraActivityPoseRight.transformPoseTo(new Pose(), mActivitySpace), poseRight);
     }
 
     @Test
     public void getActivitySpaceScale_returnsInverseOfActivitySpaceWorldScale() throws Exception {
         float activitySpaceScale = 5f;
-        this.activitySpace.setOpenXrReferenceSpacePose(Matrix4.fromScale(activitySpaceScale));
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.fromScale(activitySpaceScale));
         CameraViewActivityPoseImpl cameraActivityPoseLeft =
                 createCameraViewActivityPose(CameraViewActivityPose.CAMERA_TYPE_LEFT_EYE);
         assertVector3(
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/EntityManagerTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/EntityManagerTest.java
index 4674fe0..ba5f9cc 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/EntityManagerTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/EntityManagerTest.java
@@ -72,58 +72,58 @@
 
     private static final int VGA_WIDTH = 640;
     private static final int VGA_HEIGHT = 480;
-    private final FakeXrExtensions fakeExtensions = new FakeXrExtensions();
-    private final FakeImpressApi fakeImpressApi = new FakeImpressApi();
-    private final FakeScheduledExecutorService fakeExecutor = new FakeScheduledExecutorService();
-    private final PerceptionLibrary perceptionLibrary = mock(PerceptionLibrary.class);
-    private final Session session = mock(Session.class);
-    private final AndroidXrEntity activitySpaceRoot = mock(AndroidXrEntity.class);
-    private final FakeScheduledExecutorService executor = new FakeScheduledExecutorService();
-    private final Node panelEntityNode = fakeExtensions.createNode();
-    private final Node anchorEntityNode = fakeExtensions.createNode();
-    private final EntityManager entityManager = new EntityManager();
-    private final SplitEngineSubspaceManager splitEngineSubspaceManager =
+    private final FakeXrExtensions mFakeExtensions = new FakeXrExtensions();
+    private final FakeImpressApi mFakeImpressApi = new FakeImpressApi();
+    private final FakeScheduledExecutorService mFakeExecutor = new FakeScheduledExecutorService();
+    private final PerceptionLibrary mPerceptionLibrary = mock(PerceptionLibrary.class);
+    private final Session mSession = mock(Session.class);
+    private final AndroidXrEntity mActivitySpaceRoot = mock(AndroidXrEntity.class);
+    private final FakeScheduledExecutorService mExecutor = new FakeScheduledExecutorService();
+    private final Node mPanelEntityNode = mFakeExtensions.createNode();
+    private final Node mAnchorEntityNode = mFakeExtensions.createNode();
+    private final EntityManager mEntityManager = new EntityManager();
+    private final SplitEngineSubspaceManager mSplitEngineSubspaceManager =
             Mockito.mock(SplitEngineSubspaceManager.class);
-    private final ImpSplitEngineRenderer splitEngineRenderer =
+    private final ImpSplitEngineRenderer mSplitEngineRenderer =
             Mockito.mock(ImpSplitEngineRenderer.class);
-    private Node contentLessEntityNode;
-    private Node gltfEntityNode;
-    private Activity activity;
-    private JxrPlatformAdapterAxr runtime;
-    private ActivitySpaceImpl activitySpace;
+    private Node mContentLessEntityNode;
+    private Node mGltfEntityNode;
+    private Activity mActivity;
+    private JxrPlatformAdapterAxr mRuntime;
+    private ActivitySpaceImpl mActivitySpace;
 
     @Before
     public void setUp() {
         try (ActivityController<Activity> activityController =
                 Robolectric.buildActivity(Activity.class)) {
-            activity = activityController.create().start().get();
+            mActivity = activityController.create().start().get();
         }
-        when(perceptionLibrary.initSession(eq(activity), anyInt(), eq(fakeExecutor)))
-                .thenReturn(immediateFuture(session));
-        runtime =
+        when(mPerceptionLibrary.initSession(eq(mActivity), anyInt(), eq(mFakeExecutor)))
+                .thenReturn(immediateFuture(mSession));
+        mRuntime =
                 JxrPlatformAdapterAxr.create(
-                        activity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
-                        entityManager,
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
+                        mEntityManager,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         /* useSplitEngine= */ false);
-        Node taskNode = fakeExtensions.createNode();
-        this.activitySpace =
+        Node taskNode = mFakeExtensions.createNode();
+        mActivitySpace =
                 new ActivitySpaceImpl(
                         taskNode,
-                        fakeExtensions,
-                        entityManager,
-                        () -> fakeExtensions.fakeSpatialState,
-                        executor);
+                        mFakeExtensions,
+                        mEntityManager,
+                        () -> mFakeExtensions.fakeSpatialState,
+                        mExecutor);
         long currentTimeMillis = 1000000000L;
         SystemClock.setCurrentTimeMillis(currentTimeMillis);
 
         // By default, set the activity space to the root of the underlying OpenXR reference space.
-        this.activitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
     }
 
     @Test
@@ -137,8 +137,8 @@
         // Entity manager also contains the main panel entity and activity space, which are created
         // when
         // the runtime is created.
-        assertThat(entityManager.getAllEntities().size()).isAtLeast(5);
-        assertThat(entityManager.getAllEntities())
+        assertThat(mEntityManager.getAllEntities().size()).isAtLeast(5);
+        assertThat(mEntityManager.getAllEntities())
                 .containsAtLeast(
                         gltfEntity,
                         panelEntity,
@@ -153,14 +153,14 @@
         PanelEntity panelEntity = createPanelEntity();
         Entity contentlessEntity = createContentlessEntity();
         AnchorEntity anchorEntity = createAnchorEntity();
-        Node testNode = fakeExtensions.createNode();
+        Node testNode = mFakeExtensions.createNode();
 
-        assertThat(entityManager.getEntityForNode(gltfEntityNode)).isEqualTo(gltfEntity);
-        assertThat(entityManager.getEntityForNode(panelEntityNode)).isEqualTo(panelEntity);
-        assertThat(entityManager.getEntityForNode(contentLessEntityNode))
+        assertThat(mEntityManager.getEntityForNode(mGltfEntityNode)).isEqualTo(gltfEntity);
+        assertThat(mEntityManager.getEntityForNode(mPanelEntityNode)).isEqualTo(panelEntity);
+        assertThat(mEntityManager.getEntityForNode(mContentLessEntityNode))
                 .isEqualTo(contentlessEntity);
-        assertThat(entityManager.getEntityForNode(anchorEntityNode)).isEqualTo(anchorEntity);
-        assertThat(entityManager.getEntityForNode(testNode)).isNull();
+        assertThat(mEntityManager.getEntityForNode(mAnchorEntityNode)).isEqualTo(anchorEntity);
+        assertThat(mEntityManager.getEntityForNode(testNode)).isNull();
     }
 
     @Test
@@ -171,14 +171,14 @@
         AnchorEntity anchorEntity = createAnchorEntity();
         ActivityPanelEntity activityPanelEntity = createActivityPanelEntity();
 
-        assertThat(entityManager.getEntitiesOfType(GltfEntity.class)).containsExactly(gltfEntity);
+        assertThat(mEntityManager.getEntitiesOfType(GltfEntity.class)).containsExactly(gltfEntity);
         // MainPanel is also a PanelEntity.
-        assertThat(entityManager.getEntitiesOfType(PanelEntity.class)).contains(panelEntity);
+        assertThat(mEntityManager.getEntitiesOfType(PanelEntity.class)).contains(panelEntity);
         // Base class of all entities.
-        assertThat(entityManager.getEntitiesOfType(Entity.class)).contains(contentlessEntity);
-        assertThat(entityManager.getEntitiesOfType(AnchorEntity.class))
+        assertThat(mEntityManager.getEntitiesOfType(Entity.class)).contains(contentlessEntity);
+        assertThat(mEntityManager.getEntitiesOfType(AnchorEntity.class))
                 .containsExactly(anchorEntity);
-        assertThat(entityManager.getEntitiesOfType(ActivityPanelEntity.class))
+        assertThat(mEntityManager.getEntitiesOfType(ActivityPanelEntity.class))
                 .containsExactly(activityPanelEntity);
     }
 
@@ -190,8 +190,8 @@
         AnchorEntity anchorEntity = createAnchorEntity();
         ActivityPanelEntity activityPanelEntity = createActivityPanelEntity();
 
-        assertThat(entityManager.getAllEntities().size()).isAtLeast(5);
-        assertThat(entityManager.getAllEntities())
+        assertThat(mEntityManager.getAllEntities().size()).isAtLeast(5);
+        assertThat(mEntityManager.getAllEntities())
                 .containsAtLeast(
                         gltfEntity,
                         panelEntity,
@@ -199,10 +199,10 @@
                         anchorEntity,
                         activityPanelEntity);
 
-        entityManager.removeEntityForNode(contentLessEntityNode);
+        mEntityManager.removeEntityForNode(mContentLessEntityNode);
 
-        assertThat(entityManager.getAllEntities().size()).isAtLeast(4);
-        assertThat(entityManager.getAllEntities()).doesNotContain(contentlessEntity);
+        assertThat(mEntityManager.getAllEntities().size()).isAtLeast(4);
+        assertThat(mEntityManager.getAllEntities()).doesNotContain(contentlessEntity);
     }
 
     @Test
@@ -213,8 +213,8 @@
         AnchorEntity anchorEntity = createAnchorEntity();
         ActivityPanelEntity activityPanelEntity = createActivityPanelEntity();
 
-        assertThat(entityManager.getAllEntities().size()).isAtLeast(5);
-        assertThat(entityManager.getAllEntities())
+        assertThat(mEntityManager.getAllEntities().size()).isAtLeast(5);
+        assertThat(mEntityManager.getAllEntities())
                 .containsAtLeast(
                         gltfEntity,
                         panelEntity,
@@ -224,8 +224,8 @@
 
         contentlessEntity.dispose();
 
-        assertThat(entityManager.getAllEntities().size()).isAtLeast(4);
-        assertThat(entityManager.getAllEntities()).doesNotContain(contentlessEntity);
+        assertThat(mEntityManager.getAllEntities().size()).isAtLeast(4);
+        assertThat(mEntityManager.getAllEntities()).doesNotContain(contentlessEntity);
     }
 
     @Test
@@ -236,8 +236,8 @@
         AnchorEntity anchorEntity = createAnchorEntity();
         ActivityPanelEntity activityPanelEntity = createActivityPanelEntity();
 
-        assertThat(entityManager.getAllEntities().size()).isAtLeast(5);
-        assertThat(entityManager.getAllEntities())
+        assertThat(mEntityManager.getAllEntities().size()).isAtLeast(5);
+        assertThat(mEntityManager.getAllEntities())
                 .containsAtLeast(
                         gltfEntity,
                         panelEntity,
@@ -245,31 +245,31 @@
                         anchorEntity,
                         activityPanelEntity);
 
-        entityManager.clear();
+        mEntityManager.clear();
 
-        assertThat(entityManager.getAllEntities()).isEmpty();
+        assertThat(mEntityManager.getAllEntities()).isEmpty();
     }
 
     private GltfEntity createGltfEntity() throws Exception {
         ListenableFuture<GltfModelResource> modelFuture =
-                runtime.loadGltfByAssetName("FakeAsset.glb");
+                mRuntime.loadGltfByAssetName("FakeAsset.glb");
         assertThat(modelFuture).isNotNull();
         GltfModelResource model = modelFuture.get();
         GltfEntityImpl gltfEntity =
                 new GltfEntityImpl(
                         (GltfModelResourceImpl) model,
-                        activitySpaceRoot,
-                        fakeExtensions,
-                        entityManager,
-                        executor);
-        gltfEntityNode = gltfEntity.getNode();
-        entityManager.setEntityForNode(gltfEntityNode, gltfEntity);
+                        mActivitySpaceRoot,
+                        mFakeExtensions,
+                        mEntityManager,
+                        mExecutor);
+        mGltfEntityNode = gltfEntity.getNode();
+        mEntityManager.setEntityForNode(mGltfEntityNode, gltfEntity);
         return gltfEntity;
     }
 
     private PanelEntity createPanelEntity() {
-        Display display = activity.getSystemService(DisplayManager.class).getDisplays()[0];
-        Context displayContext = activity.createDisplayContext(display);
+        Display display = mActivity.getSystemService(DisplayManager.class).getDisplays()[0];
+        Context displayContext = mActivity.createDisplayContext(display);
         View view = new View(displayContext);
         view.setLayoutParams(new LayoutParams(VGA_WIDTH, VGA_HEIGHT));
         SurfaceControlViewHost surfaceControlViewHost =
@@ -280,48 +280,48 @@
         surfaceControlViewHost.setView(view, VGA_WIDTH, VGA_HEIGHT);
         PanelEntityImpl panelEntity =
                 new PanelEntityImpl(
-                        panelEntityNode,
-                        fakeExtensions,
-                        entityManager,
+                        mPanelEntityNode,
+                        mFakeExtensions,
+                        mEntityManager,
                         surfaceControlViewHost,
                         new PixelDimensions(VGA_WIDTH, VGA_HEIGHT),
-                        executor);
-        entityManager.setEntityForNode(panelEntityNode, panelEntity);
+                        mExecutor);
+        mEntityManager.setEntityForNode(mPanelEntityNode, panelEntity);
         return panelEntity;
     }
 
     private Entity createContentlessEntity() {
         Entity contentlessEntity =
-                runtime.createEntity(new Pose(), "testContentLess", runtime.getActivitySpace());
-        contentLessEntityNode = ((AndroidXrEntity) contentlessEntity).getNode();
-        entityManager.setEntityForNode(contentLessEntityNode, contentlessEntity);
+                mRuntime.createEntity(new Pose(), "testContentLess", mRuntime.getActivitySpace());
+        mContentLessEntityNode = ((AndroidXrEntity) contentlessEntity).getNode();
+        mEntityManager.setEntityForNode(mContentLessEntityNode, contentlessEntity);
         return contentlessEntity;
     }
 
     private AnchorEntity createAnchorEntity() {
         AnchorEntityImpl anchorEntity =
                 AnchorEntityImpl.createSemanticAnchor(
-                        anchorEntityNode,
+                        mAnchorEntityNode,
                         new Dimensions(1f, 1f, 1f),
                         PlaneType.VERTICAL,
                         PlaneSemantic.WALL,
                         null,
-                        activitySpace,
-                        activitySpaceRoot,
-                        fakeExtensions,
-                        entityManager,
-                        executor,
-                        perceptionLibrary);
-        entityManager.setEntityForNode(anchorEntityNode, anchorEntity);
+                        mActivitySpace,
+                        mActivitySpaceRoot,
+                        mFakeExtensions,
+                        mEntityManager,
+                        mExecutor,
+                        mPerceptionLibrary);
+        mEntityManager.setEntityForNode(mAnchorEntityNode, anchorEntity);
         return anchorEntity;
     }
 
     private ActivityPanelEntity createActivityPanelEntity() {
-        return runtime.createActivityPanelEntity(
+        return mRuntime.createActivityPanelEntity(
                 new Pose(),
                 new PixelDimensions(VGA_WIDTH, VGA_HEIGHT),
                 "test",
-                activity,
-                activitySpace);
+                mActivity,
+                mActivitySpace);
     }
 }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/InteractableComponentImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/InteractableComponentImplTest.java
index 2995e1a..d9a99dc 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/InteractableComponentImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/InteractableComponentImplTest.java
@@ -56,33 +56,33 @@
 
 @RunWith(RobolectricTestRunner.class)
 public class InteractableComponentImplTest {
-    private final ActivityController<Activity> activityController =
+    private final ActivityController<Activity> mActivityController =
             Robolectric.buildActivity(Activity.class);
-    private final Activity activity = activityController.create().start().get();
-    private final FakeScheduledExecutorService fakeExecutor = new FakeScheduledExecutorService();
-    private final PerceptionLibrary perceptionLibrary = mock(PerceptionLibrary.class);
-    private final FakeXrExtensions fakeExtensions = new FakeXrExtensions();
-    private final FakeImpressApi fakeImpressApi = new FakeImpressApi();
-    private JxrPlatformAdapterAxr fakeRuntime;
-    SplitEngineSubspaceManager splitEngineSubspaceManager =
+    private final Activity mActivity = mActivityController.create().start().get();
+    private final FakeScheduledExecutorService mFakeExecutor = new FakeScheduledExecutorService();
+    private final PerceptionLibrary mPerceptionLibrary = mock(PerceptionLibrary.class);
+    private final FakeXrExtensions mFakeExtensions = new FakeXrExtensions();
+    private final FakeImpressApi mFakeImpressApi = new FakeImpressApi();
+    private JxrPlatformAdapterAxr mFakeRuntime;
+    SplitEngineSubspaceManager mSplitEngineSubspaceManager =
             Mockito.mock(SplitEngineSubspaceManager.class);
-    ImpSplitEngineRenderer splitEngineRenderer = Mockito.mock(ImpSplitEngineRenderer.class);
+    ImpSplitEngineRenderer mSplitEngineRenderer = Mockito.mock(ImpSplitEngineRenderer.class);
 
     private Entity createTestEntity() {
-        when(perceptionLibrary.initSession(eq(activity), anyInt(), eq(fakeExecutor)))
+        when(mPerceptionLibrary.initSession(eq(mActivity), anyInt(), eq(mFakeExecutor)))
                 .thenReturn(immediateFuture(mock(Session.class)));
-        fakeRuntime =
+        mFakeRuntime =
                 JxrPlatformAdapterAxr.create(
-                        activity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
+                        mActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
                         new EntityManager(),
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         /* useSplitEngine= */ false);
-        return fakeRuntime.createEntity(new Pose(), "test", fakeRuntime.getActivitySpace());
+        return mFakeRuntime.createEntity(new Pose(), "test", mFakeRuntime.getActivitySpace());
     }
 
     @Test
@@ -96,15 +96,15 @@
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
 
         assertThat(node.getListener()).isNotNull();
-        assertThat(node.getExecutor()).isEqualTo(fakeExecutor);
+        assertThat(node.getExecutor()).isEqualTo(mFakeExecutor);
 
         FakeInputEvent inputEvent = new FakeInputEvent();
         inputEvent.setOrigin(new Vec3(0, 0, 0));
         inputEvent.setDirection(new Vec3(1, 1, 1));
         node.sendInputEvent(inputEvent);
-        fakeExecutor.runAll();
+        mFakeExecutor.runAll();
 
-        assertThat(((AndroidXrEntity) entity).inputEventListenerMap).isNotEmpty();
+        assertThat(((AndroidXrEntity) entity).mInputEventListenerMap).isNotEmpty();
         verify(inputEventListener).onInputEvent(any());
     }
 
@@ -119,15 +119,15 @@
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
 
         assertThat(node.getListener()).isNotNull();
-        assertThat(node.getExecutor()).isEqualTo(fakeExecutor);
+        assertThat(node.getExecutor()).isEqualTo(mFakeExecutor);
 
         FakeInputEvent inputEvent = new FakeInputEvent();
         inputEvent.setOrigin(new Vec3(0, 0, 0));
         inputEvent.setDirection(new Vec3(1, 1, 1));
         node.sendInputEvent(inputEvent);
-        fakeExecutor.runAll();
+        mFakeExecutor.runAll();
 
-        assertThat(((AndroidXrEntity) entity).inputEventListenerMap).isNotEmpty();
+        assertThat(((AndroidXrEntity) entity).mInputEventListenerMap).isNotEmpty();
         verify(inputEventListener).onInputEvent(any());
 
         entity.removeComponent(interactableComponent);
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/JxrPlatformAdapterAxrTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/JxrPlatformAdapterAxrTest.java
index 958e1a6..915af4b 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/JxrPlatformAdapterAxrTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/JxrPlatformAdapterAxrTest.java
@@ -107,8 +107,8 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.ListenableFuture;
 
+import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -129,55 +129,61 @@
     private static final int OPEN_XR_REFERENCE_SPACE_TYPE = 1;
 
     private static final int SUBSPACE_ID = 5;
-    private final FakeXrExtensions fakeExtensions = new FakeXrExtensions();
-    private final FakeImpressApi fakeImpressApi = new FakeImpressApi();
-    private final FakeNode subspaceNode = (FakeNode) fakeExtensions.createNode();
-    private final SubspaceNode expectedSubspace = new SubspaceNode(SUBSPACE_ID, subspaceNode);
-    private final FakeScheduledExecutorService fakeExecutor = new FakeScheduledExecutorService();
-    private final PerceptionLibrary perceptionLibrary = mock(PerceptionLibrary.class);
-    private final Session session = mock(Session.class);
-    private final Plane plane = mock(Plane.class);
-    private final Anchor anchor = mock(Anchor.class);
-    private final IBinder sharedAnchorToken = mock(IBinder.class);
-    SplitEngineSubspaceManager splitEngineSubspaceManager =
+    private final FakeXrExtensions mFakeExtensions = new FakeXrExtensions();
+    private final FakeImpressApi mFakeImpressApi = new FakeImpressApi();
+    private final FakeNode mSubspaceNode = (FakeNode) mFakeExtensions.createNode();
+    private final SubspaceNode mExpectedSubspace = new SubspaceNode(SUBSPACE_ID, mSubspaceNode);
+    private final FakeScheduledExecutorService mFakeExecutor = new FakeScheduledExecutorService();
+    private final PerceptionLibrary mPerceptionLibrary = mock(PerceptionLibrary.class);
+    private final Session mSession = mock(Session.class);
+    private final Plane mPlane = mock(Plane.class);
+    private final Anchor mAnchor = mock(Anchor.class);
+    private final IBinder mSharedAnchorToken = mock(IBinder.class);
+    SplitEngineSubspaceManager mSplitEngineSubspaceManager =
             Mockito.mock(SplitEngineSubspaceManager.class);
-    ImpSplitEngineRenderer splitEngineRenderer = Mockito.mock(ImpSplitEngineRenderer.class);
-    private ActivityController<Activity> activityController;
-    private Activity activity;
-    private JxrPlatformAdapter realityCoreRuntime;
+    ImpSplitEngineRenderer mSplitEngineRenderer = Mockito.mock(ImpSplitEngineRenderer.class);
+    private ActivityController<Activity> mActivityController;
+    private Activity mActivity;
+    private JxrPlatformAdapter mRealityCoreRuntime;
 
     @Before
     public void setUp() {
-        activityController = Robolectric.buildActivity(Activity.class);
-        activity = activityController.create().start().get();
-        fakeExtensions.setOpenXrWorldSpaceType(OPEN_XR_REFERENCE_SPACE_TYPE);
-        when(perceptionLibrary.initSession(activity, OPEN_XR_REFERENCE_SPACE_TYPE, fakeExecutor))
-                .thenReturn(immediateFuture(session));
+        mActivityController = Robolectric.buildActivity(Activity.class);
+        mActivity = mActivityController.create().start().get();
+        mFakeExtensions.setOpenXrWorldSpaceType(OPEN_XR_REFERENCE_SPACE_TYPE);
+        when(mPerceptionLibrary.initSession(mActivity, OPEN_XR_REFERENCE_SPACE_TYPE, mFakeExecutor))
+                .thenReturn(immediateFuture(mSession));
 
-        realityCoreRuntime =
+        mRealityCoreRuntime =
                 JxrPlatformAdapterAxr.create(
-                        activity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
+                        mActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
                         new EntityManager(),
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         /* useSplitEngine= */ false);
     }
 
+    @After
+    public void tearDown() {
+        // Dispose the runtime between test cases to clean up lingering references.
+        mRealityCoreRuntime.dispose();
+    }
+
     GltfEntity createGltfEntity() throws Exception {
         return createGltfEntity(new Pose());
     }
 
     GltfEntity createGltfEntity(Pose pose) throws Exception {
         ListenableFuture<GltfModelResource> modelFuture =
-                realityCoreRuntime.loadGltfByAssetName("FakeAsset.glb");
+                mRealityCoreRuntime.loadGltfByAssetName("FakeAsset.glb");
         assertThat(modelFuture).isNotNull();
         GltfModelResource model = modelFuture.get();
-        return realityCoreRuntime.createGltfEntity(
-                pose, model, realityCoreRuntime.getActivitySpaceRootImpl());
+        return mRealityCoreRuntime.createGltfEntity(
+                pose, model, mRealityCoreRuntime.getActivitySpaceRootImpl());
     }
 
     GltfEntity createGltfEntitySplitEngine() throws Exception {
@@ -185,37 +191,38 @@
     }
 
     GltfEntity createGltfEntitySplitEngine(Pose pose) throws Exception {
-        FakeNode rootNode = (FakeNode) fakeExtensions.createNode();
-        FakeNode taskWindowLeashNode = (FakeNode) fakeExtensions.createNode();
+        FakeNode rootNode = (FakeNode) mFakeExtensions.createNode();
+        FakeNode taskWindowLeashNode = (FakeNode) mFakeExtensions.createNode();
 
-        when(splitEngineSubspaceManager.createSubspace(anyString(), anyInt()))
-                .thenReturn(expectedSubspace);
+        when(mSplitEngineSubspaceManager.createSubspace(anyString(), anyInt()))
+                .thenReturn(mExpectedSubspace);
 
         JxrPlatformAdapterAxr realityCoreRuntimeWithSplitEngine =
                 JxrPlatformAdapterAxr.create(
-                        activity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
+                        mActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
                         new EntityManager(),
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         rootNode,
                         taskWindowLeashNode,
                         /* useSplitEngine= */ true);
 
-        realityCoreRuntimeWithSplitEngine.setSplitEngineSubspaceManager(splitEngineSubspaceManager);
+        realityCoreRuntimeWithSplitEngine.setSplitEngineSubspaceManager(
+                mSplitEngineSubspaceManager);
 
         ListenableFuture<GltfModelResource> modelFuture =
                 realityCoreRuntimeWithSplitEngine.loadGltfByAssetNameSplitEngine("FakeAsset.glb");
         assertThat(modelFuture).isNotNull();
         // This resolves the transformation of the Future from a SplitEngine token to the JXR
         // GltfModelResource.  This is a hidden detail from the API surface's perspective.
-        fakeExecutor.runAll();
+        mFakeExecutor.runAll();
         GltfModelResource model = modelFuture.get();
         return realityCoreRuntimeWithSplitEngine.createGltfEntity(
-                pose, model, realityCoreRuntime.getActivitySpaceRootImpl());
+                pose, model, mRealityCoreRuntime.getActivitySpaceRootImpl());
     }
 
     private PanelEntity createPanelEntity() {
@@ -227,18 +234,18 @@
      * the panel, and setting the activity space as parent.
      */
     private PanelEntity createPanelEntity(Pose pose) {
-        Display display = activity.getSystemService(DisplayManager.class).getDisplays()[0];
-        Context displayContext = activity.createDisplayContext(display);
+        Display display = mActivity.getSystemService(DisplayManager.class).getDisplays()[0];
+        Context displayContext = mActivity.createDisplayContext(display);
         View view = new View(displayContext);
         view.setLayoutParams(new LayoutParams(640, 480));
-        return realityCoreRuntime.createPanelEntity(
+        return mRealityCoreRuntime.createPanelEntity(
                 pose,
                 view,
                 new PixelDimensions(640, 480),
                 new Dimensions(0.5f, 0.5f, 0.5f),
                 "testPanel",
                 displayContext,
-                realityCoreRuntime.getActivitySpaceRootImpl());
+                mRealityCoreRuntime.getActivitySpaceRootImpl());
     }
 
     private Entity createContentlessEntity() {
@@ -246,54 +253,51 @@
     }
 
     private Entity createContentlessEntity(Pose pose) {
-        return realityCoreRuntime.createEntity(
-                pose, "test", realityCoreRuntime.getActivitySpaceRootImpl());
+        return mRealityCoreRuntime.createEntity(
+                pose, "test", mRealityCoreRuntime.getActivitySpaceRootImpl());
     }
 
     @Test
-    @Ignore
     public void initRuntimePerceptionFailure() {
         ListenableFuture<Session> sessionFuture =
                 immediateFailedFuture(
                         new FailedToInitializeException("Failed to initialize a session."));
-        when(perceptionLibrary.initSession(activity, OPEN_XR_REFERENCE_SPACE_TYPE, fakeExecutor))
+        when(mPerceptionLibrary.initSession(mActivity, OPEN_XR_REFERENCE_SPACE_TYPE, mFakeExecutor))
                 .thenReturn(sessionFuture);
 
-        realityCoreRuntime =
+        mRealityCoreRuntime =
                 JxrPlatformAdapterAxr.create(
-                        activity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
+                        mActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
                         new EntityManager(),
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         /* useSplitEngine= */ false);
 
         // The perception library failed to initialize a session, but the runtime should still be
         // created.
-        assertThat(realityCoreRuntime).isNotNull();
+        assertThat(mRealityCoreRuntime).isNotNull();
     }
 
     @Test
-    @Ignore
     public void requestHomeSpaceMode_callsExtensions() {
-        realityCoreRuntime.requestHomeSpaceMode();
-        assertThat(fakeExtensions.getSpaceMode()).isEqualTo(SpaceMode.HOME_SPACE);
+        mRealityCoreRuntime.requestHomeSpaceMode();
+        assertThat(mFakeExtensions.getSpaceMode()).isEqualTo(SpaceMode.HOME_SPACE);
     }
 
     @Test
-    @Ignore
     public void requestFullSpaceMode_callsExtensions() {
-        realityCoreRuntime.requestFullSpaceMode();
-        assertThat(fakeExtensions.getSpaceMode()).isEqualTo(SpaceMode.FULL_SPACE);
+        mRealityCoreRuntime.requestFullSpaceMode();
+        assertThat(mFakeExtensions.getSpaceMode()).isEqualTo(SpaceMode.FULL_SPACE);
     }
 
     @Test
     public void createLoggingEntity_returnsEntity() {
         Pose pose = new Pose();
-        LoggingEntity loggingeEntity = realityCoreRuntime.createLoggingEntity(pose);
+        LoggingEntity loggingeEntity = mRealityCoreRuntime.createLoggingEntity(pose);
         Pose updatedPose =
                 new Pose(
                         new Vector3(1f, pose.getTranslation().getY(), pose.getTranslation().getZ()),
@@ -302,11 +306,10 @@
     }
 
     @Test
-    @Ignore
     public void loggingEntitySetParent() {
         Pose pose = new Pose();
-        LoggingEntity childEntity = realityCoreRuntime.createLoggingEntity(pose);
-        LoggingEntity parentEntity = realityCoreRuntime.createLoggingEntity(pose);
+        LoggingEntity childEntity = mRealityCoreRuntime.createLoggingEntity(pose);
+        LoggingEntity parentEntity = mRealityCoreRuntime.createLoggingEntity(pose);
 
         childEntity.setParent(parentEntity);
         parentEntity.addChild(childEntity);
@@ -318,12 +321,11 @@
     }
 
     @Test
-    @Ignore
     public void loggingEntityUpdateParent() {
         Pose pose = new Pose();
-        LoggingEntity childEntity = realityCoreRuntime.createLoggingEntity(pose);
-        LoggingEntity parentEntity1 = realityCoreRuntime.createLoggingEntity(pose);
-        LoggingEntity parentEntity2 = realityCoreRuntime.createLoggingEntity(pose);
+        LoggingEntity childEntity = mRealityCoreRuntime.createLoggingEntity(pose);
+        LoggingEntity parentEntity1 = mRealityCoreRuntime.createLoggingEntity(pose);
+        LoggingEntity parentEntity2 = mRealityCoreRuntime.createLoggingEntity(pose);
 
         childEntity.setParent(parentEntity1);
         assertThat(childEntity.getParent()).isEqualTo(parentEntity1);
@@ -337,18 +339,17 @@
     }
 
     @Test
-    @Ignore
     public void onSpatialStateChanged_setsSpatialCapabilities() {
-        realityCoreRuntime =
+        mRealityCoreRuntime =
                 JxrPlatformAdapterAxr.create(
-                        activity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
+                        mActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
                         new EntityManager(),
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         /* useSplitEngine= */ false);
 
         FakeSpatialState spatialState = new FakeSpatialState();
@@ -361,9 +362,9 @@
                                         .SPATIAL_UI_CAPABLE;
                     }
                 });
-        ((JxrPlatformAdapterAxr) realityCoreRuntime).onSpatialStateChanged(spatialState);
+        ((JxrPlatformAdapterAxr) mRealityCoreRuntime).onSpatialStateChanged(spatialState);
 
-        SpatialCapabilities caps = realityCoreRuntime.getSpatialCapabilities();
+        SpatialCapabilities caps = mRealityCoreRuntime.getSpatialCapabilities();
         assertThat(caps.hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_UI)).isTrue();
         assertThat(caps.hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_3D_CONTENT)).isFalse();
         assertThat(caps.hasCapability(SpatialCapabilities.SPATIAL_CAPABILITY_PASSTHROUGH_CONTROL))
@@ -377,34 +378,32 @@
     }
 
     @Test
-    @Ignore
     public void onSpatialStateChanged_setsEnvironmentVisibility() {
-        SpatialEnvironment environment = realityCoreRuntime.getSpatialEnvironment();
+        SpatialEnvironment environment = mRealityCoreRuntime.getSpatialEnvironment();
         assertThat(environment.isSpatialEnvironmentPreferenceActive()).isFalse();
 
         FakeSpatialState state = new FakeSpatialState();
         state.setEnvironmentVisibility(
                 new FakeEnvironmentVisibilityState(EnvironmentVisibilityState.APP_VISIBLE));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         assertThat(environment.isSpatialEnvironmentPreferenceActive()).isTrue();
 
         state = new FakeSpatialState();
         state.setEnvironmentVisibility(
                 new FakeEnvironmentVisibilityState(EnvironmentVisibilityState.INVISIBLE));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         assertThat(environment.isSpatialEnvironmentPreferenceActive()).isFalse();
 
         state = new FakeSpatialState();
         state.setEnvironmentVisibility(
                 new FakeEnvironmentVisibilityState(EnvironmentVisibilityState.HOME_VISIBLE));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         assertThat(environment.isSpatialEnvironmentPreferenceActive()).isFalse();
     }
 
     @Test
-    @Ignore
     public void onSpatialStateChanged_callsEnvironmentListenerOnlyForChanges() {
-        SpatialEnvironment environment = realityCoreRuntime.getSpatialEnvironment();
+        SpatialEnvironment environment = mRealityCoreRuntime.getSpatialEnvironment();
         @SuppressWarnings(value = "unchecked")
         Consumer<Boolean> listener = (Consumer<Boolean>) mock(Consumer.class);
 
@@ -416,14 +415,14 @@
         FakeSpatialState state = new FakeSpatialState();
         state.setEnvironmentVisibility(
                 new FakeEnvironmentVisibilityState(EnvironmentVisibilityState.APP_VISIBLE));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         verify(listener).accept(true);
 
         // The second spatial state should also fire the listener since it's a different state
         state = new FakeSpatialState();
         state.setEnvironmentVisibility(
                 new FakeEnvironmentVisibilityState(EnvironmentVisibilityState.INVISIBLE));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         assertThat(environment.isSpatialEnvironmentPreferenceActive()).isFalse();
         verify(listener).accept(false);
 
@@ -432,47 +431,45 @@
         state = new FakeSpatialState();
         state.setEnvironmentVisibility(
                 new FakeEnvironmentVisibilityState(EnvironmentVisibilityState.INVISIBLE));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         assertThat(environment.isSpatialEnvironmentPreferenceActive()).isFalse();
         verify(listener, times(2))
                 .accept(any()); // Verify the listener was not called a third time.
     }
 
     @Test
-    @Ignore
     public void onSpatialStateChanged_setsPassthroughOpacity() {
-        SpatialEnvironment environment = realityCoreRuntime.getSpatialEnvironment();
+        SpatialEnvironment environment = mRealityCoreRuntime.getSpatialEnvironment();
         assertThat(environment.getCurrentPassthroughOpacity()).isZero();
 
         FakeSpatialState state = new FakeSpatialState();
         state.setPassthroughVisibility(
                 new FakePassthroughVisibilityState(PassthroughVisibilityState.APP, 0.4f));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         assertThat(environment.getCurrentPassthroughOpacity()).isEqualTo(0.4f);
 
         state = new FakeSpatialState();
         state.setPassthroughVisibility(
                 new FakePassthroughVisibilityState(PassthroughVisibilityState.HOME, 0.5f));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         assertThat(environment.getCurrentPassthroughOpacity()).isEqualTo(0.5f);
 
         state = new FakeSpatialState();
         state.setPassthroughVisibility(
                 new FakePassthroughVisibilityState(PassthroughVisibilityState.SYSTEM, 0.9f));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         assertThat(environment.getCurrentPassthroughOpacity()).isEqualTo(0.9f);
 
         state = new FakeSpatialState();
         state.setPassthroughVisibility(
                 new FakePassthroughVisibilityState(PassthroughVisibilityState.DISABLED, 0.0f));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         assertThat(environment.getCurrentPassthroughOpacity()).isZero();
     }
 
     @Test
-    @Ignore
     public void onSpatialStateChanged_callsPassthroughListenerOnlyForChanges() {
-        SpatialEnvironment environment = realityCoreRuntime.getSpatialEnvironment();
+        SpatialEnvironment environment = mRealityCoreRuntime.getSpatialEnvironment();
         @SuppressWarnings(value = "unchecked")
         Consumer<Float> listener = (Consumer<Float>) mock(Consumer.class);
 
@@ -484,14 +481,14 @@
         FakeSpatialState state = new FakeSpatialState();
         state.setPassthroughVisibility(
                 new FakePassthroughVisibilityState(PassthroughVisibilityState.APP, 1.0f));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         verify(listener).accept(1.0f);
 
         // The second spatial state should also fire the listener even if only the opacity changes
         state = new FakeSpatialState();
         state.setPassthroughVisibility(
                 new FakePassthroughVisibilityState(PassthroughVisibilityState.APP, 0.5f));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         assertThat(environment.getCurrentPassthroughOpacity()).isEqualTo(0.5f);
 
         // The third spatial state should also fire the listener even if only the visibility state
@@ -499,7 +496,7 @@
         state = new FakeSpatialState();
         state.setPassthroughVisibility(
                 new FakePassthroughVisibilityState(PassthroughVisibilityState.HOME, 0.5f));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         assertThat(environment.getCurrentPassthroughOpacity()).isEqualTo(0.5f);
         verify(listener, times(2))
                 .accept(0.5f); // Verify it was called a second time with this value.
@@ -509,28 +506,27 @@
         state = new FakeSpatialState();
         state.setPassthroughVisibility(
                 new FakePassthroughVisibilityState(PassthroughVisibilityState.HOME, 0.5f));
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         assertThat(environment.getCurrentPassthroughOpacity()).isEqualTo(0.5f);
         verify(listener, times(3))
                 .accept(any()); // Verify the listener was not called a fourth time.
     }
 
     @Test
-    @Ignore
     public void currentPassthroughOpacity_isSetDuringRuntimeCreation() {
-        fakeExtensions.fakeSpatialState.setPassthroughVisibility(
+        mFakeExtensions.fakeSpatialState.setPassthroughVisibility(
                 new FakePassthroughVisibilityState(PassthroughVisibilityState.APP, 0.5f));
 
         JxrPlatformAdapter newRealityCoreRuntime =
                 JxrPlatformAdapterAxr.create(
-                        activity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
+                        mActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
                         new EntityManager(),
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         /* useSplitEngine= */ false);
 
         SpatialEnvironment newEnvironment = newRealityCoreRuntime.getSpatialEnvironment();
@@ -538,18 +534,17 @@
     }
 
     @Test
-    @Ignore
     public void onSpatialStateChanged_firesSpatialCapabilitiesChangedListener() {
-        realityCoreRuntime =
+        mRealityCoreRuntime =
                 JxrPlatformAdapterAxr.create(
-                        activity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
+                        mActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
                         new EntityManager(),
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         /* useSplitEngine= */ false);
 
         @SuppressWarnings(value = "unchecked")
@@ -559,8 +554,8 @@
         Consumer<SpatialCapabilities> listener2 =
                 (Consumer<SpatialCapabilities>) mock(Consumer.class);
 
-        realityCoreRuntime.addSpatialCapabilitiesChangedListener(directExecutor(), listener1);
-        realityCoreRuntime.addSpatialCapabilitiesChangedListener(directExecutor(), listener2);
+        mRealityCoreRuntime.addSpatialCapabilitiesChangedListener(directExecutor(), listener1);
+        mRealityCoreRuntime.addSpatialCapabilitiesChangedListener(directExecutor(), listener2);
 
         FakeSpatialState state = new FakeSpatialState();
         state.setSpatialCapabilities(
@@ -570,7 +565,7 @@
                         return true;
                     }
                 });
-        fakeExtensions.sendSpatialState(state);
+        mFakeExtensions.sendSpatialState(state);
         verify(listener1).accept(any());
         verify(listener2).accept(any());
 
@@ -582,45 +577,43 @@
                         return false;
                     }
                 });
-        realityCoreRuntime.removeSpatialCapabilitiesChangedListener(listener1);
-        fakeExtensions.sendSpatialState(state);
+        mRealityCoreRuntime.removeSpatialCapabilitiesChangedListener(listener1);
+        mFakeExtensions.sendSpatialState(state);
         verify(listener1).accept(any()); // Verify the removed listener was called exactly once
         verify(listener2, times(2)).accept(any()); // Verify the active listener was called twice
     }
 
     @Test
-    @Ignore
     public void getHeadPoseInOpenXrUnboundedSpace_returnsNullWhenPerceptionSessionUninitialized() {
-        when(perceptionLibrary.getSession()).thenReturn(null);
-        assertThat(((JxrPlatformAdapterAxr) realityCoreRuntime).getHeadPoseInOpenXrUnboundedSpace())
+        when(mPerceptionLibrary.getSession()).thenReturn(null);
+        assertThat(
+                        ((JxrPlatformAdapterAxr) mRealityCoreRuntime)
+                                .getHeadPoseInOpenXrUnboundedSpace())
                 .isNull();
     }
 
     @Test
-    @Ignore
     public void getHeadPoseInOpenXrUnboundedSpace_returnsPose() {
-        when(session.getHeadPose())
+        when(mSession.getHeadPose())
                 .thenReturn(
                         new androidx.xr.scenecore.impl.perception.Pose(1f, 1f, 1f, 0f, 0f, 0f, 1f));
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
         assertPose(
-                ((JxrPlatformAdapterAxr) realityCoreRuntime).getHeadPoseInOpenXrUnboundedSpace(),
+                ((JxrPlatformAdapterAxr) mRealityCoreRuntime).getHeadPoseInOpenXrUnboundedSpace(),
                 new Pose(new Vector3(1f, 1f, 1f), new Quaternion(0f, 0f, 0f, 1f)));
     }
 
     @Test
-    @Ignore
     public void
             getStereoViewsInOpenXrUnboundedSpace_returnsNullWhenPerceptionSessionUninitialized() {
-        when(perceptionLibrary.getSession()).thenReturn(null);
+        when(mPerceptionLibrary.getSession()).thenReturn(null);
         assertThat(
-                        ((JxrPlatformAdapterAxr) realityCoreRuntime)
+                        ((JxrPlatformAdapterAxr) mRealityCoreRuntime)
                                 .getStereoViewsInOpenXrUnboundedSpace())
                 .isNull();
     }
 
     @Test
-    @Ignore
     public void getStereoViewsInOpenXrUnboundedSpace_returnsViewProjections() {
         ViewProjection leftViewProjection =
                 new ViewProjection(
@@ -632,39 +625,36 @@
                         new androidx.xr.scenecore.impl.perception.Pose(1f, 1f, 1f, 0f, 0f, 0f, 1f),
                         new Fov(1f, 1f, 1f, 1f));
 
-        when(session.getStereoViews())
+        when(mSession.getStereoViews())
                 .thenReturn(new ViewProjections(leftViewProjection, rightViewProjection));
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
         assertThat(
-                        ((JxrPlatformAdapterAxr) realityCoreRuntime)
+                        ((JxrPlatformAdapterAxr) mRealityCoreRuntime)
                                 .getStereoViewsInOpenXrUnboundedSpace())
                 .isEqualTo(new ViewProjections(leftViewProjection, rightViewProjection));
     }
 
     @Test
-    @Ignore
     public void loggingEntity_getActivitySpacePose_returnsIdentityPose() {
         Pose identityPose = new Pose();
-        LoggingEntity loggingEntity = realityCoreRuntime.createLoggingEntity(identityPose);
+        LoggingEntity loggingEntity = mRealityCoreRuntime.createLoggingEntity(identityPose);
         assertPose(loggingEntity.getActivitySpacePose(), identityPose);
     }
 
     @Test
-    @Ignore
     public void loggingEntity_transformPoseTo_returnsIdentityPose() {
         Pose identityPose = new Pose();
-        LoggingEntity loggingEntity = realityCoreRuntime.createLoggingEntity(identityPose);
+        LoggingEntity loggingEntity = mRealityCoreRuntime.createLoggingEntity(identityPose);
         assertPose(loggingEntity.transformPoseTo(identityPose, loggingEntity), identityPose);
     }
 
     @Test
-    @Ignore
     public void getPose_returnsSetPose() throws Exception {
         Pose pose = new Pose(new Vector3(1f, 2f, 3f), new Quaternion(1f, 2f, 3f, 4f));
         Pose identityPose = new Pose();
         PanelEntity panelEntity = createPanelEntity();
         GltfEntity gltfEntity = createGltfEntity();
-        LoggingEntity loggingEntity = realityCoreRuntime.createLoggingEntity(identityPose);
+        LoggingEntity loggingEntity = mRealityCoreRuntime.createLoggingEntity(identityPose);
         Entity contentlessEntity = createContentlessEntity();
 
         assertPose(panelEntity.getPose(), identityPose);
@@ -684,12 +674,11 @@
     }
 
     @Test
-    @Ignore
     public void getPose_returnsFactoryMethodPose() throws Exception {
         Pose pose = new Pose(new Vector3(1f, 2f, 3f), new Quaternion(1f, 2f, 3f, 4f));
         PanelEntity panelEntity = createPanelEntity(pose);
         GltfEntity gltfEntity = createGltfEntity(pose);
-        LoggingEntity loggingEntity = realityCoreRuntime.createLoggingEntity(pose);
+        LoggingEntity loggingEntity = mRealityCoreRuntime.createLoggingEntity(pose);
         Entity contentlessEntity = createContentlessEntity(pose);
 
         assertPose(panelEntity.getPose(), pose);
@@ -699,7 +688,6 @@
     }
 
     @Test
-    @Ignore
     public void getPoseInActivitySpace_withParentChainTranslation_returnsOffsetPositionFromRoot()
             throws Exception {
         // Create a simple pose with only a small translation on all axes
@@ -708,12 +696,12 @@
         // Set the activity space as the root of this entity hierarchy..
         AndroidXrEntity parentEntity =
                 (AndroidXrEntity)
-                        realityCoreRuntime.createEntity(
-                                pose, "parent", realityCoreRuntime.getActivitySpace());
+                        mRealityCoreRuntime.createEntity(
+                                pose, "parent", mRealityCoreRuntime.getActivitySpace());
         AndroidXrEntity childEntity1 =
-                (AndroidXrEntity) realityCoreRuntime.createEntity(pose, "child1", parentEntity);
+                (AndroidXrEntity) mRealityCoreRuntime.createEntity(pose, "child1", parentEntity);
         AndroidXrEntity childEntity2 =
-                (AndroidXrEntity) realityCoreRuntime.createEntity(pose, "child2", childEntity1);
+                (AndroidXrEntity) mRealityCoreRuntime.createEntity(pose, "child2", childEntity1);
 
         assertVector3(
                 parentEntity.getPoseInActivitySpace().getTranslation(), new Vector3(1f, 2f, 3f));
@@ -724,7 +712,6 @@
     }
 
     @Test
-    @Ignore
     public void getPoseInActivitySpace_withParentChainRotation_returnsOffsetRotationFromRoot()
             throws Exception {
         // Create a pose with a translation and one with 90 degree rotation around the y axis.
@@ -736,16 +723,16 @@
         // The parent has a translation and no rotation.
         AndroidXrEntity parentEntity =
                 (AndroidXrEntity)
-                        realityCoreRuntime.createEntity(
-                                translatedPose, "parent", realityCoreRuntime.getActivitySpace());
+                        mRealityCoreRuntime.createEntity(
+                                translatedPose, "parent", mRealityCoreRuntime.getActivitySpace());
 
         // Each child adds a rotation, but no translation.
         AndroidXrEntity childEntity1 =
                 (AndroidXrEntity)
-                        realityCoreRuntime.createEntity(rotatedPose, "child1", parentEntity);
+                        mRealityCoreRuntime.createEntity(rotatedPose, "child1", parentEntity);
         AndroidXrEntity childEntity2 =
                 (AndroidXrEntity)
-                        realityCoreRuntime.createEntity(rotatedPose, "child2", childEntity1);
+                        mRealityCoreRuntime.createEntity(rotatedPose, "child2", childEntity1);
 
         // There should be no translation offset from the root, only changes in rotation.
         assertPose(parentEntity.getPoseInActivitySpace(), translatedPose);
@@ -758,7 +745,6 @@
     }
 
     @Test
-    @Ignore
     public void getPoseInActivitySpace_withParentChainPoseOffsets_returnsOffsetPoseFromRoot()
             throws Exception {
         // Create a pose with a 1D translation and a 90 degree rotation around the z axis.
@@ -769,12 +755,12 @@
         // Each entity adds a translation and a rotation.
         AndroidXrEntity parentEntity =
                 (AndroidXrEntity)
-                        realityCoreRuntime.createEntity(
-                                pose, "parent", realityCoreRuntime.getActivitySpace());
+                        mRealityCoreRuntime.createEntity(
+                                pose, "parent", mRealityCoreRuntime.getActivitySpace());
         AndroidXrEntity childEntity1 =
-                (AndroidXrEntity) realityCoreRuntime.createEntity(pose, "child1", parentEntity);
+                (AndroidXrEntity) mRealityCoreRuntime.createEntity(pose, "child1", parentEntity);
         AndroidXrEntity childEntity2 =
-                (AndroidXrEntity) realityCoreRuntime.createEntity(pose, "child2", childEntity1);
+                (AndroidXrEntity) mRealityCoreRuntime.createEntity(pose, "child2", childEntity1);
 
         // Local pose of ActivitySpace's direct child must be the same as child's ActivitySpace
         // pose.
@@ -798,7 +784,6 @@
     }
 
     @Test
-    @Ignore
     public void getPoseInActivitySpace_withActivitySpaceParent_returnsScaledPose()
             throws Exception {
         Pose pose = new Pose(new Vector3(1f, 2f, 3f), new Quaternion(1f, 2f, 3f, 4f));
@@ -809,7 +794,7 @@
         PanelEntityImpl panelEntity = (PanelEntityImpl) createPanelEntity(pose);
         GltfEntityImpl gltfEntity = (GltfEntityImpl) createGltfEntity(pose);
         AndroidXrEntity contentlessEntity = (AndroidXrEntity) createContentlessEntity(pose);
-        ActivitySpace activitySpace = realityCoreRuntime.getActivitySpace();
+        ActivitySpace activitySpace = mRealityCoreRuntime.getActivitySpace();
         panelEntity.setParent(activitySpace);
         gltfEntity.setParent(activitySpace);
         contentlessEntity.setParent(activitySpace);
@@ -820,7 +805,6 @@
     }
 
     @Test
-    @Ignore
     public void getPoseInActivitySpace_withScale_returnsPose() throws Exception {
         Pose localPose = new Pose(new Vector3(1f, 2f, 1f), Quaternion.Identity);
 
@@ -829,7 +813,7 @@
         GltfEntityImpl child1 = (GltfEntityImpl) createGltfEntity(localPose);
         GltfEntityImpl child2 = (GltfEntityImpl) createGltfEntity(localPose);
         GltfEntityImpl child3 = (GltfEntityImpl) createGltfEntity(localPose);
-        ActivitySpace activitySpace = realityCoreRuntime.getActivitySpace();
+        ActivitySpace activitySpace = mRealityCoreRuntime.getActivitySpace();
         assertVector3(activitySpace.getScale(), new Vector3(1f, 1f, 1f));
 
         // Set a non-unit local scale to each child.
@@ -869,7 +853,6 @@
     }
 
     @Test
-    @Ignore
     public void getActivitySpacePose_withParentChainTranslation_returnsOffsetPositionFromRoot()
             throws Exception {
         // Create a simple pose with only a small translation on all axes
@@ -877,10 +860,10 @@
 
         // Set the ActivitySpace as the root of this entity hierarchy.
         Entity parentEntity =
-                realityCoreRuntime.createEntity(
-                        pose, "parent", realityCoreRuntime.getActivitySpaceRootImpl());
-        Entity childEntity1 = realityCoreRuntime.createEntity(pose, "child1", parentEntity);
-        Entity childEntity2 = realityCoreRuntime.createEntity(pose, "child2", childEntity1);
+                mRealityCoreRuntime.createEntity(
+                        pose, "parent", mRealityCoreRuntime.getActivitySpaceRootImpl());
+        Entity childEntity1 = mRealityCoreRuntime.createEntity(pose, "child1", parentEntity);
+        Entity childEntity2 = mRealityCoreRuntime.createEntity(pose, "child2", childEntity1);
 
         // The translations should accumulate with each child, but there should be no rotation.
         assertVector3(
@@ -893,7 +876,6 @@
     }
 
     @Test
-    @Ignore
     public void getActivitySpacePose_withParentChainRotation_returnsOffsetRotationFromRoot()
             throws Exception {
         // Create a pose with a translation and one with 90 degree rotation around the y axis.
@@ -904,10 +886,10 @@
 
         // The parent has a translation and no rotation and each child adds a rotation.
         Entity parentEntity =
-                realityCoreRuntime.createEntity(
-                        translatedPose, "parent", realityCoreRuntime.getActivitySpaceRootImpl());
-        Entity childEntity1 = realityCoreRuntime.createEntity(rotatedPose, "child1", parentEntity);
-        Entity childEntity2 = realityCoreRuntime.createEntity(rotatedPose, "child2", childEntity1);
+                mRealityCoreRuntime.createEntity(
+                        translatedPose, "parent", mRealityCoreRuntime.getActivitySpaceRootImpl());
+        Entity childEntity1 = mRealityCoreRuntime.createEntity(rotatedPose, "child1", parentEntity);
+        Entity childEntity2 = mRealityCoreRuntime.createEntity(rotatedPose, "child2", childEntity1);
 
         // There should be no translation offset from the parent, but rotations should accumulate.
         assertPose(parentEntity.getActivitySpacePose(), translatedPose);
@@ -920,7 +902,6 @@
     }
 
     @Test
-    @Ignore
     public void getActivitySpacePose_withParentChainPoseOffsets_returnsOffsetPoseFromRoot()
             throws Exception {
         // Create a pose with a 1D translation and a 90 degree rotation around the z axis.
@@ -930,10 +911,10 @@
 
         // Each entity adds a translation and a rotation.
         Entity parentEntity =
-                realityCoreRuntime.createEntity(
-                        pose, "parent", realityCoreRuntime.getActivitySpaceRootImpl());
-        Entity childEntity1 = realityCoreRuntime.createEntity(pose, "child1", parentEntity);
-        Entity childEntity2 = realityCoreRuntime.createEntity(pose, "child2", childEntity1);
+                mRealityCoreRuntime.createEntity(
+                        pose, "parent", mRealityCoreRuntime.getActivitySpaceRootImpl());
+        Entity childEntity1 = mRealityCoreRuntime.createEntity(pose, "child1", parentEntity);
+        Entity childEntity2 = mRealityCoreRuntime.createEntity(pose, "child2", childEntity1);
 
         // Local pose of ActivitySpace's direct child must be the same as child's ActivitySpace
         // pose.
@@ -957,7 +938,6 @@
     }
 
     @Test
-    @Ignore
     public void getActivitySpacePose_withDefaultParent_returnsPose() throws Exception {
         Pose pose = new Pose(new Vector3(1f, 2f, 3f), new Quaternion(1f, 2f, 3f, 4f));
 
@@ -972,7 +952,6 @@
     }
 
     @Test
-    @Ignore
     public void getPoseInActivitySpace_withScale_returnsScaledPose() throws Exception {
         Pose localPose = new Pose(new Vector3(1f, 2f, 1f), Quaternion.Identity);
 
@@ -982,10 +961,10 @@
         GltfEntityImpl child2 = (GltfEntityImpl) createGltfEntity(localPose);
         GltfEntityImpl child3 = (GltfEntityImpl) createGltfEntity(localPose);
         assertVector3(
-                realityCoreRuntime.getActivitySpaceRootImpl().getScale(), new Vector3(1f, 1f, 1f));
+                mRealityCoreRuntime.getActivitySpaceRootImpl().getScale(), new Vector3(1f, 1f, 1f));
 
         // Set a non-unit local scale to each child.
-        child1.setParent(realityCoreRuntime.getActivitySpaceRootImpl());
+        child1.setParent(mRealityCoreRuntime.getActivitySpaceRootImpl());
         child1.setScale(new Vector3(2f, 2f, 2f));
 
         child2.setParent(child1);
@@ -1009,7 +988,6 @@
     }
 
     @Test
-    @Ignore
     public void transformPoseTo_sameDestAndSourceEntity_returnsUnchangedPose() throws Exception {
         Pose pose =
                 new Pose(new Vector3(1f, 2f, 3f), new Quaternion(1f, 2f, 3f, 4f).toNormalized());
@@ -1028,7 +1006,6 @@
     }
 
     @Test
-    @Ignore
     public void transformPoseTo_withOnlyTranslationOffset_returnsTranslationDifference()
             throws Exception {
         PanelEntityImpl sourceEntity = (PanelEntityImpl) createPanelEntity();
@@ -1049,7 +1026,6 @@
     }
 
     @Test
-    @Ignore
     public void transformPoseTo_withOnlyRotationOffset_returnsRotationDifference()
             throws Exception {
         PanelEntityImpl sourceEntity = (PanelEntityImpl) createPanelEntity();
@@ -1077,7 +1053,6 @@
     }
 
     @Test
-    @Ignore
     public void transformPoseTo_withDifferentTranslationAndRotation_returnsTransformedPose() {
         // Assume the source and destination entities are in the same coordinate space.
         Vector3 sourceVector = new Vector3(1f, 2f, 3f);
@@ -1141,7 +1116,6 @@
     }
 
     @Test
-    @Ignore
     public void getAlpha_returnsSetAlpha() throws Exception {
         PanelEntity panelEntity = createPanelEntity();
         GltfEntity gltfEntity = createGltfEntity();
@@ -1159,14 +1133,13 @@
         assertThat(gltfEntity.getAlpha()).isEqualTo(0.5f);
         assertThat(contentlessEntity.getAlpha()).isEqualTo(0.5f);
         assertThat(
-                        fakeExtensions.createdNodes.stream()
+                        mFakeExtensions.createdNodes.stream()
                                 .map(FakeNode::getAlpha)
                                 .collect(Collectors.toList()))
                 .containsAtLeast(0.5f, 0.5f, 0.5f);
     }
 
     @Test
-    @Ignore
     public void getActivitySpaceAlpha_returnsTotalAncestorAlpha() throws Exception {
         PanelEntity grandparent = createPanelEntity();
         GltfEntity parent = createGltfEntity();
@@ -1186,14 +1159,13 @@
         assertThat(parent.getActivitySpaceAlpha()).isEqualTo(0.25f);
         assertThat(entity.getActivitySpaceAlpha()).isEqualTo(0.125f);
         assertThat(
-                        fakeExtensions.createdNodes.stream()
+                        mFakeExtensions.createdNodes.stream()
                                 .map(FakeNode::getAlpha)
                                 .collect(Collectors.toList()))
                 .containsAtLeast(0.5f, 0.5f, 0.5f);
     }
 
     @Test
-    @Ignore
     public void transformPoseTo_withScale_returnsPose() throws Exception {
         PanelEntityImpl sourceEntity = (PanelEntityImpl) createPanelEntity();
         GltfEntityImpl destinationEntity = (GltfEntityImpl) createGltfEntity();
@@ -1209,7 +1181,6 @@
     }
 
     @Test
-    @Ignore("Flaky test, see b/380269912")
     public void transformPoseTo_withNonUniformScalesAndTranslations_returnsPose() throws Exception {
         PanelEntityImpl sourceEntity = (PanelEntityImpl) createPanelEntity();
         GltfEntityImpl destinationEntity = (GltfEntityImpl) createGltfEntity();
@@ -1233,7 +1204,6 @@
     }
 
     @Test
-    @Ignore
     public void isHidden_returnsSetHidden() throws Exception {
         PanelEntity parentEntity = createPanelEntity();
         assertThat(parentEntity.isHidden(true)).isFalse();
@@ -1273,14 +1243,13 @@
     }
 
     @Test
-    @Ignore
     public void setHidden_modifiesReforms() throws Exception {
         PanelEntity testEntity = createPanelEntity();
         FakeNode testNode = (FakeNode) ((AndroidXrEntity) testEntity).getNode();
 
         assertThat(
                         testEntity.addComponent(
-                                realityCoreRuntime.createMovableComponent(
+                                mRealityCoreRuntime.createMovableComponent(
                                         /* systemMovable= */ true,
                                         /* scaleInZ= */ true,
                                         /* anchorPlacement= */ ImmutableSet.of(),
@@ -1294,12 +1263,11 @@
     }
 
     @Test
-    @Ignore
     public void loggingEntityAddChildren() {
         Pose pose = new Pose();
-        LoggingEntity childEntity1 = realityCoreRuntime.createLoggingEntity(pose);
-        LoggingEntity childEntity2 = realityCoreRuntime.createLoggingEntity(pose);
-        LoggingEntity parentEntity = realityCoreRuntime.createLoggingEntity(pose);
+        LoggingEntity childEntity1 = mRealityCoreRuntime.createLoggingEntity(pose);
+        LoggingEntity childEntity2 = mRealityCoreRuntime.createLoggingEntity(pose);
+        LoggingEntity parentEntity = mRealityCoreRuntime.createLoggingEntity(pose);
 
         parentEntity.addChild(childEntity1);
 
@@ -1313,9 +1281,8 @@
     }
 
     @Test
-    @Ignore
     public void getActivitySpace_returnsEntity() {
-        ActivitySpace activitySpace = realityCoreRuntime.getActivitySpace();
+        ActivitySpace activitySpace = mRealityCoreRuntime.getActivitySpace();
 
         assertThat(activitySpace).isNotNull();
         // Verify that there is an underlying extension node.
@@ -1324,9 +1291,8 @@
     }
 
     @Test
-    @Ignore
     public void getActivitySpaceRootImpl_returnsEntity() {
-        Entity activitySpaceRoot = realityCoreRuntime.getActivitySpaceRootImpl();
+        Entity activitySpaceRoot = mRealityCoreRuntime.getActivitySpaceRootImpl();
         assertThat(activitySpaceRoot).isNotNull();
 
         // Verify that there is an underlying extension node.
@@ -1335,44 +1301,40 @@
     }
 
     @Test
-    @Ignore
     public void getEnvironment_returnsEnvironment() {
-        SpatialEnvironment environment = realityCoreRuntime.getSpatialEnvironment();
+        SpatialEnvironment environment = mRealityCoreRuntime.getSpatialEnvironment();
         assertThat(environment).isNotNull();
     }
 
     @Test
-    @Ignore
     public void getHeadActivityPose_returnsNullIfNotReady() {
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.getHeadPose()).thenReturn(null);
-        HeadActivityPose headActivityPose = realityCoreRuntime.getHeadActivityPose();
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.getHeadPose()).thenReturn(null);
+        HeadActivityPose headActivityPose = mRealityCoreRuntime.getHeadActivityPose();
 
         assertThat(headActivityPose).isNull();
     }
 
     @Test
-    @Ignore
     public void getHeadActivityPose_returnsActivityPose() {
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.getHeadPose())
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.getHeadPose())
                 .thenReturn(androidx.xr.scenecore.impl.perception.Pose.identity());
-        HeadActivityPose headActivityPose = realityCoreRuntime.getHeadActivityPose();
+        HeadActivityPose headActivityPose = mRealityCoreRuntime.getHeadActivityPose();
 
         assertThat(headActivityPose).isNotNull();
     }
 
     @Test
-    @Ignore
     public void getCameraViewActivityPose_returnsNullIfNotReady() {
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.getStereoViews()).thenReturn(new ViewProjections(null, null));
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.getStereoViews()).thenReturn(new ViewProjections(null, null));
 
         CameraViewActivityPose leftCameraViewActivityPose =
-                realityCoreRuntime.getCameraViewActivityPose(
+                mRealityCoreRuntime.getCameraViewActivityPose(
                         CameraViewActivityPose.CAMERA_TYPE_LEFT_EYE);
         CameraViewActivityPose rightCameraViewActivityPose =
-                realityCoreRuntime.getCameraViewActivityPose(
+                mRealityCoreRuntime.getCameraViewActivityPose(
                         CameraViewActivityPose.CAMERA_TYPE_RIGHT_EYE);
 
         assertThat(leftCameraViewActivityPose).isNull();
@@ -1380,51 +1342,47 @@
     }
 
     @Test
-    @Ignore
     public void getLeftCameraViewActivityPose_returnsActivityPose() {
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
         ViewProjection viewProjection =
                 new ViewProjection(
                         androidx.xr.scenecore.impl.perception.Pose.identity(), new Fov(0, 0, 0, 0));
-        when(session.getStereoViews())
+        when(mSession.getStereoViews())
                 .thenReturn(new ViewProjections(viewProjection, viewProjection));
         CameraViewActivityPose cameraViewActivityPose =
-                realityCoreRuntime.getCameraViewActivityPose(
+                mRealityCoreRuntime.getCameraViewActivityPose(
                         CameraViewActivityPose.CAMERA_TYPE_LEFT_EYE);
 
         assertThat(cameraViewActivityPose).isNotNull();
     }
 
     @Test
-    @Ignore
     public void getRightCameraViewActivityPose_returnsActivityPose() {
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
         ViewProjection viewProjection =
                 new ViewProjection(
                         androidx.xr.scenecore.impl.perception.Pose.identity(), new Fov(0, 0, 0, 0));
-        when(session.getStereoViews())
+        when(mSession.getStereoViews())
                 .thenReturn(new ViewProjections(viewProjection, viewProjection));
         CameraViewActivityPose cameraViewActivityPose =
-                realityCoreRuntime.getCameraViewActivityPose(
+                mRealityCoreRuntime.getCameraViewActivityPose(
                         CameraViewActivityPose.CAMERA_TYPE_RIGHT_EYE);
 
         assertThat(cameraViewActivityPose).isNotNull();
     }
 
     @Test
-    @Ignore
     public void getUnknownCameraViewActivityPose_returnsEmptyOptional() {
         CameraViewActivityPose cameraViewActivityPose =
-                realityCoreRuntime.getCameraViewActivityPose(555);
+                mRealityCoreRuntime.getCameraViewActivityPose(555);
 
         assertThat(cameraViewActivityPose).isNull();
     }
 
     @Test
-    @Ignore
     public void loadExrImageByAssetName_returnsImage() throws Exception {
         ListenableFuture<ExrImageResource> imageFuture =
-                realityCoreRuntime.loadExrImageByAssetName("FakeAsset.exr");
+                mRealityCoreRuntime.loadExrImageByAssetName("FakeAsset.exr");
 
         assertThat(imageFuture).isNotNull();
 
@@ -1438,10 +1396,9 @@
     }
 
     @Test
-    @Ignore
     public void loadGltfByAssetName_returnsModel() throws Exception {
         ListenableFuture<GltfModelResource> modelFuture =
-                realityCoreRuntime.loadGltfByAssetName("FakeAsset.glb");
+                mRealityCoreRuntime.loadGltfByAssetName("FakeAsset.glb");
 
         assertThat(modelFuture).isNotNull();
 
@@ -1455,24 +1412,21 @@
     }
 
     @Test
-    @Ignore
     public void createGltfEntity_returnsEntity() throws Exception {
         assertThat(createGltfEntity()).isNotNull();
     }
 
     @Test
-    @Ignore
     public void createGltfEntitySplitEngine_returnsEntity() throws Exception {
         assertThat(createGltfEntitySplitEngine()).isNotNull();
     }
 
     @Test
-    @Ignore
     public void animateGltfEntitySplitEngine_gltfEntityIsAnimating() throws Exception {
         GltfEntity gltfEntitySplitEngine = createGltfEntitySplitEngine();
         gltfEntitySplitEngine.startAnimation(false, "animation_name");
-        int animatingNodes = fakeImpressApi.impressNodeAnimatingSize();
-        int loopingAnimatingNodes = fakeImpressApi.impressNodeLoopAnimatingSize();
+        int animatingNodes = mFakeImpressApi.impressNodeAnimatingSize();
+        int loopingAnimatingNodes = mFakeImpressApi.impressNodeLoopAnimatingSize();
 
         // The fakeJniApi returns a future which immediately fires, which makes it seem like the
         // animation is done immediately. This makes it look like the animation stopped right away.
@@ -1483,12 +1437,11 @@
     }
 
     @Test
-    @Ignore
     public void animateLoopGltfEntitySplitEngine_gltfEntityIsAnimatingInLoop() throws Exception {
         GltfEntity gltfEntitySplitEngine = createGltfEntitySplitEngine();
         gltfEntitySplitEngine.startAnimation(true, "animation_name");
-        int animatingNodes = fakeImpressApi.impressNodeAnimatingSize();
-        int loopingAnimatingNodes = fakeImpressApi.impressNodeLoopAnimatingSize();
+        int animatingNodes = mFakeImpressApi.impressNodeAnimatingSize();
+        int loopingAnimatingNodes = mFakeImpressApi.impressNodeLoopAnimatingSize();
 
         assertThat(gltfEntitySplitEngine.getAnimationState())
                 .isEqualTo(GltfEntity.AnimationState.PLAYING);
@@ -1497,13 +1450,12 @@
     }
 
     @Test
-    @Ignore
     public void stopAnimateGltfEntitySplitEngine_gltfEntityStopsAnimating() throws Exception {
         GltfEntity gltfEntitySplitEngine = createGltfEntitySplitEngine();
         gltfEntitySplitEngine.startAnimation(true, "animation_name");
         gltfEntitySplitEngine.stopAnimation();
-        int animatingNodes = fakeImpressApi.impressNodeAnimatingSize();
-        int loopingAnimatingNodes = fakeImpressApi.impressNodeLoopAnimatingSize();
+        int animatingNodes = mFakeImpressApi.impressNodeAnimatingSize();
+        int loopingAnimatingNodes = mFakeImpressApi.impressNodeLoopAnimatingSize();
 
         assertThat(gltfEntitySplitEngine.getAnimationState())
                 .isEqualTo(GltfEntity.AnimationState.STOPPED);
@@ -1512,7 +1464,6 @@
     }
 
     @Test
-    @Ignore
     public void gltfEntitySetParent() throws Exception {
         GltfEntity childEntity = createGltfEntity();
         GltfEntity parentEntity = createGltfEntity();
@@ -1521,7 +1472,7 @@
 
         assertThat(childEntity.getParent()).isEqualTo(parentEntity);
         assertThat(parentEntity.getParent())
-                .isEqualTo(realityCoreRuntime.getActivitySpaceRootImpl());
+                .isEqualTo(mRealityCoreRuntime.getActivitySpaceRootImpl());
         assertThat(childEntity.getChildren()).isEmpty();
         assertThat(parentEntity.getChildren()).containsExactly(childEntity);
 
@@ -1531,7 +1482,6 @@
     }
 
     @Test
-    @Ignore
     public void gltfEntityUpdateParent() throws Exception {
         GltfEntity childEntity = createGltfEntity();
         GltfEntity parentEntity1 = createGltfEntity();
@@ -1553,7 +1503,6 @@
     }
 
     @Test
-    @Ignore
     public void gltfEntityAddChildren() throws Exception {
         GltfEntity childEntity1 = createGltfEntity();
         GltfEntity childEntity2 = createGltfEntity();
@@ -1576,22 +1525,19 @@
     }
 
     @Test
-    @Ignore
     public void createPanelEntity_returnsEntity() throws Exception {
         assertThat(createPanelEntity()).isNotNull();
     }
 
     @Test
-    @Ignore
     public void allPanelEnities_haveActivitySpaceRootImplAsParentByDefault() throws Exception {
         PanelEntity panelEntity = createPanelEntity();
 
         assertThat(panelEntity.getParent())
-                .isEqualTo(realityCoreRuntime.getActivitySpaceRootImpl());
+                .isEqualTo(mRealityCoreRuntime.getActivitySpaceRootImpl());
     }
 
     @Test
-    @Ignore
     public void panelEntitySetParent_setsParent() throws Exception {
         PanelEntity childEntity = createPanelEntity();
         PanelEntity parentEntity = createPanelEntity();
@@ -1608,7 +1554,6 @@
     }
 
     @Test
-    @Ignore
     public void panelEntityUpdateParent_updatesParent() throws Exception {
         PanelEntity childEntity = createPanelEntity();
         PanelEntity parentEntity1 = createPanelEntity();
@@ -1630,7 +1575,6 @@
     }
 
     @Test
-    @Ignore
     public void panelEntityAddChildren_addsChildren() throws Exception {
         PanelEntity childEntity1 = createPanelEntity();
         PanelEntity childEntity2 = createPanelEntity();
@@ -1653,14 +1597,13 @@
     }
 
     @Test
-    @Ignore
     public void createAnchorEntity_returnsAndInitsAnchor() throws Exception {
         Dimensions anchorDimensions = new Dimensions(2f, 5f, 0f);
         androidx.xr.scenecore.impl.perception.Pose perceptionPose =
                 androidx.xr.scenecore.impl.perception.Pose.identity();
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
-        when(plane.getData(any()))
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.getAllPlanes()).thenReturn(ImmutableList.of(mPlane));
+        when(mPlane.getData(any()))
                 .thenReturn(
                         new Plane.PlaneData(
                                 perceptionPose,
@@ -1668,11 +1611,11 @@
                                 5.0f,
                                 Plane.Type.VERTICAL.intValue,
                                 Plane.Label.WALL.intValue));
-        when(plane.createAnchor(eq(perceptionPose), any())).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
+        when(mPlane.createAnchor(eq(perceptionPose), any())).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(mSharedAnchorToken);
 
         AnchorEntity anchorEntity =
-                realityCoreRuntime.createAnchorEntity(
+                mRealityCoreRuntime.createAnchorEntity(
                         anchorDimensions, PlaneType.VERTICAL, PlaneSemantic.WALL, Duration.ZERO);
 
         assertThat(anchorEntity).isNotNull();
@@ -1680,22 +1623,19 @@
     }
 
     @Test
-    @Ignore
     public void getMainPanelEntity_returnsPanelEntity() throws Exception {
-        assertThat(realityCoreRuntime.getMainPanelEntity()).isNotNull();
+        assertThat(mRealityCoreRuntime.getMainPanelEntity()).isNotNull();
     }
 
     @Test
-    @Ignore
     public void getMainPanelEntity_usesWindowLeashNode() throws Exception {
-        PanelEntity mainPanel = realityCoreRuntime.getMainPanelEntity();
+        PanelEntity mainPanel = mRealityCoreRuntime.getMainPanelEntity();
 
         assertThat(((MainPanelEntityImpl) mainPanel).getNode())
-                .isEqualTo(fakeExtensions.getFakeNodeForMainWindow());
+                .isEqualTo(mFakeExtensions.getFakeNodeForMainWindow());
     }
 
     @Test
-    @Ignore
     public void addInputEventConsumerToEntity_setsUpNodeListener() {
         InputEventListener mockConsumer = mock(InputEventListener.class);
         PanelEntity panelEntity = createPanelEntity();
@@ -1704,20 +1644,19 @@
         FakeNode node = (FakeNode) ((PanelEntityImpl) panelEntity).getNode();
 
         assertThat(node.getListener()).isNotNull();
-        assertThat(node.getExecutor()).isEqualTo(fakeExecutor);
+        assertThat(node.getExecutor()).isEqualTo(mFakeExecutor);
 
         FakeInputEvent inputEvent = new FakeInputEvent();
         inputEvent.setOrigin(new Vec3(0, 0, 0));
         inputEvent.setDirection(new Vec3(1, 1, 1));
 
         node.sendInputEvent(inputEvent);
-        fakeExecutor.runAll();
+        mFakeExecutor.runAll();
 
         verify(mockConsumer).onInputEvent(any());
     }
 
     @Test
-    @Ignore
     public void inputEvent_hasHitInfo() {
         InputEventListener mockConsumer = mock(InputEventListener.class);
         PanelEntity panelEntity = createPanelEntity();
@@ -1734,7 +1673,7 @@
         xrInputEvent.setFakeHitInfo(hitInfo);
 
         node.sendInputEvent(xrInputEvent);
-        fakeExecutor.runAll();
+        mFakeExecutor.runAll();
 
         ArgumentCaptor<InputEvent> inputEventCaptor = ArgumentCaptor.forClass(InputEvent.class);
         verify(mockConsumer).onInputEvent(inputEventCaptor.capture());
@@ -1745,7 +1684,6 @@
     }
 
     @Test
-    @Ignore
     public void passingNullExecutorWhenAddingConsumer_usesInternalExecutor() {
         InputEventListener mockConsumer = mock(InputEventListener.class);
         PanelEntity panelEntity = createPanelEntity();
@@ -1757,7 +1695,6 @@
     }
 
     @Test
-    @Ignore
     public void addMultipleInputEventConsumerToEntity_setsUpInputCallbacksForAll() {
         InputEventListener mockConsumer1 = mock(InputEventListener.class);
         InputEventListener mockConsumer2 = mock(InputEventListener.class);
@@ -1771,14 +1708,13 @@
         inputEvent.setDirection(new Vec3(1, 1, 1));
 
         node.sendInputEvent(inputEvent);
-        fakeExecutor.runAll();
+        mFakeExecutor.runAll();
 
         verify(mockConsumer1).onInputEvent(any());
         verify(mockConsumer2).onInputEvent(any());
     }
 
     @Test
-    @Ignore
     public void addMultipleInputEventConsumersToEntity_setsUpInputCallbacksOnGivenExecutors() {
         InputEventListener mockConsumer1 = mock(InputEventListener.class);
         InputEventListener mockConsumer2 = mock(InputEventListener.class);
@@ -1793,7 +1729,7 @@
         inputEvent.setDirection(new Vec3(1, 1, 1));
 
         node.sendInputEvent(inputEvent);
-        fakeExecutor.runAll();
+        mFakeExecutor.runAll();
 
         assertThat(executor1.hasNext()).isTrue();
         assertThat(executor2.hasNext()).isTrue();
@@ -1806,7 +1742,6 @@
     }
 
     @Test
-    @Ignore
     public void removeInputEventConsumerToEntity_removesFromCallbacks() {
         InputEventListener mockConsumer1 = mock(InputEventListener.class);
         InputEventListener mockConsumer2 = mock(InputEventListener.class);
@@ -1820,19 +1755,18 @@
         inputEvent.setDirection(new Vec3(1, 1, 1));
 
         node.sendInputEvent(inputEvent);
-        fakeExecutor.runAll();
+        mFakeExecutor.runAll();
 
         panelEntity.removeInputEventListener(mockConsumer1);
 
         node.sendInputEvent(inputEvent);
-        fakeExecutor.runAll();
+        mFakeExecutor.runAll();
 
         verify(mockConsumer2, times(2)).onInputEvent(any());
         verify(mockConsumer1).onInputEvent(any());
     }
 
     @Test
-    @Ignore
     public void removeAllInputEventConsumers_stopsInputListening() {
         InputEventListener mockConsumer1 = mock(InputEventListener.class);
         InputEventListener mockConsumer2 = mock(InputEventListener.class);
@@ -1846,7 +1780,7 @@
         inputEvent.setDirection(new Vec3(1, 1, 1));
 
         node.sendInputEvent(inputEvent);
-        fakeExecutor.runAll();
+        mFakeExecutor.runAll();
 
         verify(mockConsumer1).onInputEvent(any());
         verify(mockConsumer2).onInputEvent(any());
@@ -1854,13 +1788,12 @@
         panelEntity.removeInputEventListener(mockConsumer1);
         panelEntity.removeInputEventListener(mockConsumer2);
 
-        assertThat(((PanelEntityImpl) panelEntity).inputEventListenerMap).isEmpty();
+        assertThat(((PanelEntityImpl) panelEntity).mInputEventListenerMap).isEmpty();
         assertThat(node.getListener()).isNull();
         assertThat(node.getExecutor()).isNull();
     }
 
     @Test
-    @Ignore
     public void dispose_stopsInputListening() {
         InputEventListener mockConsumer1 = mock(InputEventListener.class);
         InputEventListener mockConsumer2 = mock(InputEventListener.class);
@@ -1874,33 +1807,30 @@
         inputEvent.setDirection(new Vec3(1, 1, 1));
 
         node.sendInputEvent(inputEvent);
-        fakeExecutor.runAll();
+        mFakeExecutor.runAll();
 
         verify(mockConsumer1).onInputEvent(any());
         verify(mockConsumer2).onInputEvent(any());
 
         panelEntity.dispose();
 
-        assertThat(((PanelEntityImpl) panelEntity).inputEventListenerMap).isEmpty();
+        assertThat(((PanelEntityImpl) panelEntity).mInputEventListenerMap).isEmpty();
         assertThat(node.getListener()).isNull();
         assertThat(node.getExecutor()).isNull();
     }
 
     @Test
-    @Ignore
     public void createContentlessEntity_returnsEntity() throws Exception {
         assertThat(createContentlessEntity()).isNotNull();
     }
 
     @Test
-    @Ignore
     public void contentlessEntity_hasActivitySpaceRootImplAsParentByDefault() throws Exception {
         Entity entity = createContentlessEntity();
-        assertThat(entity.getParent()).isEqualTo(realityCoreRuntime.getActivitySpaceRootImpl());
+        assertThat(entity.getParent()).isEqualTo(mRealityCoreRuntime.getActivitySpaceRootImpl());
     }
 
     @Test
-    @Ignore
     public void contentlessEntityAddChildren_addsChildren() throws Exception {
         Entity childEntity1 = createContentlessEntity();
         Entity childEntity2 = createContentlessEntity();
@@ -1923,11 +1853,10 @@
     }
 
     @Test
-    @Ignore
     public void addComponent_callsOnAttach() throws Exception {
         PanelEntity panelEntity = createPanelEntity();
         GltfEntity gltfEntity = createGltfEntity();
-        LoggingEntity loggingEntity = realityCoreRuntime.createLoggingEntity(new Pose());
+        LoggingEntity loggingEntity = mRealityCoreRuntime.createLoggingEntity(new Pose());
         Component component = mock(Component.class);
         when(component.onAttach(any())).thenReturn(true);
 
@@ -1942,11 +1871,10 @@
     }
 
     @Test
-    @Ignore
     public void addComponent_failsIfOnAttachFails() throws Exception {
         PanelEntity panelEntity = createPanelEntity();
         GltfEntity gltfEntity = createGltfEntity();
-        LoggingEntity loggingEntity = realityCoreRuntime.createLoggingEntity(new Pose());
+        LoggingEntity loggingEntity = mRealityCoreRuntime.createLoggingEntity(new Pose());
         Component component = mock(Component.class);
         when(component.onAttach(any())).thenReturn(false);
 
@@ -1961,11 +1889,10 @@
     }
 
     @Test
-    @Ignore
     public void removeComponent_callsOnDetach() throws Exception {
         PanelEntity panelEntity = createPanelEntity();
         GltfEntity gltfEntity = createGltfEntity();
-        LoggingEntity loggingEntity = realityCoreRuntime.createLoggingEntity(new Pose());
+        LoggingEntity loggingEntity = mRealityCoreRuntime.createLoggingEntity(new Pose());
         Component component = mock(Component.class);
         when(component.onAttach(any())).thenReturn(true);
 
@@ -1989,11 +1916,10 @@
     }
 
     @Test
-    @Ignore
     public void addingSameComponentTypeAgain_addsComponent() throws Exception {
         PanelEntity panelEntity = createPanelEntity();
         GltfEntity gltfEntity = createGltfEntity();
-        LoggingEntity loggingEntity = realityCoreRuntime.createLoggingEntity(new Pose());
+        LoggingEntity loggingEntity = mRealityCoreRuntime.createLoggingEntity(new Pose());
         Component component1 = mock(Component.class);
         Component component2 = mock(Component.class);
         when(component1.onAttach(any())).thenReturn(true);
@@ -2016,11 +1942,10 @@
     }
 
     @Test
-    @Ignore
     public void addingDifferentComponentType_addComponentSucceeds() throws Exception {
         PanelEntity panelEntity = createPanelEntity();
         GltfEntity gltfEntity = createGltfEntity();
-        LoggingEntity loggingEntity = realityCoreRuntime.createLoggingEntity(new Pose());
+        LoggingEntity loggingEntity = mRealityCoreRuntime.createLoggingEntity(new Pose());
         Component component1 = mock(Component.class);
         Component component2 = mock(FakeComponent.class);
         when(component1.onAttach(any())).thenReturn(true);
@@ -2043,11 +1968,10 @@
     }
 
     @Test
-    @Ignore
     public void removeAll_callsOnDetachOnAll() throws Exception {
         PanelEntity panelEntity = createPanelEntity();
         GltfEntity gltfEntity = createGltfEntity();
-        LoggingEntity loggingEntity = realityCoreRuntime.createLoggingEntity(new Pose());
+        LoggingEntity loggingEntity = mRealityCoreRuntime.createLoggingEntity(new Pose());
         Component component1 = mock(Component.class);
         Component component2 = mock(FakeComponent.class);
         when(component1.onAttach(any())).thenReturn(true);
@@ -2082,11 +2006,10 @@
     }
 
     @Test
-    @Ignore
     public void addSameComponentTwice_callsOnAttachTwice() throws Exception {
         PanelEntity panelEntity = createPanelEntity();
         GltfEntity gltfEntity = createGltfEntity();
-        LoggingEntity loggingEntity = realityCoreRuntime.createLoggingEntity(new Pose());
+        LoggingEntity loggingEntity = mRealityCoreRuntime.createLoggingEntity(new Pose());
         Component component = mock(Component.class);
         when(component.onAttach(any())).thenReturn(true);
 
@@ -2104,11 +2027,10 @@
     }
 
     @Test
-    @Ignore
     public void removeSameComponentTwice_callsOnDetachOnce() throws Exception {
         PanelEntity panelEntity = createPanelEntity();
         GltfEntity gltfEntity = createGltfEntity();
-        LoggingEntity loggingEntity = realityCoreRuntime.createLoggingEntity(new Pose());
+        LoggingEntity loggingEntity = mRealityCoreRuntime.createLoggingEntity(new Pose());
         Component component = mock(Component.class);
         when(component.onAttach(any())).thenReturn(true);
 
@@ -2135,125 +2057,112 @@
     }
 
     @Test
-    @Ignore
     public void createInteractableComponent_returnsComponent() {
         InputEventListener mockConsumer = mock(InputEventListener.class);
         InteractableComponent interactableComponent =
-                realityCoreRuntime.createInteractableComponent(directExecutor(), mockConsumer);
+                mRealityCoreRuntime.createInteractableComponent(directExecutor(), mockConsumer);
         assertThat(interactableComponent).isNotNull();
     }
 
     @Test
-    @Ignore
     public void createPersistedAnchorEntity_returnsEntityInNominalCase() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.createAnchorFromUuid(any())).thenReturn(anchor);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.createAnchorFromUuid(any())).thenReturn(mAnchor);
         assertThat(
-                        realityCoreRuntime.createPersistedAnchorEntity(
+                        mRealityCoreRuntime.createPersistedAnchorEntity(
                                 UUID.randomUUID(), /* searchTimeout= */ Duration.ofSeconds(1)))
                 .isNotNull();
     }
 
     @Test
-    @Ignore
     public void createPersistedAnchorEntity_returnsEntityForNullSession() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(null);
+        when(mPerceptionLibrary.getSession()).thenReturn(null);
         assertThat(
-                        realityCoreRuntime.createPersistedAnchorEntity(
+                        mRealityCoreRuntime.createPersistedAnchorEntity(
                                 UUID.randomUUID(), /* searchTimeout= */ Duration.ofSeconds(1)))
                 .isNotNull();
     }
 
     @Test
-    @Ignore
     public void createPersistedAnchorEntity_returnsEntityForNullAnchor() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.createAnchorFromUuid(any())).thenReturn(null);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.createAnchorFromUuid(any())).thenReturn(null);
         assertThat(
-                        realityCoreRuntime.createPersistedAnchorEntity(
+                        mRealityCoreRuntime.createPersistedAnchorEntity(
                                 UUID.randomUUID(), /* searchTimeout= */ Duration.ofSeconds(1)))
                 .isNotNull();
     }
 
     @Test
-    @Ignore
     public void createPersistedAnchorEntity_returnsEntityForNullAnchorToken() throws Exception {
-        when(perceptionLibrary.getSession()).thenReturn(session);
-        when(session.createAnchorFromUuid(any())).thenReturn(anchor);
-        when(anchor.getAnchorToken()).thenReturn(null);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
+        when(mSession.createAnchorFromUuid(any())).thenReturn(mAnchor);
+        when(mAnchor.getAnchorToken()).thenReturn(null);
         UUID uuid = UUID.randomUUID();
         assertThat(
-                        realityCoreRuntime.createPersistedAnchorEntity(
+                        mRealityCoreRuntime.createPersistedAnchorEntity(
                                 uuid, /* searchTimeout= */ Duration.ofSeconds(1)))
                 .isNotNull();
-        verify(perceptionLibrary, times(3)).getSession();
-        verify(session).createAnchorFromUuid(uuid);
-        verify(anchor).getAnchorToken();
+        verify(mPerceptionLibrary, times(3)).getSession();
+        verify(mSession).createAnchorFromUuid(uuid);
+        verify(mAnchor).getAnchorToken();
     }
 
     @Test
-    @Ignore
     public void unpersistAnchor_failsWhenSessionIsNotInitialized() {
-        when(perceptionLibrary.getSession()).thenReturn(null);
-        assertThat(realityCoreRuntime.unpersistAnchor(UUID.randomUUID())).isFalse();
+        when(mPerceptionLibrary.getSession()).thenReturn(null);
+        assertThat(mRealityCoreRuntime.unpersistAnchor(UUID.randomUUID())).isFalse();
     }
 
     @Test
-    @Ignore
     public void unpersistAnchor_sessionIsInitialized_operationSucceeds() {
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
         UUID uuid = UUID.randomUUID();
-        when(session.unpersistAnchor(uuid)).thenReturn(true);
-        assertThat(realityCoreRuntime.unpersistAnchor(uuid)).isTrue();
+        when(mSession.unpersistAnchor(uuid)).thenReturn(true);
+        assertThat(mRealityCoreRuntime.unpersistAnchor(uuid)).isTrue();
     }
 
     @Test
-    @Ignore
     public void unpersistAnchor_sessionIsInitialized_operationFails() {
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
         UUID uuid = UUID.randomUUID();
-        when(session.unpersistAnchor(uuid)).thenReturn(false);
-        assertThat(realityCoreRuntime.unpersistAnchor(uuid)).isFalse();
+        when(mSession.unpersistAnchor(uuid)).thenReturn(false);
+        assertThat(mRealityCoreRuntime.unpersistAnchor(uuid)).isFalse();
     }
 
     @Test
-    @Ignore
     public void createMovableComponent_returnsComponent() {
         MovableComponent movableComponent =
-                realityCoreRuntime.createMovableComponent(
+                mRealityCoreRuntime.createMovableComponent(
                         true, true, new HashSet<AnchorPlacement>(), true);
         assertThat(movableComponent).isNotNull();
     }
 
     @Test
-    @Ignore
     public void createAnchorPlacement_returnsAnchorPlacement() {
         AnchorPlacement anchorPlacement =
-                realityCoreRuntime.createAnchorPlacementForPlanes(
+                mRealityCoreRuntime.createAnchorPlacementForPlanes(
                         ImmutableSet.of(PlaneType.ANY), ImmutableSet.of(PlaneSemantic.ANY));
         assertThat(anchorPlacement).isNotNull();
     }
 
     @Test
-    @Ignore
     public void createResizableComponent_returnsComponent() {
         ResizableComponent resizableComponent =
-                realityCoreRuntime.createResizableComponent(
+                mRealityCoreRuntime.createResizableComponent(
                         new Dimensions(0f, 0f, 0f), new Dimensions(5f, 5f, 5f));
         assertThat(resizableComponent).isNotNull();
     }
 
     @Test
-    @Ignore
     public void createPointerCaptureComponent_returnsComponent() {
         PointerCaptureComponent pointerCaptureComponent =
-                realityCoreRuntime.createPointerCaptureComponent(
+                mRealityCoreRuntime.createPointerCaptureComponent(
                         null, (inputEvent) -> {}, (state) -> {});
         assertThat(pointerCaptureComponent).isNotNull();
     }
 
     @Test
-    @Ignore
     public void dispose_clearsReformOptions() {
         AndroidXrEntity entity = (AndroidXrEntity) createContentlessEntity();
         FakeNode node = (FakeNode) entity.getNode();
@@ -2267,10 +2176,9 @@
     }
 
     @Test
-    @Ignore
     public void dispose_clearsParents() {
         AndroidXrEntity entity = (AndroidXrEntity) createContentlessEntity();
-        entity.setParent(realityCoreRuntime.getActivitySpaceRootImpl());
+        entity.setParent(mRealityCoreRuntime.getActivitySpaceRootImpl());
         assertThat(entity.getParent()).isNotNull();
 
         entity.dispose();
@@ -2278,30 +2186,26 @@
     }
 
     @Test
-    @Ignore
     public void setFullSpaceMode_callsExtensions() {
         Bundle bundle = Bundle.EMPTY;
-        bundle = realityCoreRuntime.setFullSpaceMode(bundle);
+        bundle = mRealityCoreRuntime.setFullSpaceMode(bundle);
         assertThat(bundle).isNotNull();
     }
 
     @Test
-    @Ignore
     public void setFullSpaceModeWithEnvironmentInherited_callsExtensions() {
         Bundle bundle = Bundle.EMPTY;
-        bundle = realityCoreRuntime.setFullSpaceModeWithEnvironmentInherited(bundle);
+        bundle = mRealityCoreRuntime.setFullSpaceModeWithEnvironmentInherited(bundle);
         assertThat(bundle).isNotNull();
     }
 
     @Test
-    @Ignore
     public void setPreferredAspectRatio_callsExtensions() {
-        realityCoreRuntime.setPreferredAspectRatio(activity, 1.23f);
-        assertThat(fakeExtensions.getPreferredAspectRatio()).isEqualTo(1.23f);
+        mRealityCoreRuntime.setPreferredAspectRatio(mActivity, 1.23f);
+        assertThat(mFakeExtensions.getPreferredAspectRatio()).isEqualTo(1.23f);
     }
 
     @Test
-    @Ignore
     public void createStereoSurface_returnsStereoSurface() {
         // Not a great test, since it returns the (non-SplitEngine) StereoSurfaceEntityImpl
         // and that throws this from its Ctor.
@@ -2309,46 +2213,43 @@
         assertThrows(
                 UnsupportedOperationException.class,
                 () ->
-                        realityCoreRuntime.createStereoSurfaceEntity(
+                        mRealityCoreRuntime.createStereoSurfaceEntity(
                                 StereoSurfaceEntity.StereoMode.SIDE_BY_SIDE,
                                 new Dimensions(1.0f, 1.0f, 1.0f),
                                 new Pose(),
-                                realityCoreRuntime.getActivitySpaceRootImpl()));
+                                mRealityCoreRuntime.getActivitySpaceRootImpl()));
     }
 
     @Test
-    @Ignore
     public void getSurfaceFromStereoSurface_returnsSurface() {
         assertThrows(
                 IllegalArgumentException.class,
-                () -> fakeImpressApi.getSurfaceFromStereoSurface(1));
+                () -> mFakeImpressApi.getSurfaceFromStereoSurface(1));
     }
 
     @Test
-    @Ignore
     public void setStereoModeForStereoSurface_callsExtensions() {
         assertThrows(
                 IllegalArgumentException.class,
                 () ->
-                        fakeImpressApi.setStereoModeForStereoSurface(
+                        mFakeImpressApi.setStereoModeForStereoSurface(
                                 1, StereoSurfaceEntity.StereoMode.SIDE_BY_SIDE));
     }
 
     @Test
-    @Ignore
     public void injectRootNodeAndTaskWindowLeashNode_runtimeImplUsesThoseNodes() {
-        FakeNode rootNode = (FakeNode) fakeExtensions.createNode();
-        FakeNode taskWindowLeashNode = (FakeNode) fakeExtensions.createNode();
+        FakeNode rootNode = (FakeNode) mFakeExtensions.createNode();
+        FakeNode taskWindowLeashNode = (FakeNode) mFakeExtensions.createNode();
         JxrPlatformAdapterAxr runtime =
                 JxrPlatformAdapterAxr.create(
-                        activity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
+                        mActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
                         new EntityManager(),
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         rootNode,
                         taskWindowLeashNode,
                         /* useSplitEngine= */ false);
@@ -2359,18 +2260,17 @@
     }
 
     @Test
-    @Ignore
     public void dispose_clearsResources() {
         AndroidXrEntity entity = (AndroidXrEntity) createContentlessEntity();
         FakeNode node = (FakeNode) entity.getNode();
         assertThat(node).isNotNull();
         assertThat(node.getParent()).isNotNull();
 
-        realityCoreRuntime.dispose();
+        mRealityCoreRuntime.dispose();
         assertThat(node.getParent()).isNull();
-        assertThat(fakeExtensions.getSpatialStateCallback()).isNull();
-        assertThat(fakeExtensions.getFakeNodeForMainWindow()).isNull();
-        assertThat(fakeExtensions.getFakeTaskNode()).isNull();
+        assertThat(mFakeExtensions.getSpatialStateCallback()).isNull();
+        assertThat(mFakeExtensions.getFakeNodeForMainWindow()).isNull();
+        assertThat(mFakeExtensions.getFakeTaskNode()).isNull();
     }
 
     interface FakeComponent extends Component {}
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/MainPanelEntityImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/MainPanelEntityImplTest.java
index b643154..2b75771 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/MainPanelEntityImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/MainPanelEntityImplTest.java
@@ -46,50 +46,50 @@
 
 @RunWith(RobolectricTestRunner.class)
 public class MainPanelEntityImplTest {
-    private final FakeXrExtensions fakeExtensions = new FakeXrExtensions();
-    private final FakeImpressApi fakeImpressApi = new FakeImpressApi();
-    private final ActivityController<Activity> activityController =
+    private final FakeXrExtensions mFakeExtensions = new FakeXrExtensions();
+    private final FakeImpressApi mFakeImpressApi = new FakeImpressApi();
+    private final ActivityController<Activity> mActivityController =
             Robolectric.buildActivity(Activity.class);
-    private final Activity hostActivity = activityController.create().start().get();
-    private final FakeScheduledExecutorService fakeExecutor = new FakeScheduledExecutorService();
-    private final PerceptionLibrary perceptionLibrary = Mockito.mock(PerceptionLibrary.class);
-    SplitEngineSubspaceManager splitEngineSubspaceManager =
+    private final Activity mHostActivity = mActivityController.create().start().get();
+    private final FakeScheduledExecutorService mFakeExecutor = new FakeScheduledExecutorService();
+    private final PerceptionLibrary mPerceptionLibrary = Mockito.mock(PerceptionLibrary.class);
+    SplitEngineSubspaceManager mSplitEngineSubspaceManager =
             Mockito.mock(SplitEngineSubspaceManager.class);
-    ImpSplitEngineRenderer splitEngineRenderer = Mockito.mock(ImpSplitEngineRenderer.class);
-    private JxrPlatformAdapterAxr testRuntime;
-    private MainPanelEntityImpl mainPanelEntity;
+    ImpSplitEngineRenderer mSplitEngineRenderer = Mockito.mock(ImpSplitEngineRenderer.class);
+    private JxrPlatformAdapterAxr mTestRuntime;
+    private MainPanelEntityImpl mMainPanelEntity;
 
     @Before
     public void setUp() {
-        when(perceptionLibrary.initSession(eq(hostActivity), anyInt(), eq(fakeExecutor)))
+        when(mPerceptionLibrary.initSession(eq(mHostActivity), anyInt(), eq(mFakeExecutor)))
                 .thenReturn(immediateFuture(Mockito.mock(Session.class)));
 
-        testRuntime =
+        mTestRuntime =
                 JxrPlatformAdapterAxr.create(
-                        hostActivity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
+                        mHostActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
                         new EntityManager(),
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         /* useSplitEngine= */ false);
 
-        mainPanelEntity = (MainPanelEntityImpl) testRuntime.getMainPanelEntity();
+        mMainPanelEntity = (MainPanelEntityImpl) mTestRuntime.getMainPanelEntity();
     }
 
     @Test
     public void runtimeGetMainPanelEntity_returnsPanelEntityImpl() {
-        assertThat(mainPanelEntity).isNotNull();
+        assertThat(mMainPanelEntity).isNotNull();
     }
 
     @Test
     public void mainPanelEntitySetPixelDimensions_callsExtensions() {
         PixelDimensions kTestPixelDimensions = new PixelDimensions(14, 14);
-        mainPanelEntity.setPixelDimensions(kTestPixelDimensions);
-        assertThat(fakeExtensions.getMainWindowWidth()).isEqualTo(kTestPixelDimensions.width);
-        assertThat(fakeExtensions.getMainWindowHeight()).isEqualTo(kTestPixelDimensions.height);
+        mMainPanelEntity.setPixelDimensions(kTestPixelDimensions);
+        assertThat(mFakeExtensions.getMainWindowWidth()).isEqualTo(kTestPixelDimensions.width);
+        assertThat(mFakeExtensions.getMainWindowHeight()).isEqualTo(kTestPixelDimensions.height);
     }
 
     @Test
@@ -98,8 +98,8 @@
         // This should have the same effect as setPixelDimensions, except that it has to convert
         // from Dimensions to PixelDimensions, so it casts float to int.
         Dimensions kTestDimensions = new Dimensions(123.0f, 123.0f, 123.0f);
-        mainPanelEntity.setSize(kTestDimensions);
-        assertThat(fakeExtensions.getMainWindowWidth()).isEqualTo((int) kTestDimensions.width);
-        assertThat(fakeExtensions.getMainWindowWidth()).isEqualTo((int) kTestDimensions.height);
+        mMainPanelEntity.setSize(kTestDimensions);
+        assertThat(mFakeExtensions.getMainWindowWidth()).isEqualTo((int) kTestDimensions.width);
+        assertThat(mFakeExtensions.getMainWindowWidth()).isEqualTo((int) kTestDimensions.height);
     }
 }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/MediaPlayerExtensionsWrapperImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/MediaPlayerExtensionsWrapperImplTest.java
index 7d8aaac..067a7a4 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/MediaPlayerExtensionsWrapperImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/MediaPlayerExtensionsWrapperImplTest.java
@@ -38,16 +38,16 @@
 
 @RunWith(RobolectricTestRunner.class)
 public class MediaPlayerExtensionsWrapperImplTest {
-    FakeXrExtensions fakeXrExtensions;
-    XrSpatialAudioExtensions spatialAudioExtensions;
-    FakeMediaPlayerExtensions fakeMediaPlayerExtensions;
+    FakeXrExtensions mFakeXrExtensions;
+    XrSpatialAudioExtensions mSpatialAudioExtensions;
+    FakeMediaPlayerExtensions mFakeMediaPlayerExtensions;
 
     @Before
     public void setUp() {
-        fakeXrExtensions = new FakeXrExtensions();
-        spatialAudioExtensions = fakeXrExtensions.fakeSpatialAudioExtensions;
-        fakeMediaPlayerExtensions =
-                (FakeMediaPlayerExtensions) spatialAudioExtensions.getMediaPlayerExtensions();
+        mFakeXrExtensions = new FakeXrExtensions();
+        mSpatialAudioExtensions = mFakeXrExtensions.fakeSpatialAudioExtensions;
+        mFakeMediaPlayerExtensions =
+                (FakeMediaPlayerExtensions) mSpatialAudioExtensions.getMediaPlayerExtensions();
     }
 
     @Test
@@ -62,10 +62,10 @@
                 new JxrPlatformAdapter.PointSourceAttributes(entity);
 
         MediaPlayerExtensionsWrapper wrapper =
-                new MediaPlayerExtensionsWrapperImpl(fakeMediaPlayerExtensions);
+                new MediaPlayerExtensionsWrapperImpl(mFakeMediaPlayerExtensions);
         wrapper.setPointSourceAttributes(mediaPlayer, expectedRtAttr);
 
-        assertThat(fakeMediaPlayerExtensions.getPointSourceAttributes().getNode())
+        assertThat(mFakeMediaPlayerExtensions.getPointSourceAttributes().getNode())
                 .isEqualTo(fakeNode);
     }
 
@@ -79,10 +79,10 @@
                         JxrPlatformAdapter.SpatializerConstants.AMBISONICS_ORDER_THIRD_ORDER);
 
         MediaPlayerExtensionsWrapper wrapper =
-                new MediaPlayerExtensionsWrapperImpl(fakeMediaPlayerExtensions);
+                new MediaPlayerExtensionsWrapperImpl(mFakeMediaPlayerExtensions);
         wrapper.setSoundFieldAttributes(mediaPlayer, expectedRtAttr);
 
-        assertThat(fakeMediaPlayerExtensions.getSoundFieldAttributes().getAmbisonicsOrder())
+        assertThat(mFakeMediaPlayerExtensions.getSoundFieldAttributes().getAmbisonicsOrder())
                 .isEqualTo(expectedAmbisonicOrder);
     }
 }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/MovableComponentImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/MovableComponentImplTest.java
index 2f9e930..f96f578 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/MovableComponentImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/MovableComponentImplTest.java
@@ -82,8 +82,8 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.truth.Expect;
 
+import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -97,56 +97,63 @@
 
 @RunWith(RobolectricTestRunner.class)
 public class MovableComponentImplTest {
-    private final ActivityController<Activity> activityController =
+    private final ActivityController<Activity> mActivityController =
             Robolectric.buildActivity(Activity.class);
-    private final Activity activity = activityController.create().start().get();
-    private final FakeScheduledExecutorService fakeExecutor = new FakeScheduledExecutorService();
-    private final PerceptionLibrary perceptionLibrary = mock(PerceptionLibrary.class);
-    private final FakeXrExtensions fakeExtensions = new FakeXrExtensions();
-    private final FakeImpressApi fakeImpressApi = new FakeImpressApi();
-    private final EntityManager entityManager = new EntityManager();
+    private final Activity mActivity = mActivityController.create().start().get();
+    private final FakeScheduledExecutorService mFakeExecutor = new FakeScheduledExecutorService();
+    private final PerceptionLibrary mPerceptionLibrary = mock(PerceptionLibrary.class);
+    private final FakeXrExtensions mFakeExtensions = new FakeXrExtensions();
+    private final FakeImpressApi mFakeImpressApi = new FakeImpressApi();
+    private final EntityManager mEntityManager = new EntityManager();
 
-    private final SplitEngineSubspaceManager splitEngineSubspaceManager =
+    private final SplitEngineSubspaceManager mSplitEngineSubspaceManager =
             Mockito.mock(SplitEngineSubspaceManager.class);
-    private final ImpSplitEngineRenderer splitEngineRenderer =
+    private final ImpSplitEngineRenderer mSplitEngineRenderer =
             Mockito.mock(ImpSplitEngineRenderer.class);
-    private JxrPlatformAdapter fakeRuntime;
-    private ActivitySpaceImpl activitySpaceImpl;
-    private Node activitySpaceNode;
-    private final AndroidXrEntity activitySpaceRoot = Mockito.mock(AndroidXrEntity.class);
-    private PerceptionSpaceActivityPoseImpl perceptionSpaceActivityPose;
-    private final PanelShadowRenderer panelShadowRenderer = Mockito.mock(PanelShadowRenderer.class);
+    private JxrPlatformAdapter mFakeRuntime;
+    private ActivitySpaceImpl mActivitySpaceImpl;
+    private Node mActivitySpaceNode;
+    private final AndroidXrEntity mActivitySpaceRoot = Mockito.mock(AndroidXrEntity.class);
+    private PerceptionSpaceActivityPoseImpl mPerceptionSpaceActivityPose;
+    private final PanelShadowRenderer mPanelShadowRenderer =
+            Mockito.mock(PanelShadowRenderer.class);
 
     @Rule public final Expect expect = Expect.create();
 
     @Before
     public void setUp() {
-        when(perceptionLibrary.initSession(eq(activity), anyInt(), eq(fakeExecutor)))
+        when(mPerceptionLibrary.initSession(eq(mActivity), anyInt(), eq(mFakeExecutor)))
                 .thenReturn(immediateFuture(mock(Session.class)));
-        fakeRuntime =
+        mFakeRuntime =
                 JxrPlatformAdapterAxr.create(
-                        activity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
-                        entityManager,
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
+                        mEntityManager,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         /* useSplitEngine= */ false);
-        activitySpaceImpl = (ActivitySpaceImpl) fakeRuntime.getActivitySpace();
-        activitySpaceNode = activitySpaceImpl.getNode();
-        perceptionSpaceActivityPose =
-                (PerceptionSpaceActivityPoseImpl) fakeRuntime.getPerceptionSpaceActivityPose();
+        mActivitySpaceImpl = (ActivitySpaceImpl) mFakeRuntime.getActivitySpace();
+        mActivitySpaceNode = mActivitySpaceImpl.getNode();
+        mPerceptionSpaceActivityPose =
+                (PerceptionSpaceActivityPoseImpl) mFakeRuntime.getPerceptionSpaceActivityPose();
+    }
+
+    @After
+    public void tearDown() {
+        // Dispose the runtime between test cases to clean up lingering references.
+        mFakeRuntime.dispose();
     }
 
     private Entity createTestEntity() {
-        return fakeRuntime.createEntity(new Pose(), "test", fakeRuntime.getActivitySpace());
+        return mFakeRuntime.createEntity(new Pose(), "test", mFakeRuntime.getActivitySpace());
     }
 
     private PanelEntity createTestPanelEntity() {
-        Display display = activity.getSystemService(DisplayManager.class).getDisplays()[0];
-        Context displayContext = activity.createDisplayContext(display);
+        Display display = mActivity.getSystemService(DisplayManager.class).getDisplays()[0];
+        Context displayContext = mActivity.createDisplayContext(display);
         View view = new View(displayContext);
         view.setLayoutParams(new LayoutParams(640, 480));
         SurfaceControlViewHost surfaceControlViewHost =
@@ -155,17 +162,17 @@
                         Objects.requireNonNull(displayContext.getDisplay()),
                         new Binder());
         surfaceControlViewHost.setView(view, 10, 10);
-        Node node = fakeExtensions.createNode();
+        Node node = mFakeExtensions.createNode();
 
         PanelEntityImpl panelEntity =
                 new PanelEntityImpl(
                         node,
-                        fakeExtensions,
-                        entityManager,
+                        mFakeExtensions,
+                        mEntityManager,
                         surfaceControlViewHost,
                         new PixelDimensions(10, 10),
-                        fakeExecutor);
-        panelEntity.setParent(activitySpaceImpl);
+                        mFakeExecutor);
+        panelEntity.setParent(mActivitySpaceImpl);
         return panelEntity;
     }
 
@@ -176,19 +183,18 @@
         Mat4f mat4f = new Mat4f(scaledPoseMatrix.getData());
         FakeNodeTransform nodeTransformEvent = new FakeNodeTransform(mat4f);
 
-        ((FakeNode) activitySpaceNode).sendTransformEvent(nodeTransformEvent);
-        fakeExecutor.runAll();
+        ((FakeNode) mActivitySpaceNode).sendTransformEvent(nodeTransformEvent);
+        mFakeExecutor.runAll();
     }
 
     private ImmutableSet<JxrPlatformAdapter.AnchorPlacement> createAnyAnchorPlacement() {
         JxrPlatformAdapter.AnchorPlacement anchorPlacement =
-                fakeRuntime.createAnchorPlacementForPlanes(
+                mFakeRuntime.createAnchorPlacementForPlanes(
                         ImmutableSet.of(PlaneType.ANY), ImmutableSet.of(PlaneSemantic.ANY));
         return ImmutableSet.of(anchorPlacement);
     }
 
     @Test
-    @Ignore
     public void addMovableComponent_addsReformOptionsToNode() {
         Entity entity = createTestEntity();
         MovableComponent movableComponent =
@@ -197,14 +203,14 @@
                         /* scaleInZ= */ false,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -217,7 +223,6 @@
     }
 
     @Test
-    @Ignore
     public void addMovableComponent_addsSystemMovableFlagToNode() {
         Entity entity = createTestEntity();
         MovableComponent movableComponent =
@@ -226,14 +231,14 @@
                         /* scaleInZ= */ false,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -246,7 +251,6 @@
     }
 
     @Test
-    @Ignore
     public void addMovableComponent_addsScaleInZFlagToNode() {
         Entity entity = createTestEntity();
         MovableComponent movableComponent =
@@ -255,14 +259,14 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -275,7 +279,6 @@
     }
 
     @Test
-    @Ignore
     public void addMovableComponent_addsAllFlagsToNode() {
         Entity entity = createTestEntity();
         MovableComponent movableComponent =
@@ -284,14 +287,14 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -305,7 +308,6 @@
     }
 
     @Test
-    @Ignore
     public void setSystemMovableFlag_alsoUpdatesEntityPoseAndScale() {
         AndroidXrEntity entity = (AndroidXrEntity) createTestEntity();
         MovableComponentImpl movableComponent =
@@ -314,14 +316,14 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(entity.addComponent(movableComponent)).isTrue();
         Pose expectedPose =
                 new Pose(new Vector3(2f, 2f, 2f), new Quaternion(0.5f, 0.5f, 0.5f, 0.5f));
@@ -339,15 +341,14 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
 
         expect.that(entity.getPose()).isEqualTo(expectedPose);
         expect.that(entity.getScale()).isEqualTo(expectedScale);
     }
 
     @Test
-    @Ignore
     public void systemMovableFlagNotSet_doesNotUpdateEntityPoseAndScale() {
         AndroidXrEntity entity = (AndroidXrEntity) createTestEntity();
         MovableComponent movableComponent =
@@ -356,14 +357,14 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(entity.addComponent(movableComponent)).isTrue();
         Pose expectedPose = new Pose(new Vector3(1f, 1f, 1f), new Quaternion(0f, 0f, 0f, 1f));
         Vector3 expectedScale = new Vector3(1f, 1f, 1f);
@@ -379,15 +380,14 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
 
         expect.that(entity.getPose()).isEqualTo(expectedPose);
         expect.that(entity.getScale()).isEqualTo(expectedScale);
     }
 
     @Test
-    @Ignore
     public void setSizeOnMovableComponent_setsSizeOnNodeReformOptions() {
         Entity entity = createTestEntity();
         MovableComponent movableComponent =
@@ -396,14 +396,14 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -415,7 +415,6 @@
     }
 
     @Test
-    @Ignore
     public void scaleWithDistanceOnMovableComponent_defaultsToDefaultMode() {
         Entity entity = createTestEntity();
         MovableComponent movableComponent =
@@ -424,14 +423,14 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
 
         // Default value for scaleWithDistanceMode is DEFAULT.
@@ -443,7 +442,6 @@
     }
 
     @Test
-    @Ignore
     public void setScaleWithDistanceOnMovableComponent_setsScaleWithDistanceOnNodeReformOptions() {
         Entity entity = createTestEntity();
         MovableComponent movableComponent =
@@ -452,14 +450,14 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
         assertThat(entity.addComponent(movableComponent)).isTrue();
 
@@ -472,7 +470,6 @@
     }
 
     @Test
-    @Ignore
     public void setPropertiesOnMovableComponentAttachLater_setsPropertiesOnNodeReformOptions() {
         AndroidXrEntity entity = (AndroidXrEntity) createTestEntity();
         MovableComponentImpl movableComponent =
@@ -481,19 +478,19 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         movableComponent.setSize(new Dimensions(2f, 2f, 2f));
         MoveEventListener mockMoveEventListener = mock(MoveEventListener.class);
         movableComponent.addMoveEventListener(directExecutor(), mockMoveEventListener);
-        assertThat(movableComponent.reformEventConsumer).isNotNull();
+        assertThat(movableComponent.mReformEventConsumer).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) entity.getNode();
 
@@ -502,11 +499,10 @@
         assertThat(node.getReformOptions().getCurrentSize().z).isEqualTo(2f);
         assertThat(node.getReformOptions().getEventCallback()).isNotNull();
         assertThat(node.getReformOptions().getEventExecutor()).isNotNull();
-        assertThat(entity.reformEventConsumerMap).isNotEmpty();
+        assertThat(entity.mReformEventConsumerMap).isNotEmpty();
     }
 
     @Test
-    @Ignore
     public void addMoveEventListener_onlyInvokedOnMoveEvent() {
         AndroidXrEntity entity = (AndroidXrEntity) createTestEntity();
         Vector3 initialTranslation = new Vector3(1f, 2f, 3f);
@@ -519,14 +515,14 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) entity.getNode();
@@ -535,23 +531,23 @@
         movableComponent.addMoveEventListener(directExecutor(), mockMoveEventListener);
         assertThat(node.getReformOptions().getEventCallback()).isNotNull();
         assertThat(node.getReformOptions().getEventExecutor()).isNotNull();
-        assertThat(entity.reformEventConsumerMap).isNotEmpty();
+        assertThat(entity.mReformEventConsumerMap).isNotEmpty();
 
         FakeReformEvent reformEvent = new FakeReformEvent();
         reformEvent.setType(ReformEvent.REFORM_TYPE_RESIZE);
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         verify(mockMoveEventListener, never()).onMoveEvent(any());
 
         reformEvent.setType(ReformEvent.REFORM_TYPE_MOVE);
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         ArgumentCaptor<MoveEvent> moveEventCaptor = ArgumentCaptor.forClass(MoveEvent.class);
         verify(mockMoveEventListener).onMoveEvent(moveEventCaptor.capture());
         MoveEvent moveEvent = moveEventCaptor.getValue();
@@ -560,7 +556,6 @@
     }
 
     @Test
-    @Ignore
     public void addMoveEventListenerWithExecutor_invokesListenerOnGivenExecutor() {
         Entity entity = createTestEntity();
         MovableComponent movableComponent =
@@ -569,14 +564,14 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -592,15 +587,14 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
         verify(mockMoveEventListener).onMoveEvent(any());
     }
 
     @Test
-    @Ignore
     public void addMoveEventListenerMultiple_invokesAllListeners() {
         Entity entity = createTestEntity();
         MovableComponentImpl movableComponent =
@@ -609,14 +603,14 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
         MoveEventListener mockMoveEventListener1 = mock(MoveEventListener.class);
@@ -630,8 +624,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -640,7 +634,6 @@
     }
 
     @Test
-    @Ignore
     public void removeMoveEventListenerMultiple_removesGivenListener() {
         Entity entity = createTestEntity();
         MovableComponentImpl movableComponent =
@@ -649,14 +642,14 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
         MoveEventListener mockMoveEventListener1 = mock(MoveEventListener.class);
@@ -670,7 +663,7 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        fakeExecutor.runAll();
+        mFakeExecutor.runAll();
         executorService.runAll();
 
         // Verify both listeners are invoked.
@@ -681,8 +674,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -692,7 +685,6 @@
     }
 
     @Test
-    @Ignore
     public void removeMovableComponent_clearsMoveReformOptionsAndMoveEventListeners() {
         Entity entity = createTestEntity();
         MovableComponentImpl movableComponent =
@@ -701,22 +693,22 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
         MoveEventListener mockMoveEventListener = mock(MoveEventListener.class);
 
         movableComponent.addMoveEventListener(directExecutor(), mockMoveEventListener);
-        assertThat(movableComponent.reformEventConsumer).isNotNull();
-        assertThat(((AndroidXrEntity) entity).reformEventConsumerMap).isNotEmpty();
+        assertThat(movableComponent.mReformEventConsumer).isNotNull();
+        assertThat(((AndroidXrEntity) entity).mReformEventConsumerMap).isNotEmpty();
 
         entity.removeComponent(movableComponent);
         assertThat(node.getReformOptions().getEnabledReform() & ReformOptions.ALLOW_MOVE)
@@ -726,12 +718,11 @@
                                 & (ReformOptions.FLAG_SCALE_WITH_DISTANCE
                                         | ReformOptions.FLAG_ALLOW_SYSTEM_MOVEMENT))
                 .isEqualTo(0);
-        assertThat(movableComponent.reformEventConsumer).isNull();
-        assertThat(((AndroidXrEntity) entity).reformEventConsumerMap).isEmpty();
+        assertThat(movableComponent.mReformEventConsumer).isNull();
+        assertThat(((AndroidXrEntity) entity).mReformEventConsumerMap).isEmpty();
     }
 
     @Test
-    @Ignore
     public void movableComponent_canAttachAgainAfterDetach() {
         Entity entity = createTestEntity();
         assertThat(entity).isNotNull();
@@ -741,14 +732,14 @@
                         /* scaleInZ= */ true,
                         /* anchorPlacement= */ ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         entity.removeComponent(movableComponent);
@@ -756,14 +747,13 @@
     }
 
     @Test
-    @Ignore
     public void anchorable_updatesThePoseBasedOnPlanes() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
                 new Pose(new Vector3(-1f, -1f, 0f), new Quaternion(0f, 0f, 0f, 1f)), 1f);
         Session session = Mockito.mock(Session.class);
         Plane plane = mock(Plane.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
 
         // Create a perception plane that is 2 units above the origin.
@@ -786,14 +776,14 @@
                         /* scaleInZ= */ false,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -816,8 +806,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -827,28 +817,27 @@
         // units
         // above it.
         Pose expectedPosition = new Pose(new Vector3(1f, 3f, 1f), new Quaternion(0f, 0f, 0f, 1f));
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isNull();
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isNull();
 
         // The panel shadow renderer should have no interaction.
-        verify(panelShadowRenderer, never()).updatePanelPose(any(), any(), any());
-        verify(panelShadowRenderer, never()).destroy();
-        verify(panelShadowRenderer, never()).hidePlane();
+        verify(mPanelShadowRenderer, never()).updatePanelPose(any(), any(), any());
+        verify(mPanelShadowRenderer, never()).destroy();
+        verify(mPanelShadowRenderer, never()).hidePlane();
 
         // The pose should have moved since the systemMovable is true.
         assertPose(entity.getPose(), expectedPosition);
     }
 
     @Test
-    @Ignore
     public void anchorable_nullParent_updatesThePoseBasedOnPlanes() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
                 new Pose(new Vector3(-1f, -1f, 0f), new Quaternion(0f, 0f, 0f, 1f)), 1f);
         Session session = Mockito.mock(Session.class);
         Plane plane = mock(Plane.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
 
         // Create a perception plane that is 2 units above the origin.
@@ -872,14 +861,14 @@
                         /* scaleInZ= */ false,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -902,8 +891,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -913,23 +902,22 @@
         // units
         // above it.
         Pose expectedPosition = new Pose(new Vector3(1f, 3f, 1f), new Quaternion(0f, 0f, 0f, 1f));
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isNull();
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isNull();
 
         // The pose should have moved since the systemMovable is true.
         assertPose(entity.getPose(), expectedPosition);
     }
 
     @Test
-    @Ignore
     public void anchorable_updatesPoseButDoesNotMove_ifNotSystemMovable() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
                 new Pose(new Vector3(-1f, -1f, 0f), new Quaternion(0f, 0f, 0f, 1f)), 1f);
         Session session = Mockito.mock(Session.class);
         Plane plane = mock(Plane.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
 
         // Create a perception plane that is 2 units above the origin.
@@ -952,14 +940,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -983,8 +971,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -995,27 +983,26 @@
         // above it.
         Pose expectedPosition = new Pose(new Vector3(1f, 3f, 1f), new Quaternion(0f, 0f, 0f, 1f));
 
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isNull();
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isNull();
 
         // The panel shadow renderer should have no interaction if it is not system movable.
-        verify(panelShadowRenderer, never()).updatePanelPose(any(), any(), any());
-        verify(panelShadowRenderer, never()).destroy();
-        verify(panelShadowRenderer, never()).hidePlane();
+        verify(mPanelShadowRenderer, never()).updatePanelPose(any(), any(), any());
+        verify(mPanelShadowRenderer, never()).destroy();
+        verify(mPanelShadowRenderer, never()).hidePlane();
 
         // The pose should not have moved since the systemMovable is false.
         assertPose(entity.getPose(), Pose.Identity);
     }
 
     @Test
-    @Ignore
     public void anchorable_withNonActivityParent_updatesPoseBasedOnPlanesAndParent() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
                 new Pose(new Vector3(-1f, -1f, 0f), new Quaternion(0f, 0f, 0f, 1f)), 1f);
         Session session = Mockito.mock(Session.class);
         Plane plane = mock(Plane.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
 
         // Create a perception plane that is 2 units above the origin.
@@ -1042,14 +1029,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -1073,8 +1060,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -1086,23 +1073,22 @@
         // should
         // be 4 units above the parent.
         Pose expectedPosition = new Pose(new Vector3(1f, 4f, 1f), new Quaternion(0f, 0f, 0f, 1f));
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isNull();
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isNull();
 
         // The pose should have moved since the systemMovable is true.
         assertPose(entity.getPose(), expectedPosition);
     }
 
     @Test
-    @Ignore
     public void anchorableAndScaledParent_updatesThePoseBasedOnPlanes() {
         // Set the activity space pose to be 1 unit to the left of the origin. with a scale of 2.
         setActivitySpacePose(
                 new Pose(new Vector3(-1f, -1f, 0f), new Quaternion(0f, 0f, 0f, 1f)), 2f);
         Session session = Mockito.mock(Session.class);
         Plane plane = mock(Plane.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
 
         // Create a perception plane that is 2 units above the origin.
@@ -1125,14 +1111,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -1156,8 +1142,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -1167,13 +1153,12 @@
         // units above it and the activity space is scaled by 2.
         Pose expectedPosition =
                 new Pose(new Vector3(.5f, 1.5f, .5f), new Quaternion(0f, 0f, 0f, 1f));
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isNull();
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isNull();
     }
 
     @Test
-    @Ignore
     public void anchorable_withinAnchorDistance_setsAnchorEntity() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
@@ -1182,7 +1167,7 @@
         Plane plane = mock(Plane.class);
         Anchor anchor = mock(Anchor.class);
         IBinder sharedAnchorToken = Mockito.mock(IBinder.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
         when(plane.createAnchor(any(), any())).thenReturn(anchor);
         when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
@@ -1207,14 +1192,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -1239,8 +1224,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -1253,15 +1238,14 @@
         Pose expectedPosition =
                 new Pose(new Vector3(0f, 0f, 1f), new Quaternion(-0.707f, 0f, 0f, 0.707f));
 
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         // Check that the anchor entity was set.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(entity.getParent());
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(entity.getParent());
     }
 
     @Test
-    @Ignore
     public void anchorable_withinAnchorDistanceAboveAnchor_resetsPose() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
@@ -1270,7 +1254,7 @@
         Plane plane = mock(Plane.class);
         Anchor anchor = mock(Anchor.class);
         IBinder sharedAnchorToken = Mockito.mock(IBinder.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
         when(plane.createAnchor(any(), any())).thenReturn(anchor);
         when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
@@ -1295,14 +1279,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -1329,8 +1313,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -1343,15 +1327,14 @@
         Pose expectedPosition =
                 new Pose(new Vector3(0f, 0f, 1f), new Quaternion(-0.707f, 0f, 0f, 0.707f));
 
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         // Check that the anchor entity was set.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(entity.getParent());
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(entity.getParent());
     }
 
     @Test
-    @Ignore
     public void anchorable_withIncorrectPlaneType_doesNotCreateAnchor() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
@@ -1360,7 +1343,7 @@
         Plane plane = mock(Plane.class);
         Anchor anchor = mock(Anchor.class);
         IBinder sharedAnchorToken = Mockito.mock(IBinder.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
         when(plane.createAnchor(any(), any())).thenReturn(anchor);
         when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
@@ -1379,7 +1362,7 @@
 
         // Set the anchor placement to be a table.
         AnchorPlacement anchorPlacement =
-                fakeRuntime.createAnchorPlacementForPlanes(
+                mFakeRuntime.createAnchorPlacementForPlanes(
                         ImmutableSet.of(PlaneType.ANY), ImmutableSet.of(PlaneSemantic.TABLE));
         ImmutableSet<AnchorPlacement> anchorPlacementSet = ImmutableSet.of(anchorPlacement);
 
@@ -1391,14 +1374,14 @@
                         /* scaleInZ= */ true,
                         anchorPlacementSet,
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -1423,8 +1406,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -1435,14 +1418,13 @@
         // above it. However, since the plane is not a table plane, the anchor should not be
         // created.
         Pose expectedPosition = new Pose(new Vector3(1f, 3f, 1f), new Quaternion(0f, 0f, 0f, 1f));
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         // Check that the anchor entity was not set.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isNull();
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isNull();
     }
 
     @Test
-    @Ignore
     public void anchorable_withinAnchorDistanceAndScale_setsAnchorEntityAndScales() {
         // Set the activity space pose to be 1 unit to the left of the OpenXR origin and add a scale
         // of
@@ -1454,7 +1436,7 @@
         Plane plane = mock(Plane.class);
         Anchor anchor = mock(Anchor.class);
         IBinder sharedAnchorToken = Mockito.mock(IBinder.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
         when(plane.createAnchor(any(), any())).thenReturn(anchor);
         when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
@@ -1481,14 +1463,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -1513,8 +1495,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -1527,22 +1509,21 @@
         Pose expectedPosition =
                 new Pose(new Vector3(0f, 0f, 1f), new Quaternion(-0.707f, 0f, 0f, 0.707f));
 
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         // Check that the anchor entity was set.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(entity.getParent());
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(entity.getParent());
         assertVector3(entity.getWorldSpaceScale(), entityScale.times(activityScale));
     }
 
     @Test
-    @Ignore
     public void anchorable_noPlanes_keepsProposedPose() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
                 new Pose(new Vector3(-1f, -1f, 0f), new Quaternion(0f, 0f, 0f, 1f)), 1f);
         Session session = Mockito.mock(Session.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of());
 
         PanelEntity entity = createTestPanelEntity();
@@ -1553,14 +1534,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -1581,26 +1562,25 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
         // The expected position should be unchanged from the proposed event
         Pose expectedPosition = new Pose(new Vector3(1f, 1f, 1f), new Quaternion(0f, 0f, 0f, 1f));
 
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
-        assertThat(moveEventListener.callCount).isEqualTo(1);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
     }
 
     @Test
-    @Ignore
     public void anchorable_noPlaneData_keepsProposedPose() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
                 new Pose(new Vector3(-1f, -1f, 0f), new Quaternion(0f, 0f, 0f, 1f)), 1f);
         Session session = Mockito.mock(Session.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         Plane plane = mock(Plane.class);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
         when(plane.getData(any())).thenReturn(null);
@@ -1613,14 +1593,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -1641,27 +1621,26 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
         // The expected position should be unchanged from the proposed event
         Pose expectedPosition = new Pose(new Vector3(1f, 1f, 1f), new Quaternion(0f, 0f, 0f, 1f));
 
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertThat(moveEventListener.callCount).isEqualTo(1);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
     }
 
     @Test
-    @Ignore
     public void anchorable_outsideExtents_keepsProposedPose() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
                 new Pose(new Vector3(-1f, -1f, 0f), new Quaternion(0f, 0f, 0f, 1f)), 1f);
         Session session = Mockito.mock(Session.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         Plane plane = mock(Plane.class);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
 
@@ -1685,14 +1664,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -1713,21 +1692,20 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
         // The expected position should be unchanged from the proposed event
         Pose expectedPosition = new Pose(new Vector3(1f, 1f, 1f), new Quaternion(0f, 0f, 0f, 1f));
 
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertThat(moveEventListener.callCount).isEqualTo(1);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
     }
 
     @Test
-    @Ignore
     public void anchorable_resetsToActivityPoseAfterAnchoring() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
@@ -1736,7 +1714,7 @@
         Plane plane = mock(Plane.class);
         Anchor anchor = mock(Anchor.class);
         IBinder sharedAnchorToken = Mockito.mock(IBinder.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
         when(plane.createAnchor(any(), any())).thenReturn(anchor);
         when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
@@ -1761,14 +1739,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -1793,8 +1771,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -1807,11 +1785,11 @@
         Pose expectedPosition =
                 new Pose(new Vector3(0f, 0f, 1f), new Quaternion(-0.707f, 0f, 0f, 0.707f));
 
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         // Check that the anchor entity was set.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(entity.getParent());
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(entity.getParent());
 
         // Put the proposed position at 4 above the origin so it would be off the plane. It should
         // reset to the activity space pose and rotation.
@@ -1821,8 +1799,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -1831,16 +1809,15 @@
         // anchor and it should be reparented to the activity space.
         expectedPosition = new Pose(new Vector3(1f, 4f, 1f), new Quaternion(0f, 0f, 0f, 1f));
 
-        assertThat(moveEventListener.callCount).isEqualTo(2);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(2);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         assertPose(entity.getPose(), expectedPosition);
         // Check that parent was updated to the activity space.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(activitySpaceImpl);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(entity.getParent());
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(mActivitySpaceImpl);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(entity.getParent());
     }
 
     @Test
-    @Ignore
     public void anchorable_resetsAndScaleToActivityPoseAfterAnchoring() {
         // Set the activity space pose to be 1 unit to the left of the OpenXR origin and add a scale
         // of
@@ -1852,7 +1829,7 @@
         Plane plane = mock(Plane.class);
         Anchor anchor = mock(Anchor.class);
         IBinder sharedAnchorToken = Mockito.mock(IBinder.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
         when(plane.createAnchor(any(), any())).thenReturn(anchor);
         when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
@@ -1879,14 +1856,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -1911,8 +1888,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -1925,13 +1902,13 @@
         Pose expectedPosition =
                 new Pose(new Vector3(0f, 0f, 1f), new Quaternion(-0.707f, 0f, 0f, 0.707f));
 
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         assertPose(entity.getPose(), expectedPosition);
         assertVector3(entity.getScale(), entityScale.times(activityScale));
         // Check that the anchor entity was set.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(entity.getParent());
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(entity.getParent());
         assertVector3(entity.getWorldSpaceScale(), entityScale.times(activityScale));
 
         // Put the proposed position at 4 above the activity space so it would be off the plane. It
@@ -1942,8 +1919,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -1952,18 +1929,17 @@
         // anchor and it should be reparented to the activity space.
         expectedPosition = new Pose(new Vector3(1f, 4f, 1f), new Quaternion(0f, 0f, 0f, 1f));
 
-        assertThat(moveEventListener.callCount).isEqualTo(2);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(2);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         assertPose(entity.getPose(), expectedPosition);
         // Check that parent was updated to the activity space.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(activitySpaceImpl);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(entity.getParent());
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(mActivitySpaceImpl);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(entity.getParent());
         // Check that the scale was updated to the original scale.
         assertVector3(entity.getScale(), entityScale);
     }
 
     @Test
-    @Ignore
     public void anchorableChildOfEntity_resetsToActivityPoseAfterAnchoring() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
@@ -1972,7 +1948,7 @@
         Plane plane = mock(Plane.class);
         Anchor anchor = mock(Anchor.class);
         IBinder sharedAnchorToken = Mockito.mock(IBinder.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
         when(plane.createAnchor(any(), any())).thenReturn(anchor);
         when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
@@ -2002,14 +1978,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -2035,8 +2011,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -2049,11 +2025,11 @@
         Pose expectedPosition =
                 new Pose(new Vector3(0f, 0f, 1f), new Quaternion(-0.707f, 0f, 0f, 0.707f));
 
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         // Check that the anchor entity was set.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(entity.getParent());
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(entity.getParent());
 
         // Put the proposed position at 4 above the origin so it would be off the plane. It should
         // reset to the activity space pose and rotation.
@@ -2063,8 +2039,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -2073,16 +2049,15 @@
         // anchor and it should be reparented to the activity space not the original parent..
         expectedPosition = new Pose(new Vector3(1f, 4f, 1f), new Quaternion(0f, 0f, 0f, 1f));
 
-        assertThat(moveEventListener.callCount).isEqualTo(2);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(2);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         assertPose(entity.getPose(), expectedPosition);
         // Check that parent was updated to the activity space.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(activitySpaceImpl);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(entity.getParent());
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(mActivitySpaceImpl);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(entity.getParent());
     }
 
     @Test
-    @Ignore
     public void anchorable_shouldDispose_disposesAnchorAfterUnparenting() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
@@ -2091,7 +2066,7 @@
         Plane plane = mock(Plane.class);
         Anchor anchor = mock(Anchor.class);
         IBinder sharedAnchorToken = Mockito.mock(IBinder.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
         when(plane.createAnchor(any(), any())).thenReturn(anchor);
         when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
@@ -2116,14 +2091,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ true,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -2148,8 +2123,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -2162,13 +2137,13 @@
         Pose expectedPosition =
                 new Pose(new Vector3(0f, 0f, 1f), new Quaternion(-0.707f, 0f, 0f, 0.707f));
 
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         // Check that the anchor entity was set.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(entity.getParent());
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(entity.getParent());
         // Cache the anchor entity.
-        Entity anchorEntity = moveEventListener.lastMoveEvent.updatedParent;
+        Entity anchorEntity = moveEventListener.mLastMoveEvent.updatedParent;
 
         // Put the proposed position at 4 above the origin so it would be off the plane. It should
         // reset to the activity space pose and rotation.
@@ -2178,8 +2153,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -2188,20 +2163,19 @@
         // anchor and it should be reparented to the activity space.
         expectedPosition = new Pose(new Vector3(1f, 4f, 1f), new Quaternion(0f, 0f, 0f, 1f));
 
-        assertThat(moveEventListener.callCount).isEqualTo(2);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(2);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         // Check that the anchor entity was set.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(activitySpaceImpl);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(entity.getParent());
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(mActivitySpaceImpl);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(entity.getParent());
 
         // Verify that the anchor entity was disposed by checking that it is no longer in the entity
         // manager.
-        assertThat(entityManager.getEntityForNode(((AndroidXrEntity) anchorEntity).getNode()))
+        assertThat(mEntityManager.getEntityForNode(((AndroidXrEntity) anchorEntity).getNode()))
                 .isNull();
     }
 
     @Test
-    @Ignore
     public void anchorable_shouldDispose_doeNotDisposeIfAnchorHasChildren() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
@@ -2210,7 +2184,7 @@
         Plane plane = mock(Plane.class);
         Anchor anchor = mock(Anchor.class);
         IBinder sharedAnchorToken = Mockito.mock(IBinder.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
         when(plane.createAnchor(any(), any())).thenReturn(anchor);
         when(anchor.getAnchorToken()).thenReturn(sharedAnchorToken);
@@ -2235,14 +2209,14 @@
                         /* scaleInZ= */ true,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ true,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -2267,8 +2241,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -2281,13 +2255,13 @@
         Pose expectedPosition =
                 new Pose(new Vector3(0f, 0f, 1f), new Quaternion(-0.707f, 0f, 0f, 0.707f));
 
-        assertThat(moveEventListener.callCount).isEqualTo(1);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(1);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         // Check that the anchor entity was set.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(entity.getParent());
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isInstanceOf(AnchorEntity.class);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(entity.getParent());
         // Cache the anchor entity.
-        Entity anchorEntity = moveEventListener.lastMoveEvent.updatedParent;
+        Entity anchorEntity = moveEventListener.mLastMoveEvent.updatedParent;
 
         Entity child = createTestEntity();
         anchorEntity.addChild(child);
@@ -2300,8 +2274,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -2310,27 +2284,26 @@
         // anchor and it should be reparented to the activity space.
         expectedPosition = new Pose(new Vector3(1f, 4f, 1f), new Quaternion(0f, 0f, 0f, 1f));
 
-        assertThat(moveEventListener.callCount).isEqualTo(2);
-        assertPose(moveEventListener.lastMoveEvent.currentPose, expectedPosition);
+        assertThat(moveEventListener.mCallCount).isEqualTo(2);
+        assertPose(moveEventListener.mLastMoveEvent.currentPose, expectedPosition);
         // Check that the anchor entity was set.
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(activitySpaceImpl);
-        assertThat(moveEventListener.lastMoveEvent.updatedParent).isEqualTo(entity.getParent());
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(mActivitySpaceImpl);
+        assertThat(moveEventListener.mLastMoveEvent.updatedParent).isEqualTo(entity.getParent());
 
         // Verify that the anchor entity wasn't disposed by checking that it is in the entity
         // manager.
-        assertThat(entityManager.getEntityForNode(((AndroidXrEntity) anchorEntity).getNode()))
+        assertThat(mEntityManager.getEntityForNode(((AndroidXrEntity) anchorEntity).getNode()))
                 .isEqualTo(anchorEntity);
     }
 
     @Test
-    @Ignore
     public void anchorablePanelEntity_nearPlane_rendersShadow() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
                 new Pose(new Vector3(-1f, -1f, 0f), new Quaternion(0f, 0f, 0f, 1f)), 1f);
         Session session = Mockito.mock(Session.class);
         Plane plane = mock(Plane.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
 
         // Create a perception plane that is 2 units above the origin.
@@ -2353,14 +2326,14 @@
                         /* scaleInZ= */ false,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -2375,11 +2348,11 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
 
         // Since it is by the plane a call should be made to the panel shadow renderer.
-        verify(panelShadowRenderer)
+        verify(mPanelShadowRenderer)
                 .updatePanelPose(
                         new Pose(new Vector3(0f, 2f, 1f), new Quaternion(0f, 0f, 0f, 1f)),
                         RuntimeUtils.fromPerceptionPose(perceptionPose),
@@ -2387,14 +2360,13 @@
     }
 
     @Test
-    @Ignore
     public void anchorablePanelEntity_awayFromPlane_hidesShadow() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
                 new Pose(new Vector3(-1f, -1f, 0f), new Quaternion(0f, 0f, 0f, 1f)), 1f);
         Session session = Mockito.mock(Session.class);
         Plane plane = mock(Plane.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
 
         // Create a perception plane that is 2 units above the origin.
@@ -2417,14 +2389,14 @@
                         /* scaleInZ= */ false,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -2438,22 +2410,21 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
 
         // Since it is by the plane a call should be made to the panel shadow renderer.
-        verify(panelShadowRenderer).hidePlane();
+        verify(mPanelShadowRenderer).hidePlane();
     }
 
     @Test
-    @Ignore
     public void anchorablePanelEntity_endMovement_callsDestroy() {
         // Set the activity space pose to be 1 unit to the left of the origin.
         setActivitySpacePose(
                 new Pose(new Vector3(-1f, -1f, 0f), new Quaternion(0f, 0f, 0f, 1f)), 1f);
         Session session = Mockito.mock(Session.class);
         Plane plane = mock(Plane.class);
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(session);
         when(session.getAllPlanes()).thenReturn(ImmutableList.of(plane));
 
         // Create a perception plane that is 2 units above the origin.
@@ -2476,14 +2447,14 @@
                         /* scaleInZ= */ false,
                         createAnyAnchorPlacement(),
                         /* shouldDisposeParentAnchor= */ false,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         assertThat(movableComponent).isNotNull();
         assertThat(entity.addComponent(movableComponent)).isTrue();
         FakeNode node = (FakeNode) ((AndroidXrEntity) entity).getNode();
@@ -2497,21 +2468,21 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
 
         // Since it is by the plane a call should be made to the panel shadow renderer.
-        verify(panelShadowRenderer).destroy();
+        verify(mPanelShadowRenderer).destroy();
     }
 
     static class TestMoveEventListener implements MoveEventListener {
-        int callCount = 0;
-        MoveEvent lastMoveEvent = null;
+        int mCallCount = 0;
+        MoveEvent mLastMoveEvent = null;
 
         @Override
         public void onMoveEvent(MoveEvent event) {
-            lastMoveEvent = event;
-            callCount++;
+            mLastMoveEvent = event;
+            mCallCount++;
         }
     }
 }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/OpenXrActivityPoseTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/OpenXrActivityPoseTest.java
index 4169854..e193cdd 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/OpenXrActivityPoseTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/OpenXrActivityPoseTest.java
@@ -38,7 +38,6 @@
 import androidx.xr.scenecore.testing.FakeXrExtensions.FakeGltfModelToken;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.ParameterizedRobolectricTestRunner;
@@ -51,19 +50,19 @@
 /** Test for common behaviour for ActivityPoses whose world position is retrieved from OpenXr. */
 @RunWith(ParameterizedRobolectricTestRunner.class)
 public final class OpenXrActivityPoseTest {
-    private final AndroidXrEntity activitySpaceRoot = mock(AndroidXrEntity.class);
-    private final FakeXrExtensions fakeExtensions = new FakeXrExtensions();
-    private final PerceptionLibrary perceptionLibrary = mock(PerceptionLibrary.class);
-    private final Session session = mock(Session.class);
-    private final FakeScheduledExecutorService executor = new FakeScheduledExecutorService();
-    private final EntityManager entityManager = new EntityManager();
-    private final ActivitySpaceImpl activitySpace =
+    private final AndroidXrEntity mActivitySpaceRoot = mock(AndroidXrEntity.class);
+    private final FakeXrExtensions mFakeExtensions = new FakeXrExtensions();
+    private final PerceptionLibrary mPerceptionLibrary = mock(PerceptionLibrary.class);
+    private final Session mSession = mock(Session.class);
+    private final FakeScheduledExecutorService mExecutor = new FakeScheduledExecutorService();
+    private final EntityManager mEntityManager = new EntityManager();
+    private final ActivitySpaceImpl mActivitySpace =
             new ActivitySpaceImpl(
-                    fakeExtensions.createNode(),
-                    fakeExtensions,
-                    entityManager,
-                    () -> fakeExtensions.fakeSpatialState,
-                    executor);
+                    mFakeExtensions.createNode(),
+                    mFakeExtensions,
+                    mEntityManager,
+                    () -> mFakeExtensions.fakeSpatialState,
+                    mExecutor);
 
     enum OpenXrActivityPoseType {
         HEAD_ACTIVITY_POSE,
@@ -73,25 +72,28 @@
     @Parameter(0)
     public OpenXrActivityPoseType testActivityPoseType;
 
-    BaseActivityPose testActivityPose;
+    BaseActivityPose mTestActivityPose;
 
+    /** Creates and return list of OpenXrActivityPoseType values. */
     @Parameters
     public static List<Object> data() throws Exception {
         return Arrays.asList(
-                // TODO: b/377812131 - Add OpenXrActivityPoseType.CAMERA_ACTIVITY_POSE.
-                new Object[] {OpenXrActivityPoseType.HEAD_ACTIVITY_POSE});
+                new Object[] {
+                    OpenXrActivityPoseType.HEAD_ACTIVITY_POSE,
+                    OpenXrActivityPoseType.CAMERA_ACTIVITY_POSE
+                });
     }
 
     @Before
     public void doBeforeEachTest() {
         // By default, set the activity space to the root of the underlying OpenXR reference space.
-        this.activitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
     }
 
     /** Creates a HeadActivityPoseImpl instance. */
     private HeadActivityPoseImpl createHeadActivityPose(
             ActivitySpaceImpl activitySpace, AndroidXrEntity activitySpaceRoot) {
-        return new HeadActivityPoseImpl(activitySpace, activitySpaceRoot, perceptionLibrary);
+        return new HeadActivityPoseImpl(activitySpace, activitySpaceRoot, mPerceptionLibrary);
     }
 
     /** Creates a CameraViewActivityPoseImpl instance. */
@@ -101,11 +103,11 @@
                 CameraViewActivityPose.CAMERA_TYPE_LEFT_EYE,
                 activitySpace,
                 activitySpaceRoot,
-                perceptionLibrary);
+                mPerceptionLibrary);
     }
 
     private BaseActivityPose createTestActivityPose() {
-        return createTestActivityPose(activitySpace, activitySpaceRoot);
+        return createTestActivityPose(mActivitySpace, mActivitySpaceRoot);
     }
 
     private BaseActivityPose createTestActivityPose(
@@ -120,20 +122,24 @@
     }
 
     private void setPerceptionPose(Pose pose) {
-        when(perceptionLibrary.getSession()).thenReturn(session);
+        when(mPerceptionLibrary.getSession()).thenReturn(mSession);
         androidx.xr.scenecore.impl.perception.Pose perceptionPose =
                 pose == null ? null : RuntimeUtils.poseToPerceptionPose(pose);
         switch (testActivityPoseType) {
             case HEAD_ACTIVITY_POSE:
                 {
-                    when(session.getHeadPose()).thenReturn(perceptionPose);
+                    when(mSession.getHeadPose()).thenReturn(perceptionPose);
                     break;
                 }
             case CAMERA_ACTIVITY_POSE:
                 {
+                    if (perceptionPose == null) {
+                        when(mSession.getStereoViews()).thenReturn(null);
+                        break;
+                    }
                     ViewProjection viewProjection =
                             new ViewProjection(perceptionPose, new Fov(0, 0, 0, 0));
-                    when(session.getStereoViews())
+                    when(mSession.getStereoViews())
                             .thenReturn(new ViewProjections(viewProjection, viewProjection));
                     break;
                 }
@@ -144,110 +150,111 @@
     private GltfEntityImpl createGltfEntity() {
         FakeGltfModelToken modelToken = new FakeGltfModelToken("model");
         GltfModelResourceImpl model = new GltfModelResourceImpl(modelToken);
-        return new GltfEntityImpl(model, activitySpace, fakeExtensions, entityManager, executor);
+        return new GltfEntityImpl(
+                model, mActivitySpace, mFakeExtensions, mEntityManager, mExecutor);
     }
 
     @Test
     public void
             getPoseInActivitySpace_noActivitySpaceOpenXrReferenceSpacePose_returnsIdentityPose() {
-        testActivityPose = createTestActivityPose();
+        mTestActivityPose = createTestActivityPose();
         Pose pose = new Pose(new Vector3(1, 1, 1), new Quaternion(0, 1, 0, 1));
         setPerceptionPose(pose);
-        activitySpace.openXrReferenceSpacePose = null;
+        mActivitySpace.mOpenXrReferenceSpacePose = null;
 
-        assertPose(testActivityPose.getPoseInActivitySpace(), new Pose());
+        assertPose(mTestActivityPose.getPoseInActivitySpace(), new Pose());
     }
 
     @Test
     public void getPoseInActivitySpace_whenAtSamePose_returnsIdentityPose() {
-        testActivityPose = createTestActivityPose();
+        mTestActivityPose = createTestActivityPose();
         Pose pose = new Pose(new Vector3(1, 1, 1), new Quaternion(0, 1, 0, 1).toNormalized());
         setPerceptionPose(pose);
-        activitySpace.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.fromPose(pose));
 
-        assertPose(testActivityPose.getPoseInActivitySpace(), new Pose());
+        assertPose(mTestActivityPose.getPoseInActivitySpace(), new Pose());
     }
 
-    @Ignore("b/384930655")
     @Test
     public void getPoseInActivitySpace_returnsDifferencePose() {
-        testActivityPose = createTestActivityPose();
+        mTestActivityPose = createTestActivityPose();
         Pose pose = new Pose(new Vector3(1, 1, 1), new Quaternion(0, 1, 0, 1));
         setPerceptionPose(pose);
-        activitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
 
-        assertPose(testActivityPose.getPoseInActivitySpace(), pose);
+        assertPose(mTestActivityPose.getPoseInActivitySpace(), pose);
     }
 
     @Test
     public void getActivitySpaceScale_returnsInverseOfActivitySpaceWorldScale() throws Exception {
         float activitySpaceScale = 5f;
-        this.activitySpace.setOpenXrReferenceSpacePose(Matrix4.fromScale(activitySpaceScale));
-        testActivityPose = createTestActivityPose();
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.fromScale(activitySpaceScale));
+        mTestActivityPose = createTestActivityPose();
         assertVector3(
-                testActivityPose.getActivitySpaceScale(),
+                mTestActivityPose.getActivitySpaceScale(),
                 new Vector3(1f, 1f, 1f).div(activitySpaceScale));
     }
 
     @Test
     public void getPoseInActivitySpace_withNoActivitySpace_returnsIdentityPose() {
-        testActivityPose = createTestActivityPose(/* activitySpace= */ null, activitySpaceRoot);
+        mTestActivityPose = createTestActivityPose(/* activitySpace= */ null, mActivitySpaceRoot);
 
-        assertPose(testActivityPose.getPoseInActivitySpace(), new Pose());
+        assertPose(mTestActivityPose.getPoseInActivitySpace(), new Pose());
     }
 
     @Test
     public void getActivitySpacePose_whenAtSamePose_returnsIdentityPose() {
-        testActivityPose = createTestActivityPose();
+        mTestActivityPose = createTestActivityPose();
         Pose pose = new Pose(new Vector3(1, 1, 1), new Quaternion(0, 1, 0, 1).toNormalized());
         setPerceptionPose(pose);
-        when(activitySpaceRoot.getPoseInActivitySpace()).thenReturn(pose);
+        when(mActivitySpaceRoot.getPoseInActivitySpace()).thenReturn(pose);
 
-        assertPose(testActivityPose.getActivitySpacePose(), new Pose());
+        assertPose(mTestActivityPose.getActivitySpacePose(), new Pose());
     }
 
     @Test
     public void getActivitySpacePose_returnsDifferencePose() {
-        testActivityPose = createTestActivityPose();
+        mTestActivityPose = createTestActivityPose();
         Pose pose = new Pose(new Vector3(1, 1, 1), new Quaternion(0, 1, 0, 1));
         setPerceptionPose(pose);
-        when(activitySpaceRoot.getPoseInActivitySpace()).thenReturn(new Pose());
+        when(mActivitySpaceRoot.getPoseInActivitySpace()).thenReturn(new Pose());
 
-        assertPose(testActivityPose.getActivitySpacePose(), pose);
+        assertPose(mTestActivityPose.getActivitySpacePose(), pose);
     }
 
     @Test
     public void getActivitySpacePoseWithError_returnsLastKnownPose() {
-        testActivityPose = createTestActivityPose();
+        mTestActivityPose = createTestActivityPose();
         Pose pose = new Pose(new Vector3(1, 1, 1), new Quaternion(0, 1, 0, 1));
         setPerceptionPose(pose);
-        when(activitySpaceRoot.getPoseInActivitySpace()).thenReturn(new Pose());
-        assertPose(testActivityPose.getActivitySpacePose(), pose);
+        when(mActivitySpaceRoot.getPoseInActivitySpace()).thenReturn(new Pose());
+        assertPose(mTestActivityPose.getActivitySpacePose(), pose);
 
         setPerceptionPose(null);
-        assertPose(testActivityPose.getActivitySpacePose(), pose);
+        assertPose(mTestActivityPose.getActivitySpacePose(), pose);
     }
 
     @Test
     public void getActivitySpacePose_withNonAndroidXrActivitySpaceRoot_returnsIdentityPose()
             throws Exception {
-        testActivityPose = createTestActivityPose(activitySpace, /* activitySpaceRoot= */ null);
+        mTestActivityPose = createTestActivityPose(mActivitySpace, /* activitySpaceRoot= */ null);
 
-        assertPose(testActivityPose.getActivitySpacePose(), new Pose());
+        assertPose(mTestActivityPose.getActivitySpacePose(), new Pose());
     }
 
     @Test
     public void transformPoseTo_withActivitySpace_returnsTransformedPose() {
-        testActivityPose = createTestActivityPose();
+        mTestActivityPose = createTestActivityPose();
         Pose pose = new Pose(new Vector3(1f, 2f, 3f), Quaternion.Identity);
         setPerceptionPose(pose);
-        activitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
 
         Pose userHeadSpaceOffset =
                 new Pose(
                         new Vector3(10f, 0f, 0f),
                         Quaternion.fromEulerAngles(new Vector3(0f, 0f, 90f)));
-        Pose transformedPose = testActivityPose.transformPoseTo(userHeadSpaceOffset, activitySpace);
+        Pose transformedPose =
+                mTestActivityPose.transformPoseTo(userHeadSpaceOffset, mActivitySpace);
         assertPose(
                 transformedPose,
                 new Pose(
@@ -257,21 +264,21 @@
 
     @Test
     public void transformPoseTo_fromActivitySpaceChild_returnsUserHeadSpacePose() {
-        testActivityPose = createTestActivityPose();
+        mTestActivityPose = createTestActivityPose();
         GltfEntityImpl childEntity1 = createGltfEntity();
         Pose pose = new Pose(new Vector3(1f, 2f, 3f), Quaternion.Identity);
         Pose childPose = new Pose(new Vector3(-1f, -2f, -3f), Quaternion.Identity);
 
-        activitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
-        activitySpace.addChild(childEntity1);
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.Identity);
+        mActivitySpace.addChild(childEntity1);
         childEntity1.setPose(childPose);
         setPerceptionPose(pose);
 
         assertPose(
-                activitySpace.transformPoseTo(new Pose(), testActivityPose),
+                mActivitySpace.transformPoseTo(new Pose(), mTestActivityPose),
                 new Pose(new Vector3(-1f, -2f, -3f), Quaternion.Identity));
 
-        Pose transformedPose = childEntity1.transformPoseTo(new Pose(), testActivityPose);
+        Pose transformedPose = childEntity1.transformPoseTo(new Pose(), mTestActivityPose);
         assertPose(transformedPose, new Pose(new Vector3(-2f, -4f, -6f), Quaternion.Identity));
     }
 }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/PanelEntityImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/PanelEntityImplTest.java
index feeedf5..10fa138 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/PanelEntityImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/PanelEntityImplTest.java
@@ -59,41 +59,42 @@
 public class PanelEntityImplTest {
     private static final Dimensions kVgaResolutionPx = new Dimensions(640f, 480f, 0f);
     private static final Dimensions kHdResolutionPx = new Dimensions(1280f, 720f, 0f);
-    private final FakeXrExtensions fakeExtensions = new FakeXrExtensions();
-    FakeImpressApi fakeImpressApi = new FakeImpressApi();
-    private final ActivityController<Activity> activityController =
+    private final FakeXrExtensions mFakeExtensions = new FakeXrExtensions();
+    FakeImpressApi mFakeImpressApi = new FakeImpressApi();
+    private final ActivityController<Activity> mActivityController =
             Robolectric.buildActivity(Activity.class);
-    private final Activity activity = activityController.create().start().get();
-    private final FakeScheduledExecutorService fakeExecutor = new FakeScheduledExecutorService();
-    private final PerceptionLibrary perceptionLibrary = mock(PerceptionLibrary.class);
-    private final EntityManager entityManager = new EntityManager();
-    private JxrPlatformAdapterAxr testRuntime;
+    private final Activity mActivity = mActivityController.create().start().get();
+    private final FakeScheduledExecutorService mMakeFakeExecutor =
+            new FakeScheduledExecutorService();
+    private final PerceptionLibrary mPerceptionLibrary = mock(PerceptionLibrary.class);
+    private final EntityManager mEntityManager = new EntityManager();
+    private JxrPlatformAdapterAxr mTestRuntime;
 
-    SplitEngineSubspaceManager splitEngineSubspaceManager =
+    SplitEngineSubspaceManager mSplitEngineSubspaceManager =
             Mockito.mock(SplitEngineSubspaceManager.class);
-    ImpSplitEngineRenderer splitEngineRenderer = Mockito.mock(ImpSplitEngineRenderer.class);
+    ImpSplitEngineRenderer mSplitEngineRenderer = Mockito.mock(ImpSplitEngineRenderer.class);
 
     @Before
     public void setUp() {
-        when(perceptionLibrary.initSession(eq(activity), anyInt(), eq(fakeExecutor)))
+        when(mPerceptionLibrary.initSession(eq(mActivity), anyInt(), eq(mMakeFakeExecutor)))
                 .thenReturn(immediateFuture(Mockito.mock(Session.class)));
 
-        testRuntime =
+        mTestRuntime =
                 JxrPlatformAdapterAxr.create(
-                        activity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApi,
+                        mActivity,
+                        mMakeFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApi,
                         new EntityManager(),
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         /* useSplitEngine= */ false);
     }
 
     private PanelEntityImpl createPanelEntity(Dimensions surfaceDimensionsPx) {
-        Display display = activity.getSystemService(DisplayManager.class).getDisplays()[0];
-        Context displayContext = activity.createDisplayContext(display);
+        Display display = mActivity.getSystemService(DisplayManager.class).getDisplays()[0];
+        Context displayContext = mActivity.createDisplayContext(display);
         View view = new View(displayContext);
         view.setLayoutParams(new LayoutParams(640, 480));
         SurfaceControlViewHost surfaceControlViewHost =
@@ -103,20 +104,20 @@
                         new Binder());
         surfaceControlViewHost.setView(
                 view, (int) surfaceDimensionsPx.width, (int) surfaceDimensionsPx.height);
-        Node node = fakeExtensions.createNode();
+        Node node = mFakeExtensions.createNode();
 
         PanelEntityImpl panelEntity =
                 new PanelEntityImpl(
                         node,
-                        fakeExtensions,
-                        entityManager,
+                        mFakeExtensions,
+                        mEntityManager,
                         surfaceControlViewHost,
                         new PixelDimensions(
                                 (int) surfaceDimensionsPx.width, (int) surfaceDimensionsPx.height),
-                        fakeExecutor);
+                        mMakeFakeExecutor);
 
         // TODO(b/352829122): introduce a TestRootEntity which can serve as a parent
-        panelEntity.setParent(testRuntime.getActivitySpaceRootImpl());
+        panelEntity.setParent(mTestRuntime.getActivitySpaceRootImpl());
         return panelEntity;
     }
 
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/PerceptionSpaceActivityPoseImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/PerceptionSpaceActivityPoseImplTest.java
index 45c4085..95d3e56 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/PerceptionSpaceActivityPoseImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/PerceptionSpaceActivityPoseImplTest.java
@@ -39,35 +39,36 @@
 @RunWith(RobolectricTestRunner.class)
 public final class PerceptionSpaceActivityPoseImplTest {
 
-    private final AndroidXrEntity activitySpaceRoot = Mockito.mock(AndroidXrEntity.class);
-    private final FakeXrExtensions fakeExtensions = new FakeXrExtensions();
-    private final FakeScheduledExecutorService executor = new FakeScheduledExecutorService();
-    private final EntityManager entityManager = new EntityManager();
-    private final ActivitySpaceImpl activitySpace =
+    private final AndroidXrEntity mActivitySpaceRoot = Mockito.mock(AndroidXrEntity.class);
+    private final FakeXrExtensions mFakeExtensions = new FakeXrExtensions();
+    private final FakeScheduledExecutorService mExecutor = new FakeScheduledExecutorService();
+    private final EntityManager mEntityManager = new EntityManager();
+    private final ActivitySpaceImpl mActivitySpace =
             new ActivitySpaceImpl(
-                    fakeExtensions.createNode(),
-                    fakeExtensions,
-                    entityManager,
-                    () -> fakeExtensions.fakeSpatialState,
-                    executor);
+                    mFakeExtensions.createNode(),
+                    mFakeExtensions,
+                    mEntityManager,
+                    () -> mFakeExtensions.fakeSpatialState,
+                    mExecutor);
 
-    private PerceptionSpaceActivityPoseImpl perceptionSpaceActivityPose;
+    private PerceptionSpaceActivityPoseImpl mPerceptionSpaceActivityPose;
 
     private FakeNode getActivitySpaceNode() {
-        return (FakeNode) activitySpace.getNode();
+        return (FakeNode) mActivitySpace.getNode();
     }
 
     /** Creates a generic glTF entity. */
     private GltfEntityImpl createGltfEntity() {
         FakeGltfModelToken modelToken = new FakeGltfModelToken("model");
         GltfModelResourceImpl model = new GltfModelResourceImpl(modelToken);
-        return new GltfEntityImpl(model, activitySpace, fakeExtensions, entityManager, executor);
+        return new GltfEntityImpl(
+                model, mActivitySpace, mFakeExtensions, mEntityManager, mExecutor);
     }
 
     @Before
     public void setUp() {
-        perceptionSpaceActivityPose =
-                new PerceptionSpaceActivityPoseImpl(activitySpace, activitySpaceRoot);
+        mPerceptionSpaceActivityPose =
+                new PerceptionSpaceActivityPoseImpl(mActivitySpace, mActivitySpaceRoot);
     }
 
     @Test
@@ -80,9 +81,9 @@
         getActivitySpaceNode()
                 .sendTransformEvent(
                         new FakeNodeTransform(new Mat4f(activitySpaceMatrix.getData())));
-        executor.runAll();
+        mExecutor.runAll();
 
-        Pose poseInActivitySpace = perceptionSpaceActivityPose.getPoseInActivitySpace();
+        Pose poseInActivitySpace = mPerceptionSpaceActivityPose.getPoseInActivitySpace();
 
         Pose expectedPose = activitySpaceMatrix.getInverse().getPose();
         assertPose(poseInActivitySpace, expectedPose);
@@ -98,10 +99,10 @@
         getActivitySpaceNode()
                 .sendTransformEvent(
                         new FakeNodeTransform(new Mat4f(activitySpaceMatrix.getData())));
-        executor.runAll();
+        mExecutor.runAll();
 
         Pose transformedPose =
-                perceptionSpaceActivityPose.transformPoseTo(new Pose(), activitySpace);
+                mPerceptionSpaceActivityPose.transformPoseTo(new Pose(), mActivitySpace);
 
         Pose expectedPose = activitySpaceMatrix.getInverse().getPose();
         assertPose(transformedPose, expectedPose);
@@ -117,11 +118,11 @@
         getActivitySpaceNode()
                 .sendTransformEvent(
                         new FakeNodeTransform(new Mat4f(activitySpaceMatrix.getData())));
-        executor.runAll();
+        mExecutor.runAll();
         GltfEntityImpl gltfEntity = createGltfEntity();
         gltfEntity.setScale(new Vector3(2.0f, 2.0f, 2.0f));
 
-        Pose transformedPose = perceptionSpaceActivityPose.transformPoseTo(new Pose(), gltfEntity);
+        Pose transformedPose = mPerceptionSpaceActivityPose.transformPoseTo(new Pose(), gltfEntity);
 
         Pose unscaledPose = activitySpaceMatrix.getInverse().getPose();
         Pose expectedPose =
@@ -134,9 +135,9 @@
     @Test
     public void getActivitySpaceScale_returnsInverseOfActivitySpaceWorldScale() throws Exception {
         float activitySpaceScale = 5f;
-        this.activitySpace.setOpenXrReferenceSpacePose(Matrix4.fromScale(activitySpaceScale));
+        mActivitySpace.setOpenXrReferenceSpacePose(Matrix4.fromScale(activitySpaceScale));
         assertVector3(
-                perceptionSpaceActivityPose.getActivitySpaceScale(),
+                mPerceptionSpaceActivityPose.getActivitySpaceScale(),
                 new Vector3(1f, 1f, 1f).div(activitySpaceScale));
     }
 }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/PointerCaptureComponentImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/PointerCaptureComponentImplTest.java
index 11c5ab3..be6c0b2 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/PointerCaptureComponentImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/PointerCaptureComponentImplTest.java
@@ -58,41 +58,41 @@
         }
     }
 
-    private final FakeStateListener stateListener = new FakeStateListener();
+    private final FakeStateListener mStateListener = new FakeStateListener();
 
-    private final FakeInputEventListener inputListener = new FakeInputEventListener();
+    private final FakeInputEventListener mInputListener = new FakeInputEventListener();
 
-    private final FakeXrExtensions fakeExtensions = new FakeXrExtensions();
-    private final FakeScheduledExecutorService fakeScheduler = new FakeScheduledExecutorService();
-    private final FakeNode fakeNode = (FakeNode) fakeExtensions.createNode();
+    private final FakeXrExtensions mFakeExtensions = new FakeXrExtensions();
+    private final FakeScheduledExecutorService mFakeScheduler = new FakeScheduledExecutorService();
+    private final FakeNode mFakeNode = (FakeNode) mFakeExtensions.createNode();
 
-    private final Entity entity =
-            new AndroidXrEntity(fakeNode, fakeExtensions, new EntityManager(), fakeScheduler) {};
+    private final Entity mEntity =
+            new AndroidXrEntity(mFakeNode, mFakeExtensions, new EntityManager(), mFakeScheduler) {};
 
     @Test
     public void onAttach_enablesPointerCapture() {
         PointerCaptureComponentImpl component =
-                new PointerCaptureComponentImpl(directExecutor(), stateListener, inputListener);
+                new PointerCaptureComponentImpl(directExecutor(), mStateListener, mInputListener);
 
-        assertThat(component.onAttach(entity)).isTrue();
+        assertThat(component.onAttach(mEntity)).isTrue();
 
-        assertThat(fakeNode.getPointerCaptureStateCallback()).isNotNull();
+        assertThat(mFakeNode.getPointerCaptureStateCallback()).isNotNull();
     }
 
     @Test
     public void onAttach_setsUpInputEventPropagation() {
         PointerCaptureComponentImpl component =
-                new PointerCaptureComponentImpl(directExecutor(), stateListener, inputListener);
-        assertThat(component.onAttach(entity)).isTrue();
+                new PointerCaptureComponentImpl(directExecutor(), mStateListener, mInputListener);
+        assertThat(component.onAttach(mEntity)).isTrue();
 
         FakeInputEvent fakeInput = new FakeInputEvent();
         fakeInput.setDispatchFlags(InputEvent.DISPATCH_FLAG_CAPTURED_POINTER);
         fakeInput.setOrigin(new Vec3(0, 0, 0));
         fakeInput.setDirection(new Vec3(1, 1, 1));
-        fakeNode.sendInputEvent(fakeInput);
-        fakeScheduler.runAll();
+        mFakeNode.sendInputEvent(fakeInput);
+        mFakeScheduler.runAll();
 
-        assertThat(inputListener.lastEvent).isNotNull();
+        assertThat(mInputListener.lastEvent).isNotNull();
     }
 
     // This should really be a test on AndroidXrEntity, but that does not have tests so it is here
@@ -101,8 +101,8 @@
     @Test
     public void onAttach_onlyPropagatesCapturedEvents() {
         PointerCaptureComponentImpl component =
-                new PointerCaptureComponentImpl(directExecutor(), stateListener, inputListener);
-        assertThat(component.onAttach(entity)).isTrue();
+                new PointerCaptureComponentImpl(directExecutor(), mStateListener, mInputListener);
+        assertThat(component.onAttach(mEntity)).isTrue();
 
         FakeInputEvent fakeCapturedInput = new FakeInputEvent();
         fakeCapturedInput.setDispatchFlags(InputEvent.DISPATCH_FLAG_CAPTURED_POINTER);
@@ -115,21 +115,22 @@
         fakeInput.setOrigin(new Vec3(0, 0, 0));
         fakeInput.setDirection(new Vec3(1, 1, 1));
 
-        fakeNode.sendInputEvent(fakeCapturedInput);
-        fakeNode.sendInputEvent(fakeInput);
+        mFakeNode.sendInputEvent(fakeCapturedInput);
+        mFakeNode.sendInputEvent(fakeInput);
 
-        fakeScheduler.runAll();
+        mFakeScheduler.runAll();
 
-        assertThat(inputListener.lastEvent).isNotNull();
-        assertThat(inputListener.lastEvent.timestamp).isEqualTo(fakeCapturedInput.getTimestamp());
+        assertThat(mInputListener.lastEvent).isNotNull();
+        assertThat(mInputListener.lastEvent.timestamp).isEqualTo(fakeCapturedInput.getTimestamp());
     }
 
     @Test
     public void onAttach_propagatesInputOnCorrectThread() {
         FakeScheduledExecutorService propagationExecutor = new FakeScheduledExecutorService();
         PointerCaptureComponentImpl component =
-                new PointerCaptureComponentImpl(propagationExecutor, stateListener, inputListener);
-        assertThat(component.onAttach(entity)).isTrue();
+                new PointerCaptureComponentImpl(
+                        propagationExecutor, mStateListener, mInputListener);
+        assertThat(component.onAttach(mEntity)).isTrue();
 
         FakeInputEvent fakeCapturedInput = new FakeInputEvent();
         fakeCapturedInput.setDispatchFlags(InputEvent.DISPATCH_FLAG_CAPTURED_POINTER);
@@ -137,13 +138,13 @@
         fakeCapturedInput.setOrigin(new Vec3(0, 0, 0));
         fakeCapturedInput.setDirection(new Vec3(1, 1, 1));
 
-        fakeNode.sendInputEvent(fakeCapturedInput);
+        mFakeNode.sendInputEvent(fakeCapturedInput);
 
         assertThat(propagationExecutor.hasNext()).isFalse();
         // Run the scheduler associated with the Entity so that the component's executor has the
         // task
         // scheduled on it.
-        fakeScheduler.runAll();
+        mFakeScheduler.runAll();
 
         assertThat(propagationExecutor.hasNext()).isTrue();
     }
@@ -151,60 +152,60 @@
     @Test
     public void onAttach_setsUpCorrectStatePropagation() {
         PointerCaptureComponentImpl component =
-                new PointerCaptureComponentImpl(directExecutor(), stateListener, inputListener);
-        assertThat(component.onAttach(entity)).isTrue();
+                new PointerCaptureComponentImpl(directExecutor(), mStateListener, mInputListener);
+        assertThat(component.onAttach(mEntity)).isTrue();
 
-        fakeNode.getPointerCaptureStateCallback().accept(Node.POINTER_CAPTURE_STATE_PAUSED);
-        assertThat(stateListener.lastState)
+        mFakeNode.getPointerCaptureStateCallback().accept(Node.POINTER_CAPTURE_STATE_PAUSED);
+        assertThat(mStateListener.lastState)
                 .isEqualTo(PointerCaptureComponent.POINTER_CAPTURE_STATE_PAUSED);
 
-        fakeNode.getPointerCaptureStateCallback().accept(Node.POINTER_CAPTURE_STATE_ACTIVE);
-        assertThat(stateListener.lastState)
+        mFakeNode.getPointerCaptureStateCallback().accept(Node.POINTER_CAPTURE_STATE_ACTIVE);
+        assertThat(mStateListener.lastState)
                 .isEqualTo(PointerCaptureComponent.POINTER_CAPTURE_STATE_ACTIVE);
 
-        fakeNode.getPointerCaptureStateCallback().accept(Node.POINTER_CAPTURE_STATE_STOPPED);
-        assertThat(stateListener.lastState)
+        mFakeNode.getPointerCaptureStateCallback().accept(Node.POINTER_CAPTURE_STATE_STOPPED);
+        assertThat(mStateListener.lastState)
                 .isEqualTo(PointerCaptureComponent.POINTER_CAPTURE_STATE_STOPPED);
     }
 
     @Test
     public void onAttach_failsIfAlreadyAttached() {
         PointerCaptureComponentImpl component =
-                new PointerCaptureComponentImpl(directExecutor(), stateListener, inputListener);
-        assertThat(component.onAttach(entity)).isTrue();
-        assertThat(component.onAttach(entity)).isFalse();
+                new PointerCaptureComponentImpl(directExecutor(), mStateListener, mInputListener);
+        assertThat(component.onAttach(mEntity)).isTrue();
+        assertThat(component.onAttach(mEntity)).isFalse();
     }
 
     @Test
     public void onAttach_failesIfEntityAlreadyHasAnAttachedPointerCaptureComponent() {
         PointerCaptureComponentImpl component =
-                new PointerCaptureComponentImpl(directExecutor(), stateListener, inputListener);
-        assertThat(component.onAttach(entity)).isTrue();
+                new PointerCaptureComponentImpl(directExecutor(), mStateListener, mInputListener);
+        assertThat(component.onAttach(mEntity)).isTrue();
 
         PointerCaptureComponentImpl component2 =
-                new PointerCaptureComponentImpl(directExecutor(), stateListener, inputListener);
-        assertThat(component2.onAttach(entity)).isFalse();
+                new PointerCaptureComponentImpl(directExecutor(), mStateListener, mInputListener);
+        assertThat(component2.onAttach(mEntity)).isFalse();
     }
 
     @Test
     public void onDetach_stopsPointerCapture() {
         PointerCaptureComponentImpl component =
-                new PointerCaptureComponentImpl(directExecutor(), stateListener, inputListener);
-        assertThat(component.onAttach(entity)).isTrue();
+                new PointerCaptureComponentImpl(directExecutor(), mStateListener, mInputListener);
+        assertThat(component.onAttach(mEntity)).isTrue();
 
-        component.onDetach(entity);
+        component.onDetach(mEntity);
 
-        assertThat(fakeNode.getPointerCaptureStateCallback()).isNull();
+        assertThat(mFakeNode.getPointerCaptureStateCallback()).isNull();
     }
 
     @Test
     public void onDetach_removesInputListener() {
         PointerCaptureComponentImpl component =
-                new PointerCaptureComponentImpl(directExecutor(), stateListener, inputListener);
-        assertThat(component.onAttach(entity)).isTrue();
+                new PointerCaptureComponentImpl(directExecutor(), mStateListener, mInputListener);
+        assertThat(component.onAttach(mEntity)).isTrue();
 
-        component.onDetach(entity);
+        component.onDetach(mEntity);
 
-        assertThat(fakeNode.getListener()).isNull();
+        assertThat(mFakeNode.getListener()).isNull();
     }
 }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/ResizableComponentImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/ResizableComponentImplTest.java
index 25ec51e..fe459a1 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/ResizableComponentImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/ResizableComponentImplTest.java
@@ -34,6 +34,7 @@
 import androidx.xr.extensions.node.Node;
 import androidx.xr.extensions.node.ReformEvent;
 import androidx.xr.extensions.node.ReformOptions;
+import androidx.xr.extensions.node.Vec3;
 import androidx.xr.runtime.math.Pose;
 import androidx.xr.scenecore.JxrPlatformAdapter;
 import androidx.xr.scenecore.JxrPlatformAdapter.Dimensions;
@@ -65,45 +66,46 @@
 public class ResizableComponentImplTest {
     private static final Dimensions kMinDimensions = new Dimensions(0f, 0f, 0f);
     private static final Dimensions kMaxDimensions = new Dimensions(10f, 10f, 10f);
-    private final ActivityController<Activity> activityController =
+    private final ActivityController<Activity> mActivityController =
             Robolectric.buildActivity(Activity.class);
-    private final Activity activity = activityController.create().start().get();
-    private final FakeScheduledExecutorService fakeExecutor = new FakeScheduledExecutorService();
-    private final PerceptionLibrary perceptionLibrary = mock(PerceptionLibrary.class);
-    private final FakeXrExtensions fakeExtensions = new FakeXrExtensions();
-    private final FakeImpressApi fakeImpressApiImpl = new FakeImpressApi();
-    private final EntityManager entityManager = new EntityManager();
-    private final Node activitySpaceNode = fakeExtensions.createNode();
-    private final ActivitySpaceImpl activitySpaceImpl =
+    private final Activity mActivity = mActivityController.create().start().get();
+    private final FakeScheduledExecutorService mFakeExecutor = new FakeScheduledExecutorService();
+    private final PerceptionLibrary mPerceptionLibrary = mock(PerceptionLibrary.class);
+    private final FakeXrExtensions mFakeExtensions = new FakeXrExtensions();
+    private final FakeImpressApi mFakeImpressApiImpl = new FakeImpressApi();
+    private final EntityManager mEntityManager = new EntityManager();
+    private final Node mActivitySpaceNode = mFakeExtensions.createNode();
+    private final ActivitySpaceImpl mActivitySpaceImpl =
             new ActivitySpaceImpl(
-                    activitySpaceNode,
-                    fakeExtensions,
-                    entityManager,
-                    () -> fakeExtensions.fakeSpatialState,
-                    fakeExecutor);
-    private final AndroidXrEntity activitySpaceRoot = Mockito.mock(AndroidXrEntity.class);
-    private final PerceptionSpaceActivityPoseImpl perceptionSpaceActivityPose =
-            new PerceptionSpaceActivityPoseImpl(activitySpaceImpl, activitySpaceRoot);
-    private final PanelShadowRenderer panelShadowRenderer = Mockito.mock(PanelShadowRenderer.class);
+                    mActivitySpaceNode,
+                    mFakeExtensions,
+                    mEntityManager,
+                    () -> mFakeExtensions.fakeSpatialState,
+                    mFakeExecutor);
+    private final AndroidXrEntity mActivitySpaceRoot = Mockito.mock(AndroidXrEntity.class);
+    private final PerceptionSpaceActivityPoseImpl mPerceptionSpaceActivityPose =
+            new PerceptionSpaceActivityPoseImpl(mActivitySpaceImpl, mActivitySpaceRoot);
+    private final PanelShadowRenderer mPanelShadowRenderer =
+            Mockito.mock(PanelShadowRenderer.class);
 
-    private final SplitEngineSubspaceManager splitEngineSubspaceManager =
+    private final SplitEngineSubspaceManager mSplitEngineSubspaceManager =
             Mockito.mock(SplitEngineSubspaceManager.class);
-    private final ImpSplitEngineRenderer splitEngineRenderer =
+    private final ImpSplitEngineRenderer mSplitEngineRenderer =
             Mockito.mock(ImpSplitEngineRenderer.class);
 
     private Entity createTestEntity() {
-        when(perceptionLibrary.initSession(eq(activity), anyInt(), eq(fakeExecutor)))
+        when(mPerceptionLibrary.initSession(eq(mActivity), anyInt(), eq(mFakeExecutor)))
                 .thenReturn(immediateFuture(mock(Session.class)));
         JxrPlatformAdapter fakeRuntime =
                 JxrPlatformAdapterAxr.create(
-                        activity,
-                        fakeExecutor,
-                        fakeExtensions,
-                        fakeImpressApiImpl,
-                        entityManager,
-                        perceptionLibrary,
-                        splitEngineSubspaceManager,
-                        splitEngineRenderer,
+                        mActivity,
+                        mFakeExecutor,
+                        mFakeExtensions,
+                        mFakeImpressApiImpl,
+                        mEntityManager,
+                        mPerceptionLibrary,
+                        mSplitEngineSubspaceManager,
+                        mSplitEngineRenderer,
                         /* useSplitEngine= */ false);
         return fakeRuntime.createEntity(new Pose(), "test", fakeRuntime.getActivitySpace());
     }
@@ -114,7 +116,7 @@
         Entity entity2 = createTestEntity();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
         assertThat(entity1.addComponent(resizableComponent)).isTrue();
         assertThat(entity2.addComponent(resizableComponent)).isFalse();
@@ -126,7 +128,7 @@
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
 
         assertThat(entity.addComponent(resizableComponent)).isTrue();
@@ -148,7 +150,7 @@
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
 
         assertThat(entity.addComponent(resizableComponent)).isTrue();
@@ -166,7 +168,7 @@
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
 
         assertThat(entity.addComponent(resizableComponent)).isTrue();
@@ -184,7 +186,7 @@
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
 
         assertThat(entity.addComponent(resizableComponent)).isTrue();
@@ -202,7 +204,7 @@
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
 
         assertThat(entity.addComponent(resizableComponent)).isTrue();
@@ -217,12 +219,29 @@
     }
 
     @Test
+    public void
+            setForceShowResizeOverlayOnResizableComponent_setsForceShowResizeOverlayOnNodeReformOptions() {
+        AndroidXrEntity entity = (AndroidXrEntity) createTestEntity();
+        assertThat(entity).isNotNull();
+        ResizableComponentImpl resizableComponent =
+                new ResizableComponentImpl(
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
+        assertThat(resizableComponent).isNotNull();
+
+        assertThat(entity.addComponent(resizableComponent)).isTrue();
+        FakeNode node = (FakeNode) entity.getNode();
+
+        resizableComponent.setForceShowResizeOverlay(true);
+        assertThat(node.getReformOptions().getForceShowResizeOverlay()).isTrue();
+    }
+
+    @Test
     public void addResizableComponentLater_addsReformOptionsToNode() {
         AndroidXrEntity entity = (AndroidXrEntity) createTestEntity();
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
         Dimensions testSize = new Dimensions(1f, 1f, 1f);
         Dimensions testMinSize = new Dimensions(0.25f, 0.25f, 0.25f);
@@ -253,7 +272,7 @@
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
         assertThat(entity.addComponent(resizableComponent)).isTrue();
         FakeNode node = (FakeNode) entity.getNode();
@@ -262,23 +281,23 @@
         resizableComponent.addResizeEventListener(directExecutor(), mockResizeEventListener);
         assertThat(node.getReformOptions().getEventCallback()).isNotNull();
         assertThat(node.getReformOptions().getEventExecutor()).isNotNull();
-        assertThat(entity.reformEventConsumerMap).isNotEmpty();
+        assertThat(entity.mReformEventConsumerMap).isNotEmpty();
 
         FakeReformEvent reformEvent = new FakeReformEvent();
         reformEvent.setType(ReformEvent.REFORM_TYPE_MOVE);
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         verify(mockResizeEventListener, never()).onResizeEvent(any());
 
         reformEvent.setType(ReformEvent.REFORM_TYPE_RESIZE);
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         verify(mockResizeEventListener).onResizeEvent(any());
     }
 
@@ -288,7 +307,7 @@
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
         assertThat(entity.addComponent(resizableComponent)).isTrue();
         FakeNode node = (FakeNode) entity.getNode();
@@ -304,8 +323,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
         verify(mockResizeEventListener).onResizeEvent(any());
@@ -317,7 +336,7 @@
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
         assertThat(entity.addComponent(resizableComponent)).isTrue();
         FakeNode node = (FakeNode) entity.getNode();
@@ -335,8 +354,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
         verify(mockResizeEventListener1).onResizeEvent(any());
@@ -349,7 +368,7 @@
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
         assertThat(entity.addComponent(resizableComponent)).isTrue();
         FakeNode node = (FakeNode) entity.getNode();
@@ -367,8 +386,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
 
@@ -376,8 +395,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
         verify(mockResizeEventListener1).onResizeEvent(any());
@@ -390,7 +409,7 @@
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
         assertThat(entity.addComponent(resizableComponent)).isTrue();
         FakeNode node = (FakeNode) entity.getNode();
@@ -408,8 +427,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         assertThat(executorService.hasNext()).isTrue();
         executorService.runAll();
         verify(mockResizeEventListener1).onResizeEvent(any());
@@ -418,7 +437,7 @@
         resizableComponent.removeResizeEventListener(mockResizeEventListener1);
         resizableComponent.removeResizeEventListener(mockResizeEventListener2);
 
-        assertThat(entity.reformEventConsumerMap).isEmpty();
+        assertThat(entity.mReformEventConsumerMap).isEmpty();
     }
 
     @Test
@@ -427,19 +446,19 @@
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
         assertThat(entity.addComponent(resizableComponent)).isTrue();
         FakeNode node = (FakeNode) entity.getNode();
         ResizeEventListener mockResizeEventListener = mock(ResizeEventListener.class);
 
         resizableComponent.addResizeEventListener(directExecutor(), mockResizeEventListener);
-        assertThat(resizableComponent.reformEventConsumer).isNotNull();
+        assertThat(resizableComponent.mReformEventConsumer).isNotNull();
 
         entity.removeComponent(resizableComponent);
         assertThat(node.getReformOptions().getEnabledReform() & ReformOptions.ALLOW_RESIZE)
                 .isEqualTo(0);
-        assertThat(entity.reformEventConsumerMap).isEmpty();
+        assertThat(entity.mReformEventConsumerMap).isEmpty();
     }
 
     @Test
@@ -452,18 +471,18 @@
                         true,
                         ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ true,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor,
-                        fakeExtensions,
+                        mFakeExecutor,
+                        mFakeExtensions,
                         new Dimensions(0f, 0f, 0f),
                         new Dimensions(5f, 5f, 5f));
         assertThat(entity.addComponent(movableComponent)).isTrue();
@@ -483,18 +502,18 @@
                         true,
                         ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ true,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor,
-                        fakeExtensions,
+                        mFakeExecutor,
+                        mFakeExtensions,
                         new Dimensions(0f, 0f, 0f),
                         new Dimensions(5f, 5f, 5f));
         assertThat(entity.addComponent(movableComponent)).isTrue();
@@ -516,16 +535,16 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         verify(resizeEventListener).onResizeEvent(any());
 
         reformEvent.setType(ReformEvent.REFORM_TYPE_MOVE);
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         verify(moveEventListener, never()).onMoveEvent(any());
     }
 
@@ -539,18 +558,18 @@
                         true,
                         ImmutableSet.of(),
                         /* shouldDisposeParentAnchor= */ true,
-                        perceptionLibrary,
-                        fakeExtensions,
-                        activitySpaceImpl,
-                        activitySpaceRoot,
-                        perceptionSpaceActivityPose,
-                        entityManager,
-                        panelShadowRenderer,
-                        fakeExecutor);
+                        mPerceptionLibrary,
+                        mFakeExtensions,
+                        mActivitySpaceImpl,
+                        mActivitySpaceRoot,
+                        mPerceptionSpaceActivityPose,
+                        mEntityManager,
+                        mPanelShadowRenderer,
+                        mFakeExecutor);
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor,
-                        fakeExtensions,
+                        mFakeExecutor,
+                        mFakeExtensions,
                         new Dimensions(0f, 0f, 0f),
                         new Dimensions(5f, 5f, 5f));
         assertThat(entity.addComponent(movableComponent)).isTrue();
@@ -571,16 +590,16 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         verify(moveEventListener).onMoveEvent(any());
 
         reformEvent.setType(ReformEvent.REFORM_TYPE_RESIZE);
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         verify(resizeEventListener, never()).onResizeEvent(any());
     }
 
@@ -590,7 +609,7 @@
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
         assertThat(entity.addComponent(resizableComponent)).isTrue();
         entity.removeComponent(resizableComponent);
@@ -603,7 +622,7 @@
         assertThat(entity).isNotNull();
         ResizableComponentImpl resizableComponent =
                 new ResizableComponentImpl(
-                        fakeExecutor, fakeExtensions, kMinDimensions, kMaxDimensions);
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
         assertThat(resizableComponent).isNotNull();
         assertThat(entity.addComponent(resizableComponent)).isTrue();
         entity.setAlpha(0.9f);
@@ -614,7 +633,7 @@
         resizableComponent.addResizeEventListener(directExecutor(), mockResizeEventListener);
         assertThat(node.getReformOptions().getEventCallback()).isNotNull();
         assertThat(node.getReformOptions().getEventExecutor()).isNotNull();
-        assertThat(entity.reformEventConsumerMap).isNotEmpty();
+        assertThat(entity.mReformEventConsumerMap).isNotEmpty();
 
         // Start the resize.
         FakeReformEvent reformEvent = new FakeReformEvent();
@@ -623,8 +642,8 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         ArgumentCaptor<ResizeEvent> resizeEventCaptor = ArgumentCaptor.forClass(ResizeEvent.class);
         verify(mockResizeEventListener).onResizeEvent(resizeEventCaptor.capture());
         ResizeEvent resizeEvent = resizeEventCaptor.getValue();
@@ -636,11 +655,164 @@
         node.getReformOptions()
                 .getEventExecutor()
                 .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
-        assertThat(fakeExecutor.hasNext()).isTrue();
-        fakeExecutor.runAll();
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
         verify(mockResizeEventListener, times(2)).onResizeEvent(resizeEventCaptor.capture());
         resizeEvent = resizeEventCaptor.getAllValues().get(2);
         assertThat(resizeEvent.resizeState).isEqualTo(ResizeEvent.RESIZE_STATE_END);
         assertThat(node.getAlpha()).isEqualTo(0.9f);
     }
+
+    @Test
+    public void resizableComponent_withAutoHideContentDisabled_doesNotHideEntityDuringResize() {
+        AndroidXrEntity entity = (AndroidXrEntity) createTestEntity();
+        assertThat(entity).isNotNull();
+        ResizableComponentImpl resizableComponent =
+                new ResizableComponentImpl(
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
+        assertThat(resizableComponent).isNotNull();
+        assertThat(entity.addComponent(resizableComponent)).isTrue();
+        entity.setAlpha(0.9f);
+        assertThat(entity.getAlpha()).isEqualTo(0.9f);
+        FakeNode node = (FakeNode) entity.getNode();
+        ResizeEventListener mockResizeEventListener = mock(ResizeEventListener.class);
+
+        resizableComponent.setAutoHideContent(false);
+        resizableComponent.addResizeEventListener(directExecutor(), mockResizeEventListener);
+        assertThat(node.getReformOptions().getEventCallback()).isNotNull();
+        assertThat(node.getReformOptions().getEventExecutor()).isNotNull();
+        assertThat(entity.mReformEventConsumerMap).isNotEmpty();
+
+        // Start the resize.
+        FakeReformEvent reformEvent = new FakeReformEvent();
+        reformEvent.setType(ReformEvent.REFORM_TYPE_RESIZE);
+        reformEvent.setState(ReformEvent.REFORM_STATE_START);
+        node.getReformOptions()
+                .getEventExecutor()
+                .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
+        ArgumentCaptor<ResizeEvent> resizeEventCaptor = ArgumentCaptor.forClass(ResizeEvent.class);
+        verify(mockResizeEventListener).onResizeEvent(resizeEventCaptor.capture());
+        ResizeEvent resizeEvent = resizeEventCaptor.getValue();
+        assertThat(resizeEvent.resizeState).isEqualTo(ResizeEvent.RESIZE_STATE_START);
+        assertThat(node.getAlpha()).isEqualTo(0.9f);
+
+        // End the resize.
+        reformEvent.setState(ReformEvent.REFORM_STATE_END);
+        node.getReformOptions()
+                .getEventExecutor()
+                .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
+        verify(mockResizeEventListener, times(2)).onResizeEvent(resizeEventCaptor.capture());
+        resizeEvent = resizeEventCaptor.getAllValues().get(2);
+        assertThat(resizeEvent.resizeState).isEqualTo(ResizeEvent.RESIZE_STATE_END);
+        assertThat(node.getAlpha()).isEqualTo(0.9f);
+    }
+
+    @Test
+    public void resizableComponent_updatesComponentSizeAfterResize() {
+        AndroidXrEntity entity = (AndroidXrEntity) createTestEntity();
+        assertThat(entity).isNotNull();
+        ResizableComponentImpl resizableComponent =
+                new ResizableComponentImpl(
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
+        assertThat(resizableComponent).isNotNull();
+        assertThat(entity.addComponent(resizableComponent)).isTrue();
+        FakeNode node = (FakeNode) entity.getNode();
+        resizableComponent.setSize(new Dimensions(1.0f, 2.0f, 3.0f));
+        assertThat(node.getReformOptions().getCurrentSize().x).isEqualTo(1.0f);
+        assertThat(node.getReformOptions().getCurrentSize().y).isEqualTo(2.0f);
+        assertThat(node.getReformOptions().getCurrentSize().z).isEqualTo(3.0f);
+        ResizeEventListener mockResizeEventListener = mock(ResizeEventListener.class);
+
+        resizableComponent.addResizeEventListener(directExecutor(), mockResizeEventListener);
+        assertThat(node.getReformOptions().getEventCallback()).isNotNull();
+        assertThat(node.getReformOptions().getEventExecutor()).isNotNull();
+        assertThat(entity.mReformEventConsumerMap).isNotEmpty();
+
+        // Start the resize.
+        FakeReformEvent reformEvent = new FakeReformEvent();
+        reformEvent.setType(ReformEvent.REFORM_TYPE_RESIZE);
+        reformEvent.setState(ReformEvent.REFORM_STATE_START);
+        node.getReformOptions()
+                .getEventExecutor()
+                .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
+        ArgumentCaptor<ResizeEvent> resizeEventCaptor = ArgumentCaptor.forClass(ResizeEvent.class);
+        verify(mockResizeEventListener).onResizeEvent(resizeEventCaptor.capture());
+        ResizeEvent resizeEvent = resizeEventCaptor.getValue();
+        assertThat(resizeEvent.resizeState).isEqualTo(ResizeEvent.RESIZE_STATE_START);
+
+        // End the resize.
+        reformEvent.setState(ReformEvent.REFORM_STATE_END);
+        reformEvent.setProposedSize(new Vec3(4.0f, 5.0f, 6.0f));
+        node.getReformOptions()
+                .getEventExecutor()
+                .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
+        verify(mockResizeEventListener, times(2)).onResizeEvent(resizeEventCaptor.capture());
+        resizeEvent = resizeEventCaptor.getAllValues().get(2);
+        assertThat(resizeEvent.resizeState).isEqualTo(ResizeEvent.RESIZE_STATE_END);
+        assertThat(node.getReformOptions().getCurrentSize().x).isEqualTo(4.0f);
+        assertThat(node.getReformOptions().getCurrentSize().y).isEqualTo(5.0f);
+        assertThat(node.getReformOptions().getCurrentSize().z).isEqualTo(6.0f);
+    }
+
+    @Test
+    public void
+            resizableComponent_withAutoUpdateSizeDisabled_doesNotUpdateComponentSizeAfterResize() {
+        AndroidXrEntity entity = (AndroidXrEntity) createTestEntity();
+        assertThat(entity).isNotNull();
+        ResizableComponentImpl resizableComponent =
+                new ResizableComponentImpl(
+                        mFakeExecutor, mFakeExtensions, kMinDimensions, kMaxDimensions);
+        assertThat(resizableComponent).isNotNull();
+        assertThat(entity.addComponent(resizableComponent)).isTrue();
+        FakeNode node = (FakeNode) entity.getNode();
+        resizableComponent.setAutoUpdateSize(false);
+        resizableComponent.setSize(new Dimensions(1.0f, 2.0f, 3.0f));
+        assertThat(node.getReformOptions().getCurrentSize().x).isEqualTo(1.0f);
+        assertThat(node.getReformOptions().getCurrentSize().y).isEqualTo(2.0f);
+        assertThat(node.getReformOptions().getCurrentSize().z).isEqualTo(3.0f);
+        ResizeEventListener mockResizeEventListener = mock(ResizeEventListener.class);
+
+        resizableComponent.addResizeEventListener(directExecutor(), mockResizeEventListener);
+        assertThat(node.getReformOptions().getEventCallback()).isNotNull();
+        assertThat(node.getReformOptions().getEventExecutor()).isNotNull();
+        assertThat(entity.mReformEventConsumerMap).isNotEmpty();
+
+        // Start the resize.
+        FakeReformEvent reformEvent = new FakeReformEvent();
+        reformEvent.setType(ReformEvent.REFORM_TYPE_RESIZE);
+        reformEvent.setState(ReformEvent.REFORM_STATE_START);
+        node.getReformOptions()
+                .getEventExecutor()
+                .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
+        ArgumentCaptor<ResizeEvent> resizeEventCaptor = ArgumentCaptor.forClass(ResizeEvent.class);
+        verify(mockResizeEventListener).onResizeEvent(resizeEventCaptor.capture());
+        ResizeEvent resizeEvent = resizeEventCaptor.getValue();
+        assertThat(resizeEvent.resizeState).isEqualTo(ResizeEvent.RESIZE_STATE_START);
+
+        // End the resize.
+        reformEvent.setState(ReformEvent.REFORM_STATE_END);
+        reformEvent.setProposedSize(new Vec3(4.0f, 5.0f, 6.0f));
+        node.getReformOptions()
+                .getEventExecutor()
+                .execute(() -> node.getReformOptions().getEventCallback().accept(reformEvent));
+        assertThat(mFakeExecutor.hasNext()).isTrue();
+        mFakeExecutor.runAll();
+        verify(mockResizeEventListener, times(2)).onResizeEvent(resizeEventCaptor.capture());
+        resizeEvent = resizeEventCaptor.getAllValues().get(2);
+        assertThat(resizeEvent.resizeState).isEqualTo(ResizeEvent.RESIZE_STATE_END);
+        // Reform size should be unchanged.
+        assertThat(node.getReformOptions().getCurrentSize().x).isEqualTo(1.0f);
+        assertThat(node.getReformOptions().getCurrentSize().y).isEqualTo(2.0f);
+        assertThat(node.getReformOptions().getCurrentSize().z).isEqualTo(3.0f);
+    }
 }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/SoundPoolExtensionsWrapperImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/SoundPoolExtensionsWrapperImplTest.java
index 03ca1ab..c382ee6 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/SoundPoolExtensionsWrapperImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/SoundPoolExtensionsWrapperImplTest.java
@@ -45,15 +45,15 @@
     private static final int TEST_LOOP = 0;
     private static final float TEST_RATE = 0F;
 
-    FakeXrExtensions fakeXrExtensions;
-    FakeSpatialAudioExtensions fakeSpatialAudioExtensions;
-    FakeSoundPoolExtensions fakeSoundPoolExtensions;
+    FakeXrExtensions mFakeXrExtensions;
+    FakeSpatialAudioExtensions mFakeSpatialAudioExtensions;
+    FakeSoundPoolExtensions mFakeSoundPoolExtensions;
 
     @Before
     public void setUp() {
-        fakeXrExtensions = new FakeXrExtensions();
-        fakeSpatialAudioExtensions = fakeXrExtensions.fakeSpatialAudioExtensions;
-        fakeSoundPoolExtensions = fakeSpatialAudioExtensions.soundPoolExtensions;
+        mFakeXrExtensions = new FakeXrExtensions();
+        mFakeSpatialAudioExtensions = mFakeXrExtensions.fakeSpatialAudioExtensions;
+        mFakeSoundPoolExtensions = mFakeSpatialAudioExtensions.soundPoolExtensions;
     }
 
     @Test
@@ -68,9 +68,9 @@
 
         SoundPool soundPool = new SoundPool.Builder().build();
 
-        fakeSoundPoolExtensions.setPlayAsPointSourceResult(expected);
+        mFakeSoundPoolExtensions.setPlayAsPointSourceResult(expected);
         SoundPoolExtensionsWrapper wrapper =
-                new SoundPoolExtensionsWrapperImpl(fakeSoundPoolExtensions);
+                new SoundPoolExtensionsWrapperImpl(mFakeSoundPoolExtensions);
         int actual =
                 wrapper.play(
                         soundPool,
@@ -90,9 +90,9 @@
 
         SoundPool soundPool = new SoundPool.Builder().build();
 
-        fakeSoundPoolExtensions.setPlayAsSoundFieldResult(expected);
+        mFakeSoundPoolExtensions.setPlayAsSoundFieldResult(expected);
         SoundPoolExtensionsWrapper wrapper =
-                new SoundPoolExtensionsWrapperImpl(fakeSoundPoolExtensions);
+                new SoundPoolExtensionsWrapperImpl(mFakeSoundPoolExtensions);
         JxrPlatformAdapter.SoundFieldAttributes attributes =
                 new JxrPlatformAdapter.SoundFieldAttributes(
                         JxrPlatformAdapter.SpatializerConstants.AMBISONICS_ORDER_THIRD_ORDER);
@@ -115,9 +115,9 @@
         int expected = SpatializerConstants.SOURCE_TYPE_SOUND_FIELD;
         SoundPool soundPool = new SoundPool.Builder().build();
 
-        fakeSoundPoolExtensions.setSourceType(expected);
+        mFakeSoundPoolExtensions.setSourceType(expected);
         SoundPoolExtensionsWrapper wrapper =
-                new SoundPoolExtensionsWrapperImpl(fakeSoundPoolExtensions);
+                new SoundPoolExtensionsWrapperImpl(mFakeSoundPoolExtensions);
         int actualSourceType = wrapper.getSpatialSourceType(soundPool, /* streamId= */ 0);
         assertThat(actualSourceType).isEqualTo(SpatializerConstants.SOURCE_TYPE_SOUND_FIELD);
     }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/SpatialEnvironmentImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/SpatialEnvironmentImplTest.java
index eb2c039..412118a 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/SpatialEnvironmentImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/SpatialEnvironmentImplTest.java
@@ -67,57 +67,57 @@
 @SuppressWarnings({"deprecation", "UnnecessarilyFullyQualified"}) // TODO(b/373435470): Remove
 public final class SpatialEnvironmentImplTest {
     private static final int SUBSPACE_ID = 5;
-    private final FakeImpressApi fakeImpressApi = new FakeImpressApi();
-    private ActivityController<Activity> activityController;
-    private Activity activity;
-    private FakeXrExtensions fakeExtensions = null;
-    private FakeNode subspaceNode;
-    private SubspaceNode expectedSubspace;
-    private SpatialEnvironmentImpl environment = null;
-    private SplitEngineSubspaceManager splitEngineSubspaceManager;
+    private final FakeImpressApi mFakeImpressApi = new FakeImpressApi();
+    private ActivityController<Activity> mActivityController;
+    private Activity mActivity;
+    private FakeXrExtensions mFakeExtensions = null;
+    private FakeNode mSubspaceNode;
+    private SubspaceNode mExpectedSubspace;
+    private SpatialEnvironmentImpl mEnvironment = null;
+    private SplitEngineSubspaceManager mSplitEngineSubspaceManager;
 
     @Before
     public void setUp() {
-        activityController = Robolectric.buildActivity(Activity.class);
-        activity = activityController.create().start().get();
+        mActivityController = Robolectric.buildActivity(Activity.class);
+        mActivity = mActivityController.create().start().get();
         // Reset our state.
-        fakeExtensions = new FakeXrExtensions();
-        FakeNode fakeSceneRootNode = (FakeNode) fakeExtensions.createNode();
-        subspaceNode = (FakeNode) fakeExtensions.createNode();
-        expectedSubspace = new SubspaceNode(SUBSPACE_ID, subspaceNode);
+        mFakeExtensions = new FakeXrExtensions();
+        FakeNode fakeSceneRootNode = (FakeNode) mFakeExtensions.createNode();
+        mSubspaceNode = (FakeNode) mFakeExtensions.createNode();
+        mExpectedSubspace = new SubspaceNode(SUBSPACE_ID, mSubspaceNode);
 
-        splitEngineSubspaceManager = Mockito.mock(SplitEngineSubspaceManager.class);
+        mSplitEngineSubspaceManager = Mockito.mock(SplitEngineSubspaceManager.class);
 
-        environment =
+        mEnvironment =
                 new SpatialEnvironmentImpl(
-                        activity,
-                        fakeExtensions,
+                        mActivity,
+                        mFakeExtensions,
                         fakeSceneRootNode,
                         this::getSpatialState,
                         /* useSplitEngine= */ false);
-        environment.onSplitEngineReady(splitEngineSubspaceManager, fakeImpressApi);
+        mEnvironment.onSplitEngineReady(mSplitEngineSubspaceManager, mFakeImpressApi);
     }
 
     private void setupSplitEngineEnvironmentImpl() {
-        FakeNode fakeSceneRootNode = (FakeNode) fakeExtensions.createNode();
+        FakeNode fakeSceneRootNode = (FakeNode) mFakeExtensions.createNode();
 
-        when(splitEngineSubspaceManager.createSubspace(anyString(), anyInt()))
-                .thenReturn(expectedSubspace);
+        when(mSplitEngineSubspaceManager.createSubspace(anyString(), anyInt()))
+                .thenReturn(mExpectedSubspace);
 
-        environment =
+        mEnvironment =
                 new SpatialEnvironmentImpl(
-                        activity,
-                        fakeExtensions,
+                        mActivity,
+                        mFakeExtensions,
                         fakeSceneRootNode,
                         this::getSpatialState,
                         /* useSplitEngine= */ true);
-        environment.onSplitEngineReady(splitEngineSubspaceManager, fakeImpressApi);
+        mEnvironment.onSplitEngineReady(mSplitEngineSubspaceManager, mFakeImpressApi);
     }
 
     @SuppressWarnings({"FutureReturnValueIgnored", "AndroidJdkLibsChecker"})
     private androidx.xr.extensions.asset.EnvironmentToken fakeLoadEnvironment(String name) {
         try {
-            return fakeExtensions.loadEnvironment(null, 0, 0, name).get();
+            return mFakeExtensions.loadEnvironment(null, 0, 0, name).get();
         } catch (Exception e) {
             if (e instanceof InterruptedException) {
                 Thread.currentThread().interrupt();
@@ -129,7 +129,7 @@
     @SuppressWarnings({"FutureReturnValueIgnored", "AndroidJdkLibsChecker"})
     private androidx.xr.extensions.asset.GltfModelToken fakeLoadGltfModel(String name) {
         try {
-            return fakeExtensions.loadGltfModel(null, 0, 0, name).get();
+            return mFakeExtensions.loadGltfModel(null, 0, 0, name).get();
         } catch (Exception e) {
             if (e instanceof InterruptedException) {
                 Thread.currentThread().interrupt();
@@ -141,7 +141,7 @@
     @SuppressWarnings({"FutureReturnValueIgnored", "AndroidJdkLibsChecker"})
     private long fakeLoadGltfModelSplitEngine(String name) {
         try {
-            return fakeImpressApi.loadGltfModel(name).get();
+            return mFakeImpressApi.loadGltfModel(name).get();
         } catch (Exception e) {
             if (e instanceof InterruptedException) {
                 Thread.currentThread().interrupt();
@@ -151,54 +151,54 @@
     }
 
     private SpatialState getSpatialState() {
-        return fakeExtensions.fakeSpatialState;
+        return mFakeExtensions.fakeSpatialState;
     }
 
     @Test
     public void setPassthroughOpacityPreference() {
-        environment.setPassthroughOpacityPreference(null);
-        assertThat(environment.getPassthroughOpacityPreference()).isNull();
+        mEnvironment.setPassthroughOpacityPreference(null);
+        assertThat(mEnvironment.getPassthroughOpacityPreference()).isNull();
 
-        environment.setPassthroughOpacityPreference(0.1f);
-        assertThat(environment.getPassthroughOpacityPreference()).isEqualTo(0.1f);
+        mEnvironment.setPassthroughOpacityPreference(0.1f);
+        assertThat(mEnvironment.getPassthroughOpacityPreference()).isEqualTo(0.1f);
     }
 
     @Test
     public void setPassthroughOpacityPreferenceNearOrUnderZero_getsZeroOpacity() {
         // Opacity values below 1% should be treated as zero.
-        environment.setPassthroughOpacityPreference(0.009f);
-        assertThat(environment.getPassthroughOpacityPreference()).isEqualTo(0.0f);
+        mEnvironment.setPassthroughOpacityPreference(0.009f);
+        assertThat(mEnvironment.getPassthroughOpacityPreference()).isEqualTo(0.0f);
 
-        environment.setPassthroughOpacityPreference(-0.1f);
-        assertThat(environment.getPassthroughOpacityPreference()).isEqualTo(0.0f);
+        mEnvironment.setPassthroughOpacityPreference(-0.1f);
+        assertThat(mEnvironment.getPassthroughOpacityPreference()).isEqualTo(0.0f);
     }
 
     @Test
     public void setPassthroughOpacityPreferenceNearOrOverOne_getsFullOpacity() {
         // Opacity values above 99% should be treated as full opacity.
-        environment.setPassthroughOpacityPreference(0.991f);
-        assertThat(environment.getPassthroughOpacityPreference()).isEqualTo(1.0f);
+        mEnvironment.setPassthroughOpacityPreference(0.991f);
+        assertThat(mEnvironment.getPassthroughOpacityPreference()).isEqualTo(1.0f);
 
-        environment.setPassthroughOpacityPreference(1.1f);
-        assertThat(environment.getPassthroughOpacityPreference()).isEqualTo(1.0f);
+        mEnvironment.setPassthroughOpacityPreference(1.1f);
+        assertThat(mEnvironment.getPassthroughOpacityPreference()).isEqualTo(1.0f);
     }
 
     @Test
     public void setPassthroughOpacityPreference_returnsAccordingToSpatialCapabilities() {
         // Change should be applied if the spatial capabilities allow it, otherwise should be
         // pending.
-        fakeExtensions.fakeSpatialState.setAllSpatialCapabilities(true);
-        assertThat(environment.setPassthroughOpacityPreference(0.5f))
+        mFakeExtensions.fakeSpatialState.setAllSpatialCapabilities(true);
+        assertThat(mEnvironment.setPassthroughOpacityPreference(0.5f))
                 .isEqualTo(SetPassthroughOpacityPreferenceResult.CHANGE_APPLIED);
 
-        fakeExtensions.fakeSpatialState.setAllSpatialCapabilities(false);
-        assertThat(environment.setPassthroughOpacityPreference(0.6f))
+        mFakeExtensions.fakeSpatialState.setAllSpatialCapabilities(false);
+        assertThat(mEnvironment.setPassthroughOpacityPreference(0.6f))
                 .isEqualTo(SetPassthroughOpacityPreferenceResult.CHANGE_PENDING);
     }
 
     @Test
     public void getCurrentPassthroughOpacity_returnsZeroInitially() {
-        assertThat(environment.getCurrentPassthroughOpacity()).isEqualTo(0.0f);
+        assertThat(mEnvironment.getCurrentPassthroughOpacity()).isEqualTo(0.0f);
     }
 
     @Test
@@ -208,15 +208,15 @@
         @SuppressWarnings(value = "unchecked")
         Consumer<Float> listener2 = (Consumer<Float>) mock(Consumer.class);
 
-        environment.addOnPassthroughOpacityChangedListener(listener1);
-        environment.addOnPassthroughOpacityChangedListener(listener2);
+        mEnvironment.addOnPassthroughOpacityChangedListener(listener1);
+        mEnvironment.addOnPassthroughOpacityChangedListener(listener2);
 
-        environment.firePassthroughOpacityChangedEvent(0.5f);
+        mEnvironment.firePassthroughOpacityChangedEvent(0.5f);
         verify(listener1).accept(0.5f);
         verify(listener2).accept(0.5f);
 
-        environment.removeOnPassthroughOpacityChangedListener(listener1);
-        environment.firePassthroughOpacityChangedEvent(0.0f);
+        mEnvironment.removeOnPassthroughOpacityChangedListener(listener1);
+        mEnvironment.firePassthroughOpacityChangedEvent(0.0f);
         verify(listener1)
                 .accept(any()); // Verify the removed listener was called exactly once total
         verify(listener2).accept(0.0f); // Verify the active listener was called again with false
@@ -225,22 +225,22 @@
     @Test
     public void getSpatialEnvironmentPreference_returnsSetSpatialEnvironmentPreference() {
         SpatialEnvironmentPreference preference = mock(SpatialEnvironmentPreference.class);
-        environment.setSpatialEnvironmentPreference(preference);
-        assertThat(environment.getSpatialEnvironmentPreference()).isEqualTo(preference);
+        mEnvironment.setSpatialEnvironmentPreference(preference);
+        assertThat(mEnvironment.getSpatialEnvironmentPreference()).isEqualTo(preference);
     }
 
     @Test
     public void setSpatialEnvironmentPreference_returnsAppliedWhenCapable() {
         // Change should be applied if the spatial capabilities allow it, otherwise should be
         // pending.
-        fakeExtensions.fakeSpatialState.setAllSpatialCapabilities(true);
+        mFakeExtensions.fakeSpatialState.setAllSpatialCapabilities(true);
         SpatialEnvironmentPreference preference = mock(SpatialEnvironmentPreference.class);
-        assertThat(environment.setSpatialEnvironmentPreference(preference))
+        assertThat(mEnvironment.setSpatialEnvironmentPreference(preference))
                 .isEqualTo(SetSpatialEnvironmentPreferenceResult.CHANGE_APPLIED);
 
-        fakeExtensions.fakeSpatialState.setAllSpatialCapabilities(false);
+        mFakeExtensions.fakeSpatialState.setAllSpatialCapabilities(false);
         preference = mock(SpatialEnvironmentPreference.class);
-        assertThat(environment.setSpatialEnvironmentPreference(preference))
+        assertThat(mEnvironment.setSpatialEnvironmentPreference(preference))
                 .isEqualTo(SetSpatialEnvironmentPreferenceResult.CHANGE_PENDING);
     }
 
@@ -250,12 +250,12 @@
         androidx.xr.extensions.asset.GltfModelToken gltf = fakeLoadGltfModel("fakeGltfModel");
 
         // Ensure that an environment is set.
-        environment.setSpatialEnvironmentPreference(
+        mEnvironment.setSpatialEnvironmentPreference(
                 new SpatialEnvironmentPreference(
                         new ExrImageResourceImpl(exr), new GltfModelResourceImpl(gltf)));
 
-        FakeNode skyboxNode = fakeExtensions.testGetNodeWithEnvironmentToken(exr);
-        FakeNode geometryNode = fakeExtensions.testGetNodeWithGltfToken(gltf);
+        FakeNode skyboxNode = mFakeExtensions.testGetNodeWithEnvironmentToken(exr);
+        FakeNode geometryNode = mFakeExtensions.testGetNodeWithGltfToken(gltf);
 
         assertThat(skyboxNode).isNotNull();
         assertThat(geometryNode).isNotNull();
@@ -264,11 +264,11 @@
         assertThat(geometryNode.getParent()).isNotNull();
 
         // Ensure environment is removed
-        environment.setSpatialEnvironmentPreference(null);
+        mEnvironment.setSpatialEnvironmentPreference(null);
 
         assertThat(skyboxNode.getParent()).isNull();
         assertThat(geometryNode.getParent()).isNull();
-        assertThat(fakeExtensions.getFakeEnvironmentNode()).isNull();
+        assertThat(mFakeExtensions.getFakeEnvironmentNode()).isNull();
     }
 
     @Test
@@ -279,26 +279,26 @@
         long gltf = fakeLoadGltfModelSplitEngine("fakeGltfModel");
 
         // Ensure that an environment is set.
-        environment.setSpatialEnvironmentPreference(
+        mEnvironment.setSpatialEnvironmentPreference(
                 new SpatialEnvironmentPreference(
                         new ExrImageResourceImpl(exr), new GltfModelResourceImplSplitEngine(gltf)));
 
-        FakeNode skyboxNode = fakeExtensions.testGetNodeWithEnvironmentToken(exr);
-        List<Integer> geometryNodes = fakeImpressApi.getImpressNodesForToken(gltf);
+        FakeNode skyboxNode = mFakeExtensions.testGetNodeWithEnvironmentToken(exr);
+        List<Integer> geometryNodes = mFakeImpressApi.getImpressNodesForToken(gltf);
 
         assertThat(skyboxNode).isNotNull();
         assertThat(geometryNodes).isNotEmpty();
 
         assertThat(skyboxNode.getParent()).isNotNull();
-        assertThat(fakeImpressApi.impressNodeHasParent(geometryNodes.get(0))).isTrue();
+        assertThat(mFakeImpressApi.impressNodeHasParent(geometryNodes.get(0))).isTrue();
 
         // Ensure environment is removed
-        environment.setSpatialEnvironmentPreference(null);
+        mEnvironment.setSpatialEnvironmentPreference(null);
 
         assertThat(skyboxNode.getParent()).isNull();
         // TODO: b/354711945 - Uncomment when we can test the SetGeometrySplitEngine(null) path.
         // assertThat(fakeImpressApi.impressNodeHasParent(geometryNodes.get(0))).isFalse();
-        assertThat(fakeExtensions.getFakeEnvironmentNode()).isNull();
+        assertThat(mFakeExtensions.getFakeEnvironmentNode()).isNull();
     }
 
     @Test
@@ -308,12 +308,12 @@
         androidx.xr.extensions.asset.GltfModelToken gltf = fakeLoadGltfModel("fakeGltfModel");
 
         // Ensure that an environment is set.
-        environment.setSpatialEnvironmentPreference(
+        mEnvironment.setSpatialEnvironmentPreference(
                 new SpatialEnvironmentPreference(
                         new ExrImageResourceImpl(exr), new GltfModelResourceImpl(gltf)));
 
-        FakeNode skyboxNode = fakeExtensions.testGetNodeWithEnvironmentToken(exr);
-        FakeNode geometryNode = fakeExtensions.testGetNodeWithGltfToken(gltf);
+        FakeNode skyboxNode = mFakeExtensions.testGetNodeWithEnvironmentToken(exr);
+        FakeNode geometryNode = mFakeExtensions.testGetNodeWithGltfToken(gltf);
 
         assertThat(skyboxNode).isNotNull();
         assertThat(geometryNode).isNotNull();
@@ -322,7 +322,7 @@
         assertThat(geometryNode.getParent()).isNotNull();
 
         // Ensure environment is not removed if both skybox and geometry are updated to null.
-        environment.setSpatialEnvironmentPreference(new SpatialEnvironmentPreference(null, null));
+        mEnvironment.setSpatialEnvironmentPreference(new SpatialEnvironmentPreference(null, null));
 
         assertThat(skyboxNode.getParent()).isNull();
         assertThat(geometryNode.getParent()).isNull();
@@ -333,7 +333,7 @@
         // This change isn't relevant for end users but it confirms the environment implementation
         // is working as designed.
         // assertThat(fakeExtensions.getFakeEnvironmentNode()).isNotNull();
-        assertThat(fakeExtensions.getFakeEnvironmentNode()).isNull();
+        assertThat(mFakeExtensions.getFakeEnvironmentNode()).isNull();
     }
 
     @Test
@@ -344,33 +344,32 @@
         long gltf = fakeLoadGltfModelSplitEngine("fakeGltfModel");
 
         // Ensure that an environment is set.
-        environment.setSpatialEnvironmentPreference(
+        mEnvironment.setSpatialEnvironmentPreference(
                 new SpatialEnvironmentPreference(
                         new ExrImageResourceImpl(exr), new GltfModelResourceImplSplitEngine(gltf)));
 
-        FakeNode skyboxNode = fakeExtensions.testGetNodeWithEnvironmentToken(exr);
-        List<Integer> geometryNodes = fakeImpressApi.getImpressNodesForToken(gltf);
+        FakeNode skyboxNode = mFakeExtensions.testGetNodeWithEnvironmentToken(exr);
+        List<Integer> geometryNodes = mFakeImpressApi.getImpressNodesForToken(gltf);
 
         assertThat(skyboxNode).isNotNull();
         assertThat(geometryNodes).isNotEmpty();
 
         assertThat(skyboxNode.getParent()).isNotNull();
-        assertThat(fakeImpressApi.impressNodeHasParent(geometryNodes.get(0))).isTrue();
+        assertThat(mFakeImpressApi.impressNodeHasParent(geometryNodes.get(0))).isTrue();
 
         // Ensure environment is not removed if both skybox and geometry are updated to null.
-        environment.setSpatialEnvironmentPreference(new SpatialEnvironmentPreference(null, null));
+        mEnvironment.setSpatialEnvironmentPreference(new SpatialEnvironmentPreference(null, null));
 
         assertThat(skyboxNode.getParent()).isNull();
         // TODO: b/354711945 - Uncomment when we can test the SetGeometrySplitEngine(null) path.
         // assertThat(fakeImpressApi.impressNodeHasParent(geometryNodes.get(0))).isFalse();
 
-        // TODO: b/371221872 - When the behavior is changed to set the black skybox, the fake env
-        // node
-        // will no longer be null and the commented out line should replace the uncommented line.
-        // This change isn't relevant for end users but it confirms the environment implementation
-        // is working as designed.
+        // TODO: b/371221872 - When the behavior is changed to set the black skybox,
+        // the fake env nodewill no longer be null and the commented out line should replace
+        // the uncommented line. This change isn't relevant for end users but it
+        // confirms the environment implementation is working as designed.
         // assertThat(fakeExtensions.getFakeEnvironmentNode()).isNotNull();
-        assertThat(fakeExtensions.getFakeEnvironmentNode()).isNull();
+        assertThat(mFakeExtensions.getFakeEnvironmentNode()).isNull();
     }
 
     @Test
@@ -382,20 +381,20 @@
         androidx.xr.extensions.asset.GltfModelToken newGltf = fakeLoadGltfModel("newFakeGltfModel");
 
         // Ensure that an environment is set a first time.
-        environment.setSpatialEnvironmentPreference(
+        mEnvironment.setSpatialEnvironmentPreference(
                 new SpatialEnvironmentPreference(
                         new ExrImageResourceImpl(exr), new GltfModelResourceImpl(gltf)));
 
-        FakeNode skyboxNode = fakeExtensions.testGetNodeWithEnvironmentToken(exr);
-        FakeNode geometryNode = fakeExtensions.testGetNodeWithGltfToken(gltf);
+        FakeNode skyboxNode = mFakeExtensions.testGetNodeWithEnvironmentToken(exr);
+        FakeNode geometryNode = mFakeExtensions.testGetNodeWithGltfToken(gltf);
 
         // Ensure that an environment is set a second time.
-        environment.setSpatialEnvironmentPreference(
+        mEnvironment.setSpatialEnvironmentPreference(
                 new SpatialEnvironmentPreference(
                         new ExrImageResourceImpl(newExr), new GltfModelResourceImpl(newGltf)));
 
-        FakeNode newSkyboxNode = fakeExtensions.testGetNodeWithEnvironmentToken(newExr);
-        FakeNode newGeometryNode = fakeExtensions.testGetNodeWithGltfToken(newGltf);
+        FakeNode newSkyboxNode = mFakeExtensions.testGetNodeWithEnvironmentToken(newExr);
+        FakeNode newGeometryNode = mFakeExtensions.testGetNodeWithGltfToken(newGltf);
 
         // None of the nodes should be null.
         assertThat(skyboxNode).isNotNull();
@@ -418,7 +417,7 @@
         assertThat(newGeometryNode.getName()).isEqualTo(SpatialEnvironmentImpl.GEOMETRY_NODE_NAME);
 
         // The environment node should still be attached.
-        assertThat(fakeExtensions.getFakeEnvironmentNode()).isNotNull();
+        assertThat(mFakeExtensions.getFakeEnvironmentNode()).isNotNull();
     }
 
     @Test
@@ -432,21 +431,21 @@
         long newGltf = fakeLoadGltfModelSplitEngine("newFakeGltfModel");
 
         // Ensure that an environment is set a first time.
-        environment.setSpatialEnvironmentPreference(
+        mEnvironment.setSpatialEnvironmentPreference(
                 new SpatialEnvironmentPreference(
                         new ExrImageResourceImpl(exr), new GltfModelResourceImplSplitEngine(gltf)));
 
-        FakeNode skyboxNode = fakeExtensions.testGetNodeWithEnvironmentToken(exr);
-        List<Integer> geometryNodes = fakeImpressApi.getImpressNodesForToken(gltf);
+        FakeNode skyboxNode = mFakeExtensions.testGetNodeWithEnvironmentToken(exr);
+        List<Integer> geometryNodes = mFakeImpressApi.getImpressNodesForToken(gltf);
 
         // Ensure that an environment is set a second time.
-        environment.setSpatialEnvironmentPreference(
+        mEnvironment.setSpatialEnvironmentPreference(
                 new SpatialEnvironmentPreference(
                         new ExrImageResourceImpl(newExr),
                         new GltfModelResourceImplSplitEngine(newGltf)));
 
-        FakeNode newSkyboxNode = fakeExtensions.testGetNodeWithEnvironmentToken(newExr);
-        List<Integer> newGeometryNodes = fakeImpressApi.getImpressNodesForToken(newGltf);
+        FakeNode newSkyboxNode = mFakeExtensions.testGetNodeWithEnvironmentToken(newExr);
+        List<Integer> newGeometryNodes = mFakeImpressApi.getImpressNodesForToken(newGltf);
 
         // None of the nodes should be null.
         assertThat(skyboxNode).isNotNull();
@@ -459,7 +458,7 @@
         // TODO: b/354711945 - Uncomment when we can test the SetGeometrySplitEngine(null) path.
         // assertThat(fakeImpressApi.impressNodeHasParent(geometryNodes.get(0))).isFalse();
         assertThat(newSkyboxNode.getParent()).isNotNull();
-        assertThat(fakeImpressApi.impressNodeHasParent(newGeometryNodes.get(0))).isTrue();
+        assertThat(mFakeImpressApi.impressNodeHasParent(newGeometryNodes.get(0))).isTrue();
 
         // The resources should be different.
         assertThat(skyboxNode.getEnvironment()).isNotEqualTo(newSkyboxNode.getEnvironment());
@@ -468,12 +467,12 @@
         assertThat(geometryNodes.get(0)).isNotEqualTo(newGeometryNodes.get(0));
 
         // The environment node should still be attached.
-        assertThat(fakeExtensions.getFakeEnvironmentNode()).isNotNull();
+        assertThat(mFakeExtensions.getFakeEnvironmentNode()).isNotNull();
     }
 
     @Test
     public void isSpatialEnvironmentPreferenceActive_defaultsToFalse() {
-        assertThat(environment.isSpatialEnvironmentPreferenceActive()).isFalse();
+        assertThat(mEnvironment.isSpatialEnvironmentPreferenceActive()).isFalse();
     }
 
     @Test
@@ -483,15 +482,15 @@
         @SuppressWarnings(value = "unchecked")
         Consumer<Boolean> listener2 = (Consumer<Boolean>) mock(Consumer.class);
 
-        environment.addOnSpatialEnvironmentChangedListener(listener1);
-        environment.addOnSpatialEnvironmentChangedListener(listener2);
+        mEnvironment.addOnSpatialEnvironmentChangedListener(listener1);
+        mEnvironment.addOnSpatialEnvironmentChangedListener(listener2);
 
-        environment.fireOnSpatialEnvironmentChangedEvent(true);
+        mEnvironment.fireOnSpatialEnvironmentChangedEvent(true);
         verify(listener1).accept(true);
         verify(listener2).accept(true);
 
-        environment.removeOnSpatialEnvironmentChangedListener(listener1);
-        environment.fireOnSpatialEnvironmentChangedEvent(false);
+        mEnvironment.removeOnSpatialEnvironmentChangedListener(listener1);
+        mEnvironment.fireOnSpatialEnvironmentChangedEvent(false);
         verify(listener1)
                 .accept(any()); // Verify the removed listener was called exactly once total
         verify(listener2).accept(false); // Verify the active listener was called again with false
@@ -501,13 +500,13 @@
     public void dispose_clearsSpatialEnvironmentPreferenceListeners() {
         @SuppressWarnings(value = "unchecked")
         Consumer<Boolean> listener = (Consumer<Boolean>) mock(Consumer.class);
-        environment.addOnSpatialEnvironmentChangedListener(listener);
+        mEnvironment.addOnSpatialEnvironmentChangedListener(listener);
 
-        environment.fireOnSpatialEnvironmentChangedEvent(true);
+        mEnvironment.fireOnSpatialEnvironmentChangedEvent(true);
         verify(listener).accept(true);
 
-        environment.dispose();
-        environment.fireOnSpatialEnvironmentChangedEvent(false);
+        mEnvironment.dispose();
+        mEnvironment.fireOnSpatialEnvironmentChangedEvent(false);
         verify(listener, never()).accept(false);
     }
 
@@ -515,14 +514,14 @@
     public void dispose_clearsPassthroughOpacityPreferenceListeners() {
         @SuppressWarnings(value = "unchecked")
         Consumer<Float> listener = (Consumer<Float>) mock(Consumer.class);
-        environment.addOnPassthroughOpacityChangedListener(listener);
+        mEnvironment.addOnPassthroughOpacityChangedListener(listener);
 
-        environment.firePassthroughOpacityChangedEvent(1.0f);
+        mEnvironment.firePassthroughOpacityChangedEvent(1.0f);
         verify(listener).accept(1.0f);
 
         // Ensure the listener is called exactly once, even if the event is fired after dispose.
-        environment.dispose();
-        environment.firePassthroughOpacityChangedEvent(0.5f);
+        mEnvironment.dispose();
+        mEnvironment.firePassthroughOpacityChangedEvent(0.5f);
         verify(listener).accept(any());
     }
 
@@ -536,15 +535,15 @@
                 new FakeEnvironmentVisibilityState(EnvironmentVisibilityState.APP_VISIBLE));
         spatialState.setPassthroughVisibility(
                 new FakePassthroughVisibilityState(PassthroughVisibilityState.APP, 0.5f));
-        environment.setSpatialState(spatialState);
+        mEnvironment.setSpatialState(spatialState);
 
-        environment.setSpatialEnvironmentPreference(
+        mEnvironment.setSpatialEnvironmentPreference(
                 new SpatialEnvironmentPreference(
                         new ExrImageResourceImpl(exr), new GltfModelResourceImpl(gltf)));
-        environment.setPassthroughOpacityPreference(0.5f);
+        mEnvironment.setPassthroughOpacityPreference(0.5f);
 
-        FakeNode skyboxNode = fakeExtensions.testGetNodeWithEnvironmentToken(exr);
-        FakeNode geometryNode = fakeExtensions.testGetNodeWithGltfToken(gltf);
+        FakeNode skyboxNode = mFakeExtensions.testGetNodeWithEnvironmentToken(exr);
+        FakeNode geometryNode = mFakeExtensions.testGetNodeWithGltfToken(gltf);
 
         assertThat(skyboxNode).isNotNull();
         assertThat(geometryNode).isNotNull();
@@ -552,19 +551,19 @@
         assertThat(skyboxNode.getParent()).isNotNull();
         assertThat(geometryNode.getParent()).isNotNull();
 
-        assertThat(environment.getSpatialEnvironmentPreference()).isNotNull();
-        assertThat(environment.isSpatialEnvironmentPreferenceActive()).isTrue();
+        assertThat(mEnvironment.getSpatialEnvironmentPreference()).isNotNull();
+        assertThat(mEnvironment.isSpatialEnvironmentPreferenceActive()).isTrue();
 
-        assertThat(environment.getPassthroughOpacityPreference()).isNotNull();
-        assertThat(environment.getCurrentPassthroughOpacity()).isEqualTo(0.5f);
+        assertThat(mEnvironment.getPassthroughOpacityPreference()).isNotNull();
+        assertThat(mEnvironment.getCurrentPassthroughOpacity()).isEqualTo(0.5f);
 
-        environment.dispose();
+        mEnvironment.dispose();
         assertThat(skyboxNode.getParent()).isNull();
         assertThat(geometryNode.getParent()).isNull();
-        assertThat(fakeExtensions.getFakeEnvironmentNode()).isNull();
-        assertThat(environment.getSpatialEnvironmentPreference()).isNull();
-        assertThat(environment.isSpatialEnvironmentPreferenceActive()).isFalse();
-        assertThat(environment.getPassthroughOpacityPreference()).isNull();
-        assertThat(environment.getCurrentPassthroughOpacity()).isEqualTo(0.0f);
+        assertThat(mFakeExtensions.getFakeEnvironmentNode()).isNull();
+        assertThat(mEnvironment.getSpatialEnvironmentPreference()).isNull();
+        assertThat(mEnvironment.isSpatialEnvironmentPreferenceActive()).isFalse();
+        assertThat(mEnvironment.getPassthroughOpacityPreference()).isNull();
+        assertThat(mEnvironment.getCurrentPassthroughOpacity()).isEqualTo(0.0f);
     }
 }
diff --git a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/SystemSpaceEntityImplTest.java b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/SystemSpaceEntityImplTest.java
index 82ce0d4..10df5fe 100644
--- a/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/SystemSpaceEntityImplTest.java
+++ b/xr/scenecore/scenecore/src/test/java/androidx/xr/scenecore/impl/SystemSpaceEntityImplTest.java
@@ -64,14 +64,14 @@
         FakeNode node = (FakeNode) systemSpaceEntity.getNode();
         assertThat(node.getTransformListener()).isNotNull();
         assertThat(node.getTransformExecutor()).isEqualTo(fakeExecutor);
-        assertThat(systemSpaceEntity.nodeTransformCloseable).isNotNull();
+        assertThat(systemSpaceEntity.mNodeTransformCloseable).isNotNull();
     }
 
     @Test
     public void dispose_closesNodeTransformSubscription() {
         SystemSpaceEntityImpl systemSpaceEntity = getSystemSpaceEntityImpl();
         FakeCloseable nodeTransformCloseable =
-                (FakeCloseable) systemSpaceEntity.nodeTransformCloseable;
+                (FakeCloseable) systemSpaceEntity.mNodeTransformCloseable;
         assertThat(nodeTransformCloseable.isClosed()).isFalse();
 
         systemSpaceEntity.dispose();