Merge "Consider views during database bundle schema equality check." into androidx-main
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/ToolbarMenuHostTest.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/ToolbarMenuHostTest.kt
index 0cd857e..8acaaa7 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/ToolbarMenuHostTest.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/ToolbarMenuHostTest.kt
@@ -33,6 +33,9 @@
 import androidx.testutils.PollingCheck
 import androidx.testutils.withActivity
 import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -93,6 +96,7 @@
     fun providedMenuItemSelected() {
         with(ActivityScenario.launch(ToolbarTestActivity::class.java)) {
             var itemSelectedId: Int? = null
+            val itemSelectedCountDownLatch = CountDownLatch(1)
             val toolbar: Toolbar = withActivity {
                 findViewById(androidx.appcompat.test.R.id.toolbar)
             }
@@ -107,6 +111,7 @@
                         return when (menuItem.itemId) {
                             R.id.item1, R.id.item2 -> {
                                 itemSelectedId = menuItem.itemId
+                                itemSelectedCountDownLatch.countDown()
                                 true
                             }
                             else -> false
@@ -118,6 +123,10 @@
             toolbar.showOverflowMenu()
             PollingCheck.waitFor { toolbar.isOverflowMenuShowing }
             onView(withText("Item1")).perform(click())
+
+            assertWithMessage("Failed to select MenuItem")
+                .that(itemSelectedCountDownLatch.await(1000, TimeUnit.MILLISECONDS))
+                .isTrue()
             assertThat(itemSelectedId).isEqualTo(R.id.item1)
 
             withActivity {
@@ -130,6 +139,7 @@
                         return when (menuItem.itemId) {
                             R.id.item3, R.id.item4 -> {
                                 itemSelectedId = menuItem.itemId
+                                itemSelectedCountDownLatch.countDown()
                                 true
                             }
                             else -> false
@@ -141,6 +151,10 @@
             toolbar.showOverflowMenu()
             PollingCheck.waitFor { toolbar.isOverflowMenuShowing }
             onView(withText("Item3")).perform(click())
+
+            assertWithMessage("Failed to select MenuItem")
+                .that(itemSelectedCountDownLatch.await(1000, TimeUnit.MILLISECONDS))
+                .isTrue()
             assertThat(itemSelectedId).isEqualTo(R.id.item3)
         }
     }
diff --git a/biometric/biometric/src/androidTest/java/androidx/biometric/BiometricPromptTest.java b/biometric/biometric/src/androidTest/java/androidx/biometric/BiometricPromptTest.java
index e4d454d..f211126 100644
--- a/biometric/biometric/src/androidTest/java/androidx/biometric/BiometricPromptTest.java
+++ b/biometric/biometric/src/androidTest/java/androidx/biometric/BiometricPromptTest.java
@@ -35,6 +35,7 @@
 import com.google.common.util.concurrent.MoreExecutors;
 
 import org.junit.After;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -47,8 +48,13 @@
         UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).pressHome();
     }
 
+    @Test // prevents test runner from failing since all tests are ignored
+    @SdkSuppress(minSdkVersion = 18)
+    public void dummy() {}
+
     @Test
     @SdkSuppress(minSdkVersion = 18)
+    @Ignore("TODO(b/225187683): fails in postsubmit")
     public void testViewModel_inActivity() {
         try (ActivityScenario<TestActivity> scenario =
                      ActivityScenario.launch(TestActivity.class)) {
@@ -73,6 +79,7 @@
 
     @Test
     @SdkSuppress(minSdkVersion = 18)
+    @Ignore("TODO(b/225187683): fails in postsubmit")
     public void testViewModel_inFragment() {
         try (FragmentScenario<TestFragment> scenario =
                      FragmentScenario.launchInContainer(TestFragment.class)) {
diff --git a/buildSrc-tests/src/test/kotlin/androidx/build/libabigail/symbolfiles/SymbolFileParserTest.kt b/buildSrc-tests/src/test/kotlin/androidx/build/libabigail/symbolfiles/SymbolFileParserTest.kt
deleted file mode 100644
index 32d8497..0000000
--- a/buildSrc-tests/src/test/kotlin/androidx/build/libabigail/symbolfiles/SymbolFileParserTest.kt
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.build.libabigail.symbolfiles
-
-import com.google.common.truth.Truth.assertThat
-import java.io.ByteArrayInputStream
-import org.junit.Assert.assertThrows
-import org.junit.Test
-
-class SymbolFileParserTest {
-
-    @Test
-    fun testNextLine() {
-        val input = ByteArrayInputStream("""
-            foo
-            bar
-            # baz
-            qux
-        """.trimIndent().toByteArray())
-        val parser = SymbolFileParser(input)
-        assertThat(parser.currentLine.trim()).isEqualTo("foo")
-        assertThat(parser.nextLine().trim()).isEqualTo("bar")
-        assertThat(parser.currentLine.trim()).isEqualTo("bar")
-        assertThat(parser.nextLine().trim()).isEqualTo("qux")
-        assertThat(parser.currentLine.trim()).isEqualTo("qux")
-        assertThat(parser.nextLine().trim()).isEqualTo("")
-        assertThat(parser.currentLine.trim()).isEqualTo("")
-    }
-
-    @Test
-    fun testParseVersion() {
-        val input = ByteArrayInputStream("""
-            VERSION_1 {
-                baz;
-                qux;
-            };
-            VERSION_2 {
-            } VERSION_1;
-        """.trimIndent().toByteArray())
-        val parser = SymbolFileParser(input)
-        val version = parser.parseNextVersion()
-        assertThat(version.name).isEqualTo("VERSION_1")
-        assertThat(version.base).isNull()
-        assertThat(version.symbols).isEqualTo(
-            listOf(
-                Symbol("baz"),
-                Symbol("qux")
-            )
-        )
-        parser.nextLine()
-        val version2 = parser.parseNextVersion()
-        assertThat(version2.name).isEqualTo("VERSION_2")
-        assertThat(version2.base).isEqualTo("VERSION_1")
-    }
-
-    @Test
-    fun testParseVersionEOF() {
-        val input = ByteArrayInputStream("""
-            VERSION_1 {
-        """.trimIndent().toByteArray())
-        val parser = SymbolFileParser(input)
-        val throwable = assertThrows(ParseError::class.java) {
-            parser.parseNextVersion()
-        }
-        assertThat(throwable.message).isEqualTo("Unexpected EOF in version block.")
-    }
-
-    @Test
-    fun testUnknownScopeLabel() {
-        val input = ByteArrayInputStream("""
-            VERSION_1 {
-                foo:
-            }
-        """.trimIndent().toByteArray())
-        val parser = SymbolFileParser(input)
-        val throwable = assertThrows(ParseError::class.java) {
-            parser.parseNextVersion()
-        }
-        assertThat(throwable.message).isEqualTo("Unknown visibility label: foo")
-    }
-
-    @Test
-    fun testParseSymbol() {
-        val input = ByteArrayInputStream("""
-            foo;
-            bar;
-            "baz()";
-        """.trimIndent().toByteArray())
-        val parser = SymbolFileParser(input)
-        val symbol = parser.parseNextSymbol(cppSymbol = false)
-        assertThat(symbol.name).isEqualTo("foo")
-        parser.nextLine()
-        val symbol2 = parser.parseNextSymbol(cppSymbol = false)
-        assertThat(symbol2.name).isEqualTo("bar")
-        parser.nextLine()
-        val symbol3 = parser.parseNextSymbol(cppSymbol = true)
-        assertThat(symbol3.name).isEqualTo("baz()")
-    }
-
-    @Test
-    fun testWildcardSymbolGlobal() {
-        val input = ByteArrayInputStream("""
-            VERSION_1 {
-                *;
-            };
-        """.trimIndent().toByteArray())
-        val parser = SymbolFileParser(input)
-        val throwable = assertThrows(ParseError::class.java) {
-            parser.parseNextVersion()
-        }
-        assertThat(throwable.message).isEqualTo("Wildcard global symbols are not permitted.")
-    }
-
-    @Test
-    fun testWildcardSymbolLocal() {
-        val input = ByteArrayInputStream(
-            """
-            VERSION_1 {
-                local:
-                    *;
-            };
-        """.trimIndent().toByteArray()
-        )
-        val parser = SymbolFileParser(input)
-        val version = parser.parseNextVersion()
-        assertThat(version.symbols).isEmpty()
-    }
-
-    @Test
-    fun testMissingSemicolon() {
-        val input = ByteArrayInputStream("""
-            VERSION_1 {
-                foo
-            };
-        """.trimIndent().toByteArray())
-        val parser = SymbolFileParser(input)
-        val throwable = assertThrows(ParseError::class.java) {
-            parser.parseNextVersion()
-        }
-        assertThat(throwable.message).isEqualTo("Expected ; to terminate symbol: foo")
-    }
-
-    @Test
-    fun testParseFailsInvalidInput() {
-        val input = ByteArrayInputStream("""
-            foo
-        """.trimIndent().toByteArray())
-        val parser = SymbolFileParser(input)
-        val throwable = assertThrows(ParseError::class.java) {
-            parser.parse()
-        }
-        assertThat(throwable.message).isEqualTo("Unexpected contents at top level: foo")
-    }
-
-    @Test
-    fun testParse() {
-        val input = ByteArrayInputStream("""
-            VERSION_1 {
-                local:
-                    hidden1;
-                global:
-                    foo;
-                    bar;
-            };
-            VERSION_2 {
-                # Implicit global scope.
-                    woodly;
-                    doodly;
-                local:
-                    qwerty;
-            } VERSION_1;
-        """.trimIndent().toByteArray())
-        val parser = SymbolFileParser(input)
-        val versions = parser.parse()
-        assertThat(versions).isEqualTo(
-            listOf(
-                Version(
-                    name = "VERSION_1",
-                    symbols = listOf(
-                        Symbol("foo"),
-                        Symbol("bar"),
-                    )
-                ),
-                Version(
-                    name = "VERSION_2",
-                    base = "VERSION_1",
-                    symbols = listOf(
-                        Symbol("woodly"),
-                        Symbol("doodly"),
-                    )
-                )
-            )
-        )
-    }
-    @Test
-    fun testParseExternCpp() {
-        val input = ByteArrayInputStream("""
-            VERSION_1 {
-                local:
-                    hidden1;
-                global:
-                    extern "C++" {
-                        "foo()";
-                        "bar(int)";
-                    };
-            };
-        """.trimIndent().toByteArray())
-        val parser = SymbolFileParser(input)
-        val versions = parser.parse()
-        assertThat(versions).isEqualTo(
-            listOf(
-                Version(
-                    name = "VERSION_1",
-                    symbols = listOf(
-                        Symbol("foo()"),
-                        Symbol("bar(int)"),
-                    )
-                )
-            )
-        )
-    }
-}
\ No newline at end of file
diff --git a/buildSrc-tests/src/test/kotlin/androidx/build/libabigail/symbolfiles/SymbolListGeneratorTest.kt b/buildSrc-tests/src/test/kotlin/androidx/build/libabigail/symbolfiles/SymbolListGeneratorTest.kt
deleted file mode 100644
index 5c393d0..0000000
--- a/buildSrc-tests/src/test/kotlin/androidx/build/libabigail/symbolfiles/SymbolListGeneratorTest.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.build.libabigail.symbolfiles
-
-import com.google.common.truth.Truth.assertThat
-import java.io.ByteArrayInputStream
-import java.io.ByteArrayOutputStream
-import org.junit.Test
-
-class SymbolListGeneratorTest {
-
-    @Test
-    fun writesSimpleFileToList() {
-        val input = ByteArrayInputStream("""
-            VERSION_1 {
-                local:
-                    hidden1;
-                global:
-                    foo;
-                    bar;
-            };
-            VERSION_2 { # wasd
-                # Implicit global scope.
-                    woodly;
-                    extern "C++" {
-                        "doodly()";
-                    };
-                local:
-                    qwerty;
-            } VERSION_1;
-        """.trimIndent().toByteArray())
-        val output = ByteArrayOutputStream()
-        val generator = SymbolListGenerator(input = input, output = output)
-        generator.generate()
-        assertThat(output.toString()).isEqualTo("""
-            [abi_symbol_list]
-              foo
-              bar
-              woodly
-              doodly()
-            
-        """.trimIndent())
-    }
-}
\ No newline at end of file
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
index 6a34e51..2e51ac8 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
@@ -192,6 +192,8 @@
             it.from(project.getTestConfigDirectory())
             // We're mostly zipping a bunch of .apk files that are already compressed
             it.entryCompression = ZipEntryCompression.STORED
+            // Archive is greater than 4Gb :O
+            it.isZip64()
         }
         project.tasks.register(
             ZIP_CONSTRAINED_TEST_CONFIGS_WITH_APKS_TASK, Zip::class.java
@@ -201,6 +203,8 @@
             it.from(project.getConstrainedTestConfigDirectory())
             // We're mostly zipping a bunch of .apk files that are already compressed
             it.entryCompression = ZipEntryCompression.STORED
+            // Archive is greater than 4Gb :O
+            it.isZip64()
         }
 
         AffectedModuleDetector.configure(gradle, this)
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/ListTaskOutputsTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/ListTaskOutputsTask.kt
index 27955d3..4312272 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/ListTaskOutputsTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/ListTaskOutputsTask.kt
@@ -127,7 +127,11 @@
     "updateLintBaselineWithExpandProjectionDebug",
     "updateLintBaselineWithExpandProjectionRelease",
     "updateLintBaselineWithNullAwareTypeConverterDebug",
-    "updateLintBaselineWithNullAwareTypeConverterRelease"
+    "updateLintBaselineWithNullAwareTypeConverterRelease",
+    "updateLintBaselineWithoutExpandProjectionDebug",
+    "updateLintBaselineWithoutExpandProjectionRelease",
+    "updateLintBaselineWithoutNullAwareTypeConverterDebug",
+    "updateLintBaselineWithoutNullAwareTypeConverterRelease"
 )
 
 fun shouldValidateTaskOutput(task: Task): Boolean {
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/libabigail/GenerateNativeApiTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/libabigail/GenerateNativeApiTask.kt
index 00c9000..33ecd7c 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/libabigail/GenerateNativeApiTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/libabigail/GenerateNativeApiTask.kt
@@ -32,7 +32,6 @@
 import org.gradle.workers.WorkerExecutor
 import java.io.File
 import javax.inject.Inject
-import org.gradle.api.tasks.InputFile
 
 private const val ARCH_PREFIX = "android."
 internal val architectures = listOf("arm64-v8a", "armeabi-v7a", "x86", "x86_64")
@@ -49,9 +48,6 @@
     @get:InputDirectory
     abstract val prefabDirectory: Property<File>
 
-    @get:InputFile
-    abstract val symbolFile: Property<File>
-
     @get:Internal
     abstract val projectRootDir: Property<File>
 
@@ -111,7 +107,6 @@
                     outputFilePath.parentFile.mkdirs()
                     workQueue.submit(AbiDwWorkAction::class.java) { parameters ->
                         parameters.rootDir = projectRootDir.get().toString()
-                        parameters.symbolList = symbolFile.get().toString()
                         parameters.pathToLib = artifact.canonicalPath
                         parameters.outputFilePath = outputFilePath.toString()
                     }
@@ -123,7 +118,6 @@
 
 interface AbiDwParameters : WorkParameters {
     var rootDir: String
-    var symbolList: String
     var pathToLib: String
     var outputFilePath: String
 }
@@ -137,12 +131,6 @@
             it.args = listOf(
                 "--drop-private-types",
                 "--no-show-locs",
-                // Do not actually pass the symbol list to `abidw`. As long as the version script
-                // is being used to build the library `abidw` will only document the visible symbols
-                // and there are currently some unresolved issues with certain symbols being
-                // incorrectly omitted from the output of abidw.
-                // "-w",
-                // parameters.symbolList,
                 "--out-file",
                 tempFile.toString(),
                 parameters.pathToLib
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/libabigail/NativeApiTasks.kt b/buildSrc/private/src/main/kotlin/androidx/build/libabigail/NativeApiTasks.kt
index bcb8de2..314a912 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/libabigail/NativeApiTasks.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/libabigail/NativeApiTasks.kt
@@ -19,7 +19,6 @@
 import androidx.build.addToBuildOnServer
 import androidx.build.addToCheckTask
 import androidx.build.checkapi.getRequiredCompatibilityApiLocation
-import androidx.build.libabigail.symbolfiles.GenerateSymbolFileTask
 import com.android.build.gradle.LibraryExtension
 import org.gradle.api.Project
 import java.io.File
@@ -39,16 +38,6 @@
             LibraryExtension::class.java
         ).prefab.names.toList()
 
-        val generateSymbolFileTask = project.tasks.register(
-            "generateSymbolFile",
-            GenerateSymbolFileTask::class.java
-        ) { task ->
-            task.description = "Generate a list of public symbols from a version script in the " +
-                "project directory"
-            task.buildDir.set(project.buildDir)
-            task.projectDir.set(project.projectDir)
-        }
-
         // Generates API files from source in the build directory
         val generateNativeApi = project.tasks.register(
             "generateNativeApi",
@@ -57,13 +46,11 @@
             task.group = apiGroup
             task.description = "Generates API files from native source"
             task.projectRootDir.set(project.rootDir)
-            task.symbolFile.set(generateSymbolFileTask.get().getOutputFile())
             task.prefabDirectory.set(
                 project.buildDir.resolve("intermediates/prefab_package/release/prefab")
             )
             task.artifactNames.set(artifactNames)
             task.apiLocation.set(builtApiLocation)
-            task.dependsOn("generateSymbolFile")
             task.dependsOn("prefabReleasePackage")
         }
 
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/libabigail/symbolfiles/GenerateSymbolFileTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/libabigail/symbolfiles/GenerateSymbolFileTask.kt
deleted file mode 100644
index cff98a5..0000000
--- a/buildSrc/private/src/main/kotlin/androidx/build/libabigail/symbolfiles/GenerateSymbolFileTask.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.build.libabigail.symbolfiles
-
-import java.io.File
-import java.io.FileInputStream
-import java.io.FileOutputStream
-import org.gradle.api.DefaultTask
-import org.gradle.api.GradleException
-import org.gradle.api.tasks.InputFile
-import org.gradle.api.tasks.Internal
-import org.gradle.api.tasks.OutputFile
-import org.gradle.api.tasks.TaskAction
-import org.gradle.api.provider.Property
-
-/**
- * Task to generate a symbol file from a single .map.txt file in the project. Requires exactly one
- * .map.txt file to exist.
- */
-abstract class GenerateSymbolFileTask : DefaultTask() {
-    @get:Internal
-    abstract val buildDir: Property<File>
-
-    @get:Internal
-    abstract val projectDir: Property<File>
-
-    @InputFile
-    fun getInputFile(): File {
-        return runCatching {
-            projectDir.get().walk().single {
-                it.isFile && it.name.endsWith(".map.txt")
-            }
-        }.getOrNull() ?: throw GradleException(
-            "A single version script with extension .map.txt is required in $projectDir."
-        )
-    }
-
-    @OutputFile
-    fun getOutputFile(): File {
-        return buildDir.get().resolve("symbol_files/abi_symbol_list.txt")
-    }
-
-    @TaskAction
-    fun exec() {
-        SymbolListGenerator(
-            input = FileInputStream(getInputFile()),
-            output = FileOutputStream(getOutputFile())
-        ).generate()
-    }
-}
\ No newline at end of file
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/libabigail/symbolfiles/SymbolFileParser.kt b/buildSrc/private/src/main/kotlin/androidx/build/libabigail/symbolfiles/SymbolFileParser.kt
deleted file mode 100644
index 89550ea..0000000
--- a/buildSrc/private/src/main/kotlin/androidx/build/libabigail/symbolfiles/SymbolFileParser.kt
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.build.libabigail.symbolfiles
-
-import java.io.BufferedReader
-import java.io.InputStream
-import java.io.InputStreamReader
-
-class ParseError(message: String) : RuntimeException(message)
-
-typealias Tags = List<String>
-
-data class Version(
-    val name: String,
-    val base: String? = null,
-    val symbols: List<Symbol> = emptyList()
-)
-
-data class Symbol(val name: String)
-
-/**
- * Class to parse version scripts based on the original python implementation but simplified to
- * ignore tags and some other unused parameters.
- *
- * https://android.googlesource.com/platform/build/soong/+/master/cc/symbolfile/__init__.py
- */
-class SymbolFileParser(
-    val input: InputStream
-) {
-    val reader = BufferedReader(InputStreamReader(input))
-    lateinit var currentLine: String
-
-    init {
-        nextLine()
-    }
-
-    fun parse(): List<Version> {
-        val versions = mutableListOf<Version>()
-        do {
-            if (currentLine.contains("{")) {
-                versions.add(parseNextVersion())
-            } else {
-                throw ParseError("Unexpected contents at top level: $currentLine")
-            }
-        } while (nextLine().isNotBlank())
-        return versions
-    }
-
-    /**
-     * Parses a single version section and returns a Version object.
-     */
-    fun parseNextVersion(): Version {
-        val name = currentLine.split("{").first().trim()
-        val symbols = mutableListOf<Symbol>()
-        var globalScope = true
-        var cppSymbols = false
-        while (nextLine().isNotBlank()) {
-            if (currentLine.contains("}")) {
-                // Line is something like '} BASE; # tags'. Both base and tags are optional here.
-                val base = currentLine.split("}").last().split("#").first().trim()
-                if (!base.endsWith(";")) {
-                    throw ParseError("Unterminated version/export \"C++\" block (expected ;).")
-                }
-                if (cppSymbols) {
-                    cppSymbols = false
-                } else {
-                    return Version(
-                        name,
-                        base.removeSuffix(";").trim().ifBlank { null },
-                        symbols
-                    )
-                }
-            } else if (currentLine.contains("extern \"C++\" {")) {
-                cppSymbols = true
-            } else if (!cppSymbols && currentLine.contains(":")) {
-                val visibility = currentLine.split(':').first().trim()
-                if (visibility == "local") {
-                    globalScope = false
-                } else if (visibility == "global") {
-                    globalScope = true
-                } else {
-                    throw ParseError("Unknown visibility label: $visibility")
-                }
-            } else if (globalScope) {
-                symbols.add(parseNextSymbol(cppSymbols))
-            } else {
-                // We're in a hidden scope. Ignore everything.
-            }
-        }
-        throw ParseError("Unexpected EOF in version block.")
-    }
-
-    /**
-     * Parses a single symbol line and returns a Symbol object.
-     */
-    fun parseNextSymbol(cppSymbol: Boolean): Symbol {
-        val line = currentLine
-        if (!line.contains(";")) {
-            throw ParseError("Expected ; to terminate symbol: ${line.trim()}")
-        }
-        if (line.contains("*")) {
-            throw ParseError("Wildcard global symbols are not permitted.")
-        }
-        // Line is now in the format "<symbol-name>; # tags"
-        val name = line.trim().split(";").first().let {
-            if (cppSymbol) {
-              it.removeSurrounding("\"")
-            } else {
-                it
-            }
-        }
-        return Symbol(name)
-    }
-
-    /**
-     * Returns the next non-empty non-comment line.
-     * A return value of '' indicates EOF.
-     */
-    fun nextLine(): String {
-        var line: String? = reader.readLine()
-        while (line != null && (line.isBlank() || line.trim().startsWith("#"))) {
-            line = reader.readLine() ?: break
-        }
-        currentLine = line ?: ""
-        return currentLine
-    }
-}
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/libabigail/symbolfiles/SymbolListGenerator.kt b/buildSrc/private/src/main/kotlin/androidx/build/libabigail/symbolfiles/SymbolListGenerator.kt
deleted file mode 100644
index d614fa9..0000000
--- a/buildSrc/private/src/main/kotlin/androidx/build/libabigail/symbolfiles/SymbolListGenerator.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.build.libabigail.symbolfiles
-
-import java.io.InputStream
-import java.io.OutputStream
-
-/**
- * Class to generate a symbol list [output] from a given version script [input]. The generated
- * symbol list can be passed to abidw as an allow list of visible symbols to document.
- */
-class SymbolListGenerator(val input: InputStream, val output: OutputStream) {
-    fun generate() {
-        val versions = SymbolFileParser(input).parse()
-        write(versions)
-    }
-
-    fun write(versions: List<Version>) {
-        writeLine("[abi_symbol_list]")
-        versions.forEach { writeVersion(it) }
-    }
-
-    fun writeVersion(version: Version) {
-        version.symbols.forEach { writeLine("  " + it.name) }
-    }
-
-    private fun writeLine(line: String) {
-        output.write("$line\n".toByteArray())
-    }
-}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/AeFpsRangeLegacyQuirk.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/AeFpsRangeLegacyQuirk.java
index 94cd307..5f3c1b4 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/AeFpsRangeLegacyQuirk.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/AeFpsRangeLegacyQuirk.java
@@ -26,17 +26,21 @@
 import androidx.camera.core.impl.Quirk;
 
 /**
- * Quirk required to maintain good exposure on legacy devices by specifying a proper
- * {@link android.hardware.camera2.CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE}.
- * <p>
- * Legacy devices set the AE target FPS range to [30, 30]. This can potentially cause underexposure
- * issues. {@link androidx.camera.camera2.internal.compat.workaround.AeFpsRange} contains a
- * workaround that is used on legacy devices to set a AE FPS range whose upper bound is 30, which
- * guarantees a smooth frame rate, and whose lower bound is as small as possible to properly
- * expose frames in low light conditions. The default behavior on non legacy devices does not add
- * the AE FPS range option.
- *
- * @see androidx.camera.camera2.internal.compat.workaround.AeFpsRange
+ * <p>QuirkSummary
+ *     Bug Id: b/167425305
+ *     Description: Quirk required to maintain good exposure on legacy devices by specifying a
+ *                  proper
+ *                  {@link android.hardware.camera2.CaptureRequest#CONTROL_AE_TARGET_FPS_RANGE}.
+ *                  Legacy devices set the AE target FPS range to [30, 30]. This can potentially
+ *                  cause underexposure issues.
+ *                  {@link androidx.camera.camera2.internal.compat.workaround.AeFpsRange}
+ *                  contains a workaround that is used on legacy devices to set a AE FPS range
+ *                  whose upper bound is 30, which guarantees a smooth frame rate, and whose lower
+ *                  bound is as small as possible to properly expose frames in low light
+ *                  conditions. The default behavior on non legacy devices does not add the AE
+ *                  FPS range option.
+ *     Device(s): All legacy devices
+ *     @see androidx.camera.camera2.internal.compat.workaround.AeFpsRange
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class AeFpsRangeLegacyQuirk implements Quirk {
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ExcludedSupportedSizesQuirk.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ExcludedSupportedSizesQuirk.java
index e365eddc..4854150 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ExcludedSupportedSizesQuirk.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ExcludedSupportedSizesQuirk.java
@@ -31,15 +31,16 @@
 import java.util.List;
 
 /**
- * Quirk required to exclude certain supported surface sizes that are problematic. These sizes
- * are dependent on the device, camera and image format.
- * <p>
- * An example is the resolution size 4000x3000 which is supported on OnePlus 6, but causes a WYSIWYG
- * issue between preview and image capture. See b/157448499.
- *
- * <p>On Huawei P20 Lite, the Preview screen will become too bright when 400x400 or 720x720
- * Preview resolutions are used together with a large zoom in value. The same symptom happens on
- * ImageAnalysis. See https://issuetracker.google.com/192129158.
+ * <p>QuirkSummary
+ *     Bug Id: b/157448499, b/192129158
+ *     Description: Quirk required to exclude certain supported surface sizes that are
+ *                  problematic. These sizes are dependent on the device, camera and image format.
+ *                  An example is the resolution size 4000x3000 which is supported on OnePlus 6,
+ *                  but causes a WYSIWYG issue between preview and image capture. Another example
+ *                  is on Huawei P20 Lite, the Preview screen will become too bright when 400x400
+ *                  or 720x720 Preview resolutions are used together with a large zoom in value.
+ *                  The same symptom happens on ImageAnalysis.
+ *     Device(s): OnePlus 6, OnePlus 6T, Huawei P20
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class ExcludedSupportedSizesQuirk implements Quirk {
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ExtraSupportedSurfaceCombinationsQuirk.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ExtraSupportedSurfaceCombinationsQuirk.java
index c8572df..11364a4 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ExtraSupportedSurfaceCombinationsQuirk.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ExtraSupportedSurfaceCombinationsQuirk.java
@@ -21,6 +21,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
+import androidx.camera.camera2.internal.compat.workaround.ExtraSupportedSurfaceCombinationsContainer;
 import androidx.camera.core.impl.Quirk;
 import androidx.camera.core.impl.SurfaceCombination;
 import androidx.camera.core.impl.SurfaceConfig;
@@ -34,13 +35,16 @@
 import java.util.Set;
 
 /**
- * Quirk required to include extra supported surface combinations which are additional to the
- * guaranteed supported configurations.
- *
- * <p>An example is the Samsung S7's LIMITED-level camera device can support additional
- * YUV/640x480 + PRIV/PREVIEW + YUV/MAXIMUM combination. Some other Samsung devices can support
- * additional YUV/640x480 + PRIV/PREVIEW + YUV/MAXIMUM and YUV/640x480 + YUV/PREVIEW +
- * YUV/MAXIMUM configutations (See b/194149215).
+ * <p>QuirkSummary
+ *     Bug Id: b/194149215
+ *     Description: Quirk required to include extra supported surface combinations which are
+ *                  additional to the guaranteed supported configurations. An example is the
+ *                  Samsung S7's LIMITED-level camera device can support additional YUV/640x480 +
+ *                  PRIV/PREVIEW + YUV/MAXIMUM combination. Some other Samsung devices can
+ *                  support additional YUV/640x480 + PRIV/PREVIEW + YUV/MAXIMUM and YUV/640x480 +
+ *                  YUV/PREVIEW + YUV/MAXIMUM configurations.
+ *     Device(s): Some Samsung devices
+ *     @see ExtraSupportedSurfaceCombinationsContainer
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class ExtraSupportedSurfaceCombinationsQuirk implements Quirk {
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ImageCapturePixelHDRPlusQuirk.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ImageCapturePixelHDRPlusQuirk.java
index 5800ecc..0e7d807 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ImageCapturePixelHDRPlusQuirk.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/ImageCapturePixelHDRPlusQuirk.java
@@ -26,12 +26,17 @@
 import java.util.List;
 
 /**
- * Quirk required to turn on/off HDR+ on Pixel devices by enabling/disabling zero-shutter-lag
- * (ZSL) mode on the capture request, depending on the image capture use case's capture mode, i.e.
- * prioritizing image capture latency over quality, or vice versa. This means that when the
- * capture mode is {@link ImageCapture#CAPTURE_MODE_MINIMIZE_LATENCY}, HDR+ is turned off by
- * disabling ZSL, and when it is {@link ImageCapture#CAPTURE_MODE_MAXIMIZE_QUALITY}, HDR+ is
- * turned on by enabling ZSL.
+ * <p>QuirkSummary
+ *     Bug Id: b/123897971
+ *     Description: Quirk required to turn on/off HDR+ on Pixel devices by enabling/disabling
+ *                  zero-shutter-lag (ZSL) mode on the capture request, depending on the image
+ *                  capture use case's capture mode, i.e. prioritizing image capture latency over
+ *                  quality, or vice versa. This means that when the capture mode is
+ *                  {@link ImageCapture#CAPTURE_MODE_MINIMIZE_LATENCY}, HDR+ is turned off by
+ *                  disabling ZSL, and when it is
+ *                  {@link ImageCapture#CAPTURE_MODE_MAXIMIZE_QUALITY}, HDR+ is turned on by
+ *                  enabling ZSL.
+ *     Device(s): Pixel 2, Pixel 2 XL, Pixel 3, Pixel 3 XL
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class ImageCapturePixelHDRPlusQuirk implements Quirk {
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/YuvImageOnePixelShiftQuirk.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/YuvImageOnePixelShiftQuirk.java
index 06e74de..2cb8d0c 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/YuvImageOnePixelShiftQuirk.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/YuvImageOnePixelShiftQuirk.java
@@ -24,8 +24,12 @@
 import androidx.camera.core.internal.compat.quirk.OnePixelShiftQuirk;
 
 /**
- * For these devices, workaround will be patched to shift one pixel right to left and
- * duplicate the last pixel for YUV_420_888 data when converting to RGBA.
+ * <p>QuirkSummary
+ *     Bug Id: 184229033
+ *     Description: On certain devices, one pixel shifted when the HAL layer converts RGB data to
+ *                  YUV data. It leads to the leftmost column degradation when converting YUV to
+ *                  RGB in applications.
+ *     Device(s): Motorola MotoG3, Samsung SM-G532F/SM-J700F
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class YuvImageOnePixelShiftQuirk implements OnePixelShiftQuirk {
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/compat/quirk/ImageCaptureRotationOptionQuirk.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/compat/quirk/ImageCaptureRotationOptionQuirk.java
index 4713958..7f9c9c3 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/compat/quirk/ImageCaptureRotationOptionQuirk.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/compat/quirk/ImageCaptureRotationOptionQuirk.java
@@ -25,16 +25,20 @@
 import androidx.camera.core.impl.Quirk;
 
 /**
- * Checks whether ImageCapture supports a specific capture config option.
- *
- * <p>When capturing images, JPEG related options will be applied. But not all devices can
- * support those options. For example, CaptureConfig.OPTION_ROTATION is used to provide the
- * target rotation information to the HAL. So that the HAL can rotate the image buffer directly
- * and provide the correct orientation information in the embedded exif data. But Huawei Mate 20
- * Lite and Honor 9X can't handle the capture rotation option correctly and the embedded exif's
- * orientation value is wrong. For these devices, the rotation option can't be used and we should
- * calculate the rotation value according to the target rotation setting for the final output
- * image. See: b/171492111.
+ * <p>QuirkSummary
+ *     Bug Id: b/171492111
+ *     Description: Quirk required to check whether ImageCapture supports a specific capture
+ *                  config option. For example, JPEG related options will be applied when
+ *                  capturing images. CaptureConfig.OPTION_ROTATION is used to provide the target
+ *                  rotation information to the HAL. So that the HAL can rotate the image buffer
+ *                  directly and provide the correct orientation information in the embedded exif
+ *                  data. But not all devices can support CaptureConfig.OPTION_ROTATION. Huawei
+ *                  Mate 20 Lite and Honor 9X can't handle the capture rotation option correctly
+ *                  and the embedded exif's orientation value is wrong. For these devices, the
+ *                  rotation option can't be used and we should calculate the rotation value
+ *                  according to the target rotation setting for the final output image.
+ *     Device(s): Huawei Mate 20 Lite, Honor 9X
+ *     @see androidx.camera.core.internal.compat.workaround.ExifRotationAvailability
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public final class ImageCaptureRotationOptionQuirk implements Quirk {
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/quirk/ExtensionDisabledQuirk.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/quirk/ExtensionDisabledQuirk.java
index 19a8e0f..75a3ee9 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/quirk/ExtensionDisabledQuirk.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/compat/quirk/ExtensionDisabledQuirk.java
@@ -25,15 +25,17 @@
 
 
 /**
- * Quirk required to disable extension for some devices.
- *
- * <p>An example is that Pixel 5's availability check result of the basic extension
- * interface should be false, but it actually returns true. Therefore, force disable Basic
- * Extender capability on the device. See b/199408131.
- *
- * <p>Another example is that Motorola razr 5G's availability check results of both back
- * and front camera are true, but it will cause the black preview screen issue. Therefore, force
- * disable the bokeh mode on the device. See b/214130117.
+ * <p>QuirkSummary
+ *     Bug Id: b/199408131, b/214130117
+ *     Description: Quirk required to disable extension for some devices. An example is that
+ *                  Pixel 5's availability check result of the basic extension interface should
+ *                  be false, but it actually returns true. Therefore, force disable Basic
+ *                  Extender capability on the device. Another example is that Motorola razr 5G's
+ *                  availability check results of both back and front camera are true, but it
+ *                  will cause the black preview screen issue. Therefore, force disable the bokeh
+ *                  mode on the device.
+ *     Device(s): Pixel 5, Motorola razr 5G
+ *     @see androidx.camera.extensions.internal.compat.workaround.ExtensionDisabledValidator
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public class ExtensionDisabledQuirk implements Quirk {
diff --git a/camera/integration-tests/viewtestapp/build.gradle b/camera/integration-tests/viewtestapp/build.gradle
index 155e485..565c10d 100644
--- a/camera/integration-tests/viewtestapp/build.gradle
+++ b/camera/integration-tests/viewtestapp/build.gradle
@@ -80,10 +80,10 @@
     // Compose UI
     kotlinPlugin(projectOrArtifact(":compose:compiler:compiler"))
     implementation(project(":compose:runtime:runtime"))
-    implementation("androidx.compose.ui:ui:1.0.0-rc02")
-    implementation("androidx.compose.material:material:1.0.0-rc02")
-    implementation("androidx.compose.ui:ui-tooling:1.0.0-rc02")
-    implementation("androidx.activity:activity-compose:1.3.0-beta02")
+    implementation("androidx.compose.ui:ui:1.0.5")
+    implementation("androidx.compose.material:material:1.0.5")
+    implementation("androidx.compose.ui:ui-tooling:1.0.5")
+    implementation("androidx.activity:activity-compose:1.3.1")
 
     // Testing framework
     androidTestImplementation(libs.testExtJunit)
diff --git a/car/app/app/src/main/java/androidx/car/app/CarAppBinder.java b/car/app/app/src/main/java/androidx/car/app/CarAppBinder.java
new file mode 100644
index 0000000..9d774e0
--- /dev/null
+++ b/car/app/app/src/main/java/androidx/car/app/CarAppBinder.java
@@ -0,0 +1,369 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.car.app;
+
+import static androidx.car.app.utils.LogTags.TAG;
+import static androidx.car.app.utils.RemoteUtils.dispatchCallFromHost;
+
+import static java.util.Objects.requireNonNull;
+
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Binder;
+import android.util.Log;
+
+import androidx.annotation.MainThread;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.car.app.navigation.NavigationManager;
+import androidx.car.app.serialization.Bundleable;
+import androidx.car.app.serialization.BundlerException;
+import androidx.car.app.utils.RemoteUtils;
+import androidx.car.app.utils.ThreadUtils;
+import androidx.car.app.validation.HostValidator;
+import androidx.car.app.versioning.CarAppApiLevels;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleRegistry;
+
+import java.security.InvalidParameterException;
+
+/** Implementation of the binder {@link ICarApp}. */
+final class CarAppBinder extends ICarApp.Stub {
+    @Nullable
+    private CarAppService mService;
+
+    @Nullable
+    private Session mCurrentSession;
+    @Nullable
+    private HostValidator mHostValidator;
+    @Nullable
+    private HandshakeInfo mHandshakeInfo;
+
+    CarAppBinder(@NonNull CarAppService service) {
+        mService = service;
+    }
+
+    /**
+     * Explicitly mark the binder to be destroyed and remove the reference to the
+     * {@link CarAppService}, and any subsequent call from the host after this would be
+     * considered invalid and throws an exception.
+     *
+     * <p>This is needed because the binder object can outlive the service and will not be
+     * garbage collected until the car host cleans up its side of the binder reference,
+     * causing a leak. See https://github.com/square/leakcanary/issues/1906 for more context
+     * related to this issue.
+     */
+    void destroy() {
+        onDestroyLifecycle();
+        mCurrentSession = null;
+        mHostValidator = null;
+        mHandshakeInfo = null;
+        mService = null;
+    }
+
+    void onDestroyLifecycle() {
+        Session session = mCurrentSession;
+        if (session != null) {
+            session.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
+        }
+        mCurrentSession = null;
+    }
+
+    // incompatible argument for parameter context of attachBaseContext.
+    // call to onCreateScreen(android.content.Intent) not allowed on the given receiver.
+    @SuppressWarnings({
+            "nullness:argument.type.incompatible",
+            "nullness:method.invocation.invalid"
+    })
+    @Override
+    public void onAppCreate(
+            ICarHost carHost,
+            Intent intent,
+            Configuration configuration,
+            IOnDoneCallback callback) {
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "onAppCreate intent: " + intent);
+        }
+
+        dispatchCallFromHost(callback, "onAppCreate", () -> {
+            CarAppService service = requireNonNull(mService);
+            Session session = mCurrentSession;
+            if (session == null
+                    || session.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) {
+                session = service.onCreateSession();
+                mCurrentSession = session;
+            }
+
+            session.configure(service,
+                    requireNonNull(getHandshakeInfo()),
+                    requireNonNull(service.getHostInfo()),
+                    carHost, configuration);
+
+            // Whenever the host unbinds, the screens in the stack are destroyed.  If
+            // there is another bind, before the OS has destroyed this Service, then
+            // the stack will be empty, and we need to treat it as a new instance.
+            LifecycleRegistry registry = (LifecycleRegistry) session.getLifecycle();
+            Lifecycle.State state = registry.getCurrentState();
+            int screenStackSize = session.getCarContext().getCarService(
+                    ScreenManager.class).getScreenStack().size();
+            if (!state.isAtLeast(Lifecycle.State.CREATED) || screenStackSize < 1) {
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "onAppCreate the app was not yet created or the "
+                            + "screen stack was empty state: "
+                            + registry.getCurrentState()
+                            + ", stack size: " + screenStackSize);
+                }
+                session.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
+                session.getCarContext().getCarService(ScreenManager.class).push(
+                        session.onCreateScreen(intent));
+            } else {
+                if (Log.isLoggable(TAG, Log.DEBUG)) {
+                    Log.d(TAG, "onAppCreate the app was already created");
+                }
+                onNewIntentInternal(session, intent);
+            }
+            return null;
+        });
+
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "onAppCreate completed");
+        }
+    }
+
+    @Override
+    public void onAppStart(IOnDoneCallback callback) {
+        dispatchCallFromHost(
+                getCurrentLifecycle(), callback,
+                "onAppStart", () -> {
+                    requireNonNull(mCurrentSession).handleLifecycleEvent(Lifecycle.Event.ON_START);
+                    return null;
+                });
+    }
+
+    @Override
+    public void onAppResume(IOnDoneCallback callback) {
+        dispatchCallFromHost(
+                getCurrentLifecycle(), callback,
+                "onAppResume", () -> {
+                    requireNonNull(mCurrentSession).handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
+                    return null;
+                });
+    }
+
+    @Override
+    public void onAppPause(IOnDoneCallback callback) {
+        dispatchCallFromHost(
+                getCurrentLifecycle(), callback, "onAppPause",
+                () -> {
+                    requireNonNull(mCurrentSession).handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
+                    return null;
+                });
+    }
+
+    @Override
+    public void onAppStop(IOnDoneCallback callback) {
+        dispatchCallFromHost(
+                getCurrentLifecycle(), callback, "onAppStop",
+                () -> {
+                    requireNonNull(mCurrentSession).handleLifecycleEvent(Lifecycle.Event.ON_STOP);
+                    return null;
+                });
+    }
+
+    @Override
+    public void onNewIntent(Intent intent, IOnDoneCallback callback) {
+        dispatchCallFromHost(
+                getCurrentLifecycle(),
+                callback,
+                "onNewIntent",
+                () -> {
+                    onNewIntentInternal(requireNonNull(mCurrentSession), intent);
+                    return null;
+                });
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration configuration,
+            IOnDoneCallback callback) {
+        dispatchCallFromHost(
+                getCurrentLifecycle(),
+                callback,
+                "onConfigurationChanged",
+                () -> {
+                    onConfigurationChangedInternal(requireNonNull(mCurrentSession),
+                            configuration);
+                    return null;
+                });
+    }
+
+    @Override
+    public void getManager(@CarContext.CarServiceType @NonNull String type,
+            IOnDoneCallback callback) {
+        ThreadUtils.runOnMain(() -> {
+            Session session = requireNonNull(mCurrentSession);
+            switch (type) {
+                case CarContext.APP_SERVICE:
+                    RemoteUtils.sendSuccessResponseToHost(
+                            callback,
+                            "getManager",
+                            session.getCarContext().getCarService(
+                                    AppManager.class).getIInterface());
+                    return;
+                case CarContext.NAVIGATION_SERVICE:
+                    RemoteUtils.sendSuccessResponseToHost(
+                            callback,
+                            "getManager",
+                            session.getCarContext().getCarService(
+                                    NavigationManager.class).getIInterface());
+                    return;
+                default:
+                    Log.e(TAG, type + "%s is not a valid manager");
+                    RemoteUtils.sendFailureResponseToHost(callback, "getManager",
+                            new InvalidParameterException(
+                                    type + " is not a valid manager type"));
+            }
+        });
+    }
+
+    @Override
+    public void getAppInfo(IOnDoneCallback callback) {
+        try {
+            CarAppService service = requireNonNull(mService);
+            RemoteUtils.sendSuccessResponseToHost(
+                    callback, "getAppInfo", service.getAppInfo());
+        } catch (IllegalArgumentException e) {
+            // getAppInfo() could fail with the specified API version is invalid.
+            RemoteUtils.sendFailureResponseToHost(callback, "getAppInfo", e);
+        }
+    }
+
+    @Override
+    public void onHandshakeCompleted(Bundleable handshakeInfo,
+            IOnDoneCallback callback) {
+        CarAppService service = requireNonNull(mService);
+        try {
+            HandshakeInfo deserializedHandshakeInfo =
+                    (HandshakeInfo) handshakeInfo.get();
+            String packageName = deserializedHandshakeInfo.getHostPackageName();
+            int uid = Binder.getCallingUid();
+            HostInfo hostInfo = new HostInfo(packageName, uid);
+            if (!getHostValidator().isValidHost(hostInfo)) {
+                RemoteUtils.sendFailureResponseToHost(callback, "onHandshakeCompleted",
+                        new IllegalArgumentException("Unknown host '"
+                                + packageName + "', uid:" + uid));
+                return;
+            }
+
+            AppInfo appInfo = service.getAppInfo();
+            int appMinApiLevel = appInfo.getMinCarAppApiLevel();
+            int appMaxApiLevel = appInfo.getLatestCarAppApiLevel();
+            int hostApiLevel = deserializedHandshakeInfo.getHostCarAppApiLevel();
+            if (appMinApiLevel > hostApiLevel) {
+                RemoteUtils.sendFailureResponseToHost(callback, "onHandshakeCompleted",
+                        new IllegalArgumentException(
+                                "Host API level (" + hostApiLevel + ") is "
+                                        + "less than the app's min API level ("
+                                        + appMinApiLevel + ")"));
+                return;
+            }
+            if (appMaxApiLevel < hostApiLevel) {
+                RemoteUtils.sendFailureResponseToHost(callback, "onHandshakeCompleted",
+                        new IllegalArgumentException(
+                                "Host API level (" + hostApiLevel + ") is "
+                                        + "greater than the app's max API level ("
+                                        + appMaxApiLevel + ")"));
+                return;
+            }
+
+            service.setHostInfo(hostInfo);
+            mHandshakeInfo = deserializedHandshakeInfo;
+            RemoteUtils.sendSuccessResponseToHost(callback, "onHandshakeCompleted",
+                    null);
+        } catch (BundlerException | IllegalArgumentException e) {
+            service.setHostInfo(null);
+            RemoteUtils.sendFailureResponseToHost(callback, "onHandshakeCompleted", e);
+        }
+    }
+
+    @Nullable
+    private Lifecycle getCurrentLifecycle() {
+        return mCurrentSession == null ? null : mCurrentSession.getLifecycle();
+    }
+
+    private HostValidator getHostValidator() {
+        if (mHostValidator == null) {
+            mHostValidator = requireNonNull(mService).createHostValidator();
+        }
+        return mHostValidator;
+    }
+
+    // call to onNewIntent(android.content.Intent) not allowed on the given receiver.
+    @SuppressWarnings("nullness:method.invocation.invalid")
+    @MainThread
+    private void onNewIntentInternal(Session session, Intent intent) {
+        ThreadUtils.checkMainThread();
+        session.onNewIntent(intent);
+    }
+
+    // call to onCarConfigurationChanged(android.content.res.Configuration) not
+    // allowed on the given receiver.
+    @SuppressWarnings("nullness:method.invocation.invalid")
+    @MainThread
+    private void onConfigurationChangedInternal(Session session,
+            Configuration configuration) {
+        ThreadUtils.checkMainThread();
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, "onCarConfigurationChanged configuration: " + configuration);
+        }
+
+        session.onCarConfigurationChangedInternal(configuration);
+    }
+
+    void onAutoDriveEnabled() {
+        Session session = mCurrentSession;
+        if (session != null) {
+            session.getCarContext().getCarService(
+                    NavigationManager.class).onAutoDriveEnabled();
+        }
+    }
+
+    /**
+     * Used by tests to verify the different behaviors when the app has different api level than
+     * the host.
+     */
+    @VisibleForTesting
+    void setHandshakeInfo(@NonNull HandshakeInfo handshakeInfo) {
+        int apiLevel = handshakeInfo.getHostCarAppApiLevel();
+        if (!CarAppApiLevels.isValid(apiLevel)) {
+            throw new IllegalArgumentException("Invalid Car App API level received: " + apiLevel);
+        }
+
+        mHandshakeInfo = handshakeInfo;
+    }
+
+    @VisibleForTesting
+    @Nullable
+    HandshakeInfo getHandshakeInfo() {
+        return mHandshakeInfo;
+    }
+
+    @Nullable
+    Session getCurrentSession() {
+        return mCurrentSession;
+    }
+}
diff --git a/car/app/app/src/main/java/androidx/car/app/CarAppService.java b/car/app/app/src/main/java/androidx/car/app/CarAppService.java
index 9136963..dc64b2b 100644
--- a/car/app/app/src/main/java/androidx/car/app/CarAppService.java
+++ b/car/app/app/src/main/java/androidx/car/app/CarAppService.java
@@ -23,33 +23,18 @@
 
 import android.app.Service;
 import android.content.Intent;
-import android.content.res.Configuration;
-import android.os.Binder;
 import android.os.IBinder;
 import android.util.Log;
 
 import androidx.annotation.CallSuper;
-import androidx.annotation.MainThread;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
-import androidx.car.app.CarContext.CarServiceType;
 import androidx.car.app.annotations.ExperimentalCarApi;
-import androidx.car.app.navigation.NavigationManager;
-import androidx.car.app.serialization.Bundleable;
-import androidx.car.app.serialization.BundlerException;
-import androidx.car.app.utils.RemoteUtils;
-import androidx.car.app.utils.ThreadUtils;
 import androidx.car.app.validation.HostValidator;
-import androidx.car.app.versioning.CarAppApiLevels;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.Lifecycle.Event;
-import androidx.lifecycle.Lifecycle.State;
-import androidx.lifecycle.LifecycleRegistry;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.security.InvalidParameterException;
 
 /**
  * The base class for implementing a car app that runs in the car.
@@ -130,18 +115,9 @@
     private AppInfo mAppInfo;
 
     @Nullable
-    private Session mCurrentSession;
-
-    @Nullable
-    private HostValidator mHostValidator;
-
-    @Nullable
     private HostInfo mHostInfo;
 
     @Nullable
-    private HandshakeInfo mHandshakeInfo;
-
-    @Nullable
     private CarAppBinder mBinder;
 
     @Override
@@ -185,19 +161,10 @@
             Log.d(TAG, "onUnbind intent: " + intent);
         }
         runOnMain(() -> {
-            if (mCurrentSession != null) {
-                // Destroy the session
-                // The session's lifecycle is observed by some of the manager and they will
-                // perform cleanup on destroy.  For example, the ScreenManager can destroy all
-                // Screens it holds.
-                LifecycleRegistry lifecycleRegistry = getLifecycleIfValid();
-                if (lifecycleRegistry == null) {
-                    Log.e(TAG, "Null Session when unbinding");
-                } else {
-                    lifecycleRegistry.handleLifecycleEvent(Event.ON_DESTROY);
-                }
+            if (mBinder != null) {
+                mBinder.onDestroyLifecycle();
             }
-            mCurrentSession = null;
+            mBinder = null;
         });
 
         if (Log.isLoggable(TAG, Log.DEBUG)) {
@@ -273,9 +240,8 @@
                     Log.d(TAG, "Executing onAutoDriveEnabled");
                 }
                 runOnMain(() -> {
-                    if (mCurrentSession != null) {
-                        mCurrentSession.getCarContext().getCarService(
-                                NavigationManager.class).onAutoDriveEnabled();
+                    if (mBinder != null) {
+                        mBinder.onAutoDriveEnabled();
                     }
                 });
             }
@@ -301,13 +267,9 @@
      */
     @Nullable
     public final Session getCurrentSession() {
-        return mCurrentSession;
+        return mBinder == null ? null : mBinder.getCurrentSession();
     }
 
-    // Strictly to avoid synthetic accessor.
-    void setCurrentSession(@Nullable Session session) {
-        mCurrentSession = session;
-    }
 
     // Strictly to avoid synthetic accessor.
     @NonNull
@@ -328,300 +290,8 @@
         mAppInfo = appInfo;
     }
 
-    @NonNull
-    HostValidator getHostValidator() {
-        if (mHostValidator == null) {
-            mHostValidator = createHostValidator();
-        }
-        return mHostValidator;
-    }
-
-    /**
-     * Used by tests to verify the different behaviors when the app has different api level than
-     * the host.
-     */
     @VisibleForTesting
-    void setHandshakeInfo(@NonNull HandshakeInfo handshakeInfo) {
-        int apiLevel = handshakeInfo.getHostCarAppApiLevel();
-        if (!CarAppApiLevels.isValid(apiLevel)) {
-            throw new IllegalArgumentException("Invalid Car App API level received: " + apiLevel);
-        }
-
-        mHandshakeInfo = handshakeInfo;
-    }
-
-    // Strictly to avoid synthetic accessor.
-    @Nullable
-    HandshakeInfo getHandshakeInfo() {
-        return mHandshakeInfo;
-    }
-
-    @Nullable
-    LifecycleRegistry getLifecycleIfValid() {
-        Session session = getCurrentSession();
-        return session == null ? null : (LifecycleRegistry) session.getLifecycleInternal();
-    }
-
-    @NonNull
-    LifecycleRegistry getLifecycle() {
-        return requireNonNull(getLifecycleIfValid());
-    }
-
-    private static final class CarAppBinder extends ICarApp.Stub {
-        @Nullable private CarAppService mService;
-
-        CarAppBinder(@NonNull CarAppService service) {
-            mService = service;
-        }
-
-        /**
-         * Explicitly mark the binder to be destroyed and remove the reference to the
-         * {@link CarAppService}, and any subsequent call from the host after this would be
-         * considered invalid and throws an exception.
-         *
-         * <p>This is needed because the binder object can outlive the service and will not be
-         * garbage collected until the car host cleans up its side of the binder reference,
-         * causing a leak. See https://github.com/square/leakcanary/issues/1906 for more context
-         * related to this issue.
-         */
-        void destroy() {
-            mService = null;
-        }
-
-        // incompatible argument for parameter context of attachBaseContext.
-        // call to onCreateScreen(android.content.Intent) not allowed on the given receiver.
-        @SuppressWarnings({
-                "nullness:argument.type.incompatible",
-                "nullness:method.invocation.invalid"
-        })
-        @Override
-        public void onAppCreate(
-                ICarHost carHost,
-                Intent intent,
-                Configuration configuration,
-                IOnDoneCallback callback) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "onAppCreate intent: " + intent);
-            }
-
-            RemoteUtils.dispatchCallFromHost(callback, "onAppCreate", () -> {
-                CarAppService service = requireNonNull(mService);
-                Session session = service.getCurrentSession();
-                if (session == null
-                        || service.getLifecycle().getCurrentState() == State.DESTROYED) {
-                    session = service.onCreateSession();
-                    service.setCurrentSession(session);
-                }
-
-                session.configure(service,
-                        requireNonNull(service.getHandshakeInfo()),
-                        requireNonNull(service.getHostInfo()),
-                        carHost, configuration);
-
-                // Whenever the host unbinds, the screens in the stack are destroyed.  If
-                // there is another bind, before the OS has destroyed this Service, then
-                // the stack will be empty, and we need to treat it as a new instance.
-                LifecycleRegistry registry = service.getLifecycle();
-                Lifecycle.State state = registry.getCurrentState();
-                int screenStackSize = session.getCarContext().getCarService(
-                        ScreenManager.class).getScreenStack().size();
-                if (!state.isAtLeast(State.CREATED) || screenStackSize < 1) {
-                    if (Log.isLoggable(TAG, Log.DEBUG)) {
-                        Log.d(TAG, "onAppCreate the app was not yet created or the "
-                                + "screen stack was empty state: "
-                                + registry.getCurrentState()
-                                + ", stack size: " + screenStackSize);
-                    }
-                    registry.handleLifecycleEvent(Event.ON_CREATE);
-                    session.getCarContext().getCarService(ScreenManager.class).push(
-                            session.onCreateScreen(intent));
-                } else {
-                    if (Log.isLoggable(TAG, Log.DEBUG)) {
-                        Log.d(TAG, "onAppCreate the app was already created");
-                    }
-                    onNewIntentInternal(session, intent);
-                }
-                return null;
-            });
-
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "onAppCreate completed");
-            }
-        }
-
-        @Override
-        public void onAppStart(IOnDoneCallback callback) {
-            CarAppService service = requireNonNull(mService);
-            RemoteUtils.dispatchCallFromHost(
-                    service.getLifecycleIfValid(), callback,
-                    "onAppStart", () -> {
-                        service.getLifecycle().handleLifecycleEvent(Event.ON_START);
-                        return null;
-                    });
-        }
-
-        @Override
-        public void onAppResume(IOnDoneCallback callback) {
-            CarAppService service = requireNonNull(mService);
-            RemoteUtils.dispatchCallFromHost(
-                    service.getLifecycleIfValid(), callback,
-                    "onAppResume", () -> {
-                        service.getLifecycle()
-                                .handleLifecycleEvent(Event.ON_RESUME);
-                        return null;
-                    });
-        }
-
-        @Override
-        public void onAppPause(IOnDoneCallback callback) {
-            CarAppService service = requireNonNull(mService);
-            RemoteUtils.dispatchCallFromHost(
-                    service.getLifecycleIfValid(), callback, "onAppPause",
-                    () -> {
-                        service.getLifecycle().handleLifecycleEvent(Event.ON_PAUSE);
-                        return null;
-                    });
-        }
-
-        @Override
-        public void onAppStop(IOnDoneCallback callback) {
-            CarAppService service = requireNonNull(mService);
-            RemoteUtils.dispatchCallFromHost(
-                    service.getLifecycleIfValid(), callback, "onAppStop",
-                    () -> {
-                        service.getLifecycle().handleLifecycleEvent(Event.ON_STOP);
-                        return null;
-                    });
-        }
-
-        @Override
-        public void onNewIntent(Intent intent, IOnDoneCallback callback) {
-            CarAppService service = requireNonNull(mService);
-            RemoteUtils.dispatchCallFromHost(
-                    service.getLifecycleIfValid(),
-                    callback,
-                    "onNewIntent",
-                    () -> {
-                        onNewIntentInternal(requireNonNull(service.getCurrentSession()), intent);
-                        return null;
-                    });
-        }
-
-        @Override
-        public void onConfigurationChanged(Configuration configuration,
-                IOnDoneCallback callback) {
-            CarAppService service = requireNonNull(mService);
-            RemoteUtils.dispatchCallFromHost(
-                    service.getLifecycleIfValid(),
-                    callback,
-                    "onConfigurationChanged",
-                    () -> {
-                        onConfigurationChangedInternal(requireNonNull(service.getCurrentSession()),
-                                configuration);
-                        return null;
-                    });
-        }
-
-        @Override
-        public void getManager(@CarServiceType @NonNull String type,
-                IOnDoneCallback callback) {
-            ThreadUtils.runOnMain(() -> {
-                CarAppService service = requireNonNull(mService);
-                Session session = requireNonNull(service.getCurrentSession());
-                switch (type) {
-                    case CarContext.APP_SERVICE:
-                        RemoteUtils.sendSuccessResponseToHost(
-                                callback,
-                                "getManager",
-                                session.getCarContext().getCarService(
-                                        AppManager.class).getIInterface());
-                        return;
-                    case CarContext.NAVIGATION_SERVICE:
-                        RemoteUtils.sendSuccessResponseToHost(
-                                callback,
-                                "getManager",
-                                session.getCarContext().getCarService(
-                                        NavigationManager.class).getIInterface());
-                        return;
-                    default:
-                        Log.e(TAG, type + "%s is not a valid manager");
-                        RemoteUtils.sendFailureResponseToHost(callback, "getManager",
-                                new InvalidParameterException(
-                                        type + " is not a valid manager type"));
-                }
-            });
-        }
-
-        @Override
-        public void getAppInfo(IOnDoneCallback callback) {
-            try {
-                CarAppService service = requireNonNull(mService);
-                RemoteUtils.sendSuccessResponseToHost(
-                        callback, "getAppInfo", service.getAppInfo());
-            } catch (IllegalArgumentException e) {
-                // getAppInfo() could fail with the specified API version is invalid.
-                RemoteUtils.sendFailureResponseToHost(callback, "getAppInfo", e);
-            }
-        }
-
-        @Override
-        public void onHandshakeCompleted(Bundleable handshakeInfo,
-                IOnDoneCallback callback) {
-            CarAppService service = requireNonNull(mService);
-            try {
-                HandshakeInfo deserializedHandshakeInfo =
-                        (HandshakeInfo) handshakeInfo.get();
-                String packageName = deserializedHandshakeInfo.getHostPackageName();
-                int uid = Binder.getCallingUid();
-                HostInfo hostInfo = new HostInfo(packageName, uid);
-                if (!service.getHostValidator().isValidHost(hostInfo)) {
-                    RemoteUtils.sendFailureResponseToHost(callback, "onHandshakeCompleted",
-                            new IllegalArgumentException("Unknown host '"
-                                    + packageName + "', uid:" + uid));
-                    return;
-                }
-
-                int appMinApiLevel = service.getAppInfo().getMinCarAppApiLevel();
-                int hostApiLevel = deserializedHandshakeInfo.getHostCarAppApiLevel();
-                if (appMinApiLevel > hostApiLevel) {
-                    RemoteUtils.sendFailureResponseToHost(callback, "onHandshakeCompleted",
-                            new IllegalArgumentException(
-                                    "Host API level (" + hostApiLevel + ") is "
-                                            + "less than the app's min API level ("
-                                            + appMinApiLevel + ")"));
-                    return;
-                }
-
-                service.setHostInfo(hostInfo);
-                service.setHandshakeInfo(deserializedHandshakeInfo);
-                RemoteUtils.sendSuccessResponseToHost(callback, "onHandshakeCompleted",
-                        null);
-            } catch (BundlerException | IllegalArgumentException e) {
-                service.setHostInfo(null);
-                RemoteUtils.sendFailureResponseToHost(callback, "onHandshakeCompleted", e);
-            }
-        }
-
-        // call to onNewIntent(android.content.Intent) not allowed on the given receiver.
-        @SuppressWarnings("nullness:method.invocation.invalid")
-        @MainThread
-        private void onNewIntentInternal(Session session, Intent intent) {
-            ThreadUtils.checkMainThread();
-            session.onNewIntent(intent);
-        }
-
-        // call to onCarConfigurationChanged(android.content.res.Configuration) not
-        // allowed on the given receiver.
-        @SuppressWarnings("nullness:method.invocation.invalid")
-        @MainThread
-        private void onConfigurationChangedInternal(Session session,
-                Configuration configuration) {
-            ThreadUtils.checkMainThread();
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "onCarConfigurationChanged configuration: " + configuration);
-            }
-
-            session.onCarConfigurationChangedInternal(configuration);
-        }
+    void setCarAppbinder(@Nullable CarAppBinder carAppbinder) {
+        mBinder = carAppbinder;
     }
 }
diff --git a/car/app/app/src/main/java/androidx/car/app/Session.java b/car/app/app/src/main/java/androidx/car/app/Session.java
index ecbe43c..e95865b 100644
--- a/car/app/app/src/main/java/androidx/car/app/Session.java
+++ b/car/app/app/src/main/java/androidx/car/app/Session.java
@@ -22,6 +22,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RestrictTo;
+import androidx.annotation.VisibleForTesting;
 import androidx.lifecycle.DefaultLifecycleObserver;
 import androidx.lifecycle.Lifecycle;
 import androidx.lifecycle.LifecycleObserver;
@@ -173,12 +174,20 @@
      * events with respect to the {@link Session} and {@link Screen} lifecycles in the correct
      * order.
      */
+    @VisibleForTesting
     @NonNull
     Lifecycle getLifecycleInternal() {
         return mRegistry;
     }
 
     /**
+     * Updates the {@link Session}'s lifecycle.
+     */
+    void handleLifecycleEvent(Lifecycle.Event event) {
+        mRegistry.handleLifecycleEvent(event);
+    }
+
+    /**
      * @hide
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) // used by the testing library.
diff --git a/car/app/app/src/test/java/androidx/car/app/CarAppBinderTest.java b/car/app/app/src/test/java/androidx/car/app/CarAppBinderTest.java
new file mode 100644
index 0000000..7664c96
--- /dev/null
+++ b/car/app/app/src/test/java/androidx/car/app/CarAppBinderTest.java
@@ -0,0 +1,632 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.car.app;
+
+import static androidx.lifecycle.Lifecycle.Event.ON_CREATE;
+import static androidx.lifecycle.Lifecycle.Event.ON_DESTROY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.RemoteException;
+
+import androidx.annotation.NonNull;
+import androidx.car.app.model.ItemList;
+import androidx.car.app.model.PlaceListMapTemplate;
+import androidx.car.app.model.Template;
+import androidx.car.app.navigation.NavigationManager;
+import androidx.car.app.serialization.Bundleable;
+import androidx.car.app.serialization.BundlerException;
+import androidx.car.app.testing.SessionController;
+import androidx.car.app.testing.TestCarContext;
+import androidx.car.app.validation.HostValidator;
+import androidx.car.app.versioning.CarAppApiLevels;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleRegistry;
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.internal.DoNotInstrument;
+
+import java.util.Deque;
+import java.util.Locale;
+
+/** Tests for {@link CarAppBinder} and related classes for establishing a host connection. */
+@RunWith(RobolectricTestRunner.class)
+@DoNotInstrument
+public class CarAppBinderTest {
+    @Mock
+    ICarHost mMockCarHost;
+    @Mock
+    DefaultLifecycleObserver mLifecycleObserver;
+    @Mock
+    IOnDoneCallback mMockOnDoneCallback;
+
+    private TestCarContext mCarContext;
+    private final Template mTemplate =
+            new PlaceListMapTemplate.Builder()
+                    .setTitle("Title")
+                    .setItemList(new ItemList.Builder().build())
+                    .build();
+    @Captor
+    ArgumentCaptor<Bundleable> mBundleableArgumentCaptor;
+
+    private CarAppService mCarAppService;
+    private CarAppBinder mCarAppBinder;
+    private SessionController mSessionController;
+    private Intent mIntentSet;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mCarAppService =
+                new CarAppService() {
+                    @Override
+                    @NonNull
+                    public HostValidator createHostValidator() {
+                        return HostValidator.ALLOW_ALL_HOSTS_VALIDATOR;
+                    }
+
+                    @Override
+                    @NonNull
+                    public Session onCreateSession() {
+                        // Recreate a new CarContext, because the previous one would have been
+                        // destroyed in an unbind-rebind scenario.
+                        mCarContext = TestCarContext.createCarContext(
+                                ApplicationProvider.getApplicationContext());
+                        Session session = createTestSession();
+                        mSessionController = new SessionController(session, mCarContext,
+                                new Intent());
+                        return session;
+                    }
+                };
+
+        AppInfo appInfo = new AppInfo(CarAppApiLevels.getOldest(), CarAppApiLevels.getLatest(),
+                "blah");
+        mCarAppService.setAppInfo(appInfo);
+        mCarAppBinder = new CarAppBinder(mCarAppService);
+        mCarAppService.setCarAppbinder(mCarAppBinder);
+
+        // Sets default handshake and host info. OnAppCreate depends on these being non-null.
+        String hostPackageName = "com.google.projection.gearhead";
+        HandshakeInfo handshakeInfo = new HandshakeInfo(hostPackageName,
+                CarAppApiLevels.getLatest());
+        HostInfo hostInfo = new HostInfo(hostPackageName, 1);
+        mCarAppService.setHostInfo(hostInfo);
+
+        mCarAppBinder.setHandshakeInfo(handshakeInfo);
+    }
+
+    private Session createTestSession() {
+        return new Session() {
+            @NonNull
+            @Override
+            public Screen onCreateScreen(@NonNull Intent intent) {
+                mIntentSet = intent;
+                return new Screen(getCarContext()) {
+                    @Override
+                    @NonNull
+                    public Template onGetTemplate() {
+                        return mTemplate;
+                    }
+                };
+            }
+
+            @Override
+            public void onNewIntent(@NonNull Intent intent) {
+                mIntentSet = intent;
+            }
+        };
+    }
+
+    @Test
+    public void onAppCreate_updatesCarApiLevel() throws RemoteException, BundlerException {
+        String hostPackageName = "com.google.projection.gearhead";
+        int hostApiLevel = CarAppApiLevels.LEVEL_1;
+        HandshakeInfo handshakeInfo = new HandshakeInfo(hostPackageName, hostApiLevel);
+
+        mCarAppBinder.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
+
+        assertThat(
+                mCarAppBinder.getCurrentSession().getCarContext().getCarAppApiLevel()).isEqualTo(
+                hostApiLevel);
+    }
+
+    @Test
+    public void onAppCreate_updatesContextHostInfo()
+            throws RemoteException, BundlerException, InterruptedException {
+        String hostPackageName = "com.google.projection.gearhead";
+        HandshakeInfo handshakeInfo = new HandshakeInfo(hostPackageName, CarAppApiLevels.LEVEL_1);
+
+        mCarAppBinder.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
+
+        assertThat(mCarAppBinder.getCurrentSession()
+                .getCarContext().getHostInfo().getPackageName()).isEqualTo(hostPackageName);
+    }
+
+    @Test
+    public void onAppCreate_createsFirstScreen() throws RemoteException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
+
+        assertThat(
+                mCarAppBinder
+                        .getCurrentSession()
+                        .getCarContext()
+                        .getCarService(ScreenManager.class)
+                        .getTopTemplate()
+                        .getTemplate())
+                .isInstanceOf(PlaceListMapTemplate.class);
+    }
+
+    @Test
+    public void onAppCreate_withIntent_callsWithOnCreateScreenWithIntent() throws
+            RemoteException {
+        Intent intent = new Intent("Foo");
+        mCarAppBinder.onAppCreate(mMockCarHost, intent, new Configuration(), mMockOnDoneCallback);
+
+        assertThat(mIntentSet).isEqualTo(intent);
+        verify(mMockOnDoneCallback).onSuccess(any());
+    }
+
+    @Test
+    public void onAppCreate_alreadyPreviouslyCreated_callsOnNewIntent() throws RemoteException {
+        IOnDoneCallback callback = mock(IOnDoneCallback.class);
+
+        Intent intent = new Intent("Foo");
+        mCarAppBinder.onAppCreate(mMockCarHost, intent, new Configuration(), callback);
+        verify(callback).onSuccess(any());
+
+        IOnDoneCallback callback2 = mock(IOnDoneCallback.class);
+        Intent intent2 = new Intent("Foo2");
+        mCarAppBinder.onAppCreate(mMockCarHost, intent2, new Configuration(), callback2);
+
+        assertThat(mIntentSet).isEqualTo(intent2);
+        verify(callback2).onSuccess(any());
+    }
+
+    @SuppressLint("NewApi")
+    @Test
+    public void onAppCreate_updatesTheConfiguration() throws RemoteException {
+        Configuration configuration = new Configuration();
+        configuration.setToDefaults();
+        configuration.setLocale(Locale.CANADA_FRENCH);
+
+        mCarAppBinder.onAppCreate(mMockCarHost, null, configuration, mock(IOnDoneCallback.class));
+
+        assertThat(mCarContext.getResources().getConfiguration().getLocales().get(0))
+                .isEqualTo(Locale.CANADA_FRENCH);
+    }
+
+    @Test
+    public void onNewIntent_callsOnNewIntentWithIntent() throws RemoteException {
+        Intent intent = new Intent("Foo");
+        mCarAppBinder.onAppCreate(mMockCarHost, intent, new Configuration(),
+                mock(IOnDoneCallback.class));
+
+        Intent intent2 = new Intent("Foo2");
+        mCarAppBinder.onNewIntent(intent2, mMockOnDoneCallback);
+
+        assertThat(mIntentSet).isEqualTo(intent2);
+        verify(mMockOnDoneCallback).onSuccess(any());
+    }
+
+    @Test
+    public void onNewIntent_lifecycleNotCreated_doesNotDispatch_sendsError()
+            throws RemoteException {
+        mCarAppBinder.onNewIntent(new Intent("Foo"), mMockOnDoneCallback);
+
+        assertThat(mIntentSet).isNull();
+        verify(mMockOnDoneCallback).onFailure(any());
+    }
+
+    @Test
+    public void getNavigationManager() throws RemoteException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(),
+                mock(IOnDoneCallback.class));
+
+        assertThat(mCarAppBinder.getCurrentSession().getCarContext().getCarService(
+                NavigationManager.class)).isNotNull();
+    }
+
+    @Test
+    public void onConfigurationChanged_lifecycleNotCreated_returnsAFailure()
+            throws RemoteException {
+        Configuration configuration = new Configuration();
+        configuration.setToDefaults();
+        configuration.setLocale(Locale.CANADA_FRENCH);
+
+        mCarAppBinder.onConfigurationChanged(configuration, mMockOnDoneCallback);
+
+        assertThat(mCarContext).isNull();
+        verify(mMockOnDoneCallback).onFailure(any());
+    }
+
+    @SuppressLint("NewApi")
+    @Test
+    public void onConfigurationChanged_updatesTheConfiguration() throws RemoteException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(),
+                mock(IOnDoneCallback.class));
+
+        Configuration configuration = new Configuration();
+        configuration.setToDefaults();
+        configuration.setLocale(Locale.CANADA_FRENCH);
+
+        mCarAppBinder.onConfigurationChanged(configuration, mMockOnDoneCallback);
+
+        assertThat(mCarContext.getResources().getConfiguration().getLocales().get(0))
+                .isEqualTo(Locale.CANADA_FRENCH);
+        verify(mMockOnDoneCallback).onSuccess(any());
+    }
+
+    @Test
+    public void getAppInfo() throws RemoteException, BundlerException {
+        AppInfo appInfo = new AppInfo(3, 4, "foo");
+        mCarAppService.setAppInfo(appInfo);
+
+        mCarAppBinder.getAppInfo(mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onSuccess(mBundleableArgumentCaptor.capture());
+        AppInfo receivedAppInfo = (AppInfo) mBundleableArgumentCaptor.getValue().get();
+        assertThat(receivedAppInfo.getMinCarAppApiLevel())
+                .isEqualTo(appInfo.getMinCarAppApiLevel());
+        assertThat(receivedAppInfo.getLatestCarAppApiLevel())
+                .isEqualTo(appInfo.getLatestCarAppApiLevel());
+        assertThat(receivedAppInfo.getLibraryDisplayVersion()).isEqualTo(
+                appInfo.getLibraryDisplayVersion());
+    }
+
+    @Test
+    public void onHandshakeCompleted_updatesHostInfo()
+            throws RemoteException, BundlerException, InterruptedException {
+        String hostPackageName = "com.google.projection.gearhead";
+        HandshakeInfo handshakeInfo = new HandshakeInfo(hostPackageName, CarAppApiLevels.LEVEL_1);
+
+        mCarAppBinder.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
+
+        assertThat(mCarAppService.getHostInfo().getPackageName()).isEqualTo(hostPackageName);
+    }
+
+    @Test
+    public void onHandshakeCompleted_updatesHandshakeInfo() throws RemoteException,
+            BundlerException {
+        String hostPackageName = "com.google.projection.gearhead";
+
+        HandshakeInfo handshakeInfo = new HandshakeInfo(hostPackageName, CarAppApiLevels.LEVEL_1);
+        mCarAppBinder.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
+        assertThat(mCarAppBinder.getHandshakeInfo()).isNotNull();
+        assertThat(mCarAppBinder.getHandshakeInfo().getHostCarAppApiLevel()).isEqualTo(
+                handshakeInfo.getHostCarAppApiLevel());
+        assertThat(mCarAppBinder.getHandshakeInfo().getHostPackageName()).isEqualTo(
+                handshakeInfo.getHostPackageName());
+    }
+
+    @Test
+    public void onHandshakeCompleted_lowerThanMinApiLevel_throws() throws BundlerException,
+            RemoteException {
+        AppInfo appInfo = new AppInfo(3, 4, "foo");
+        mCarAppService.setAppInfo(appInfo);
+
+        HandshakeInfo handshakeInfo = new HandshakeInfo("bar",
+                appInfo.getMinCarAppApiLevel() - 1);
+        mCarAppBinder.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onFailure(any());
+    }
+
+    @Test
+    public void onHandshakeCompleted_higherThanCurrentApiLevel_throws() throws BundlerException,
+            RemoteException {
+        AppInfo appInfo = new AppInfo(3, 4, "foo");
+        mCarAppService.setAppInfo(appInfo);
+
+        HandshakeInfo handshakeInfo = new HandshakeInfo("bar",
+                appInfo.getLatestCarAppApiLevel() + 1);
+        mCarAppBinder.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onFailure(any());
+    }
+
+    @Test
+    public void destroy_movesLifecycleStateToDestroyed() throws RemoteException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
+        mCarAppBinder.onAppStart(mMockOnDoneCallback);
+
+        // TODO(b/184154464): this should use the public getLifecycle() after the public
+        // LifecycleRegistry is properly hooked up to the TestLifecycleOwner.
+        mCarAppBinder.getCurrentSession().getLifecycleInternal().addObserver(mLifecycleObserver);
+
+        mCarAppBinder.destroy();
+
+        verify(mLifecycleObserver).onDestroy(any());
+    }
+
+    @Test
+    public void onDestroyLifecycle_onCreate_callsOnCreateScreen() throws RemoteException,
+            BundlerException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
+        mCarAppBinder.onAppStart(mMockOnDoneCallback);
+
+        Session currentSession = mCarAppBinder.getCurrentSession();
+        // TODO(b/184154464): this should use the public getLifecycle() after the public
+        // LifecycleRegistry is properly hooked up to the TestLifecycleOwner.
+        currentSession.getLifecycleInternal().addObserver(mLifecycleObserver);
+        mCarAppBinder.onDestroyLifecycle();
+
+        verify(mLifecycleObserver).onDestroy(any());
+
+        assertThat(currentSession.getCarContext().getCarService(
+                ScreenManager.class).getScreenStack()).isEmpty();
+        assertThat(mCarAppBinder.getCurrentSession()).isNull();
+
+        String hostPackageName = "com.google.projection.gearhead";
+        int hostApiLevel = CarAppApiLevels.LEVEL_1;
+        HandshakeInfo handshakeInfo = new HandshakeInfo(hostPackageName, hostApiLevel);
+        mCarAppBinder.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
+
+        currentSession = mCarAppBinder.getCurrentSession();
+        assertThat(currentSession.getCarContext().getCarService(
+                ScreenManager.class).getScreenStack()).hasSize(1);
+    }
+
+    @Test
+    public void onDestroyLifecycle_clearsScreenStack() throws RemoteException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
+
+        Deque<Screen> screenStack =
+                mCarAppBinder.getCurrentSession().getCarContext().getCarService(
+                        ScreenManager.class).getScreenStack();
+        assertThat(screenStack).hasSize(1);
+
+        Screen screen = screenStack.getFirst();
+        assertThat(screen.getLifecycle().getCurrentState()).isAtLeast(Lifecycle.State.CREATED);
+
+        mCarAppBinder.onDestroyLifecycle();
+
+        assertThat(screenStack).isEmpty();
+        assertThat(screen.getLifecycle().getCurrentState()).isEqualTo(Lifecycle.State.DESTROYED);
+    }
+
+    @Test
+    public void onNewIntent_callsSessionIntent() throws
+            RemoteException {
+        // onAppCreate must be called first to create the Session before onNewIntent.
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(),
+                mock(IOnDoneCallback.class));
+        assertThat(mIntentSet).isNull();
+
+        Intent intent = new Intent("Foo");
+        mCarAppBinder.onNewIntent(intent, mMockOnDoneCallback);
+
+        assertThat(mIntentSet).isEqualTo(intent);
+        verify(mMockOnDoneCallback).onSuccess(any());
+    }
+
+    @Test
+    public void onNewIntent_notAtLeastCreated_doesCallSessionIntent_sendsFailure() throws
+            RemoteException {
+        Intent intent = new Intent("Foo");
+        mCarAppBinder.onNewIntent(intent, mMockOnDoneCallback);
+
+        assertThat(mIntentSet).isNull();
+        verify(mMockOnDoneCallback).onFailure(any());
+    }
+
+    @Test
+    public void onNewIntent_destroyed_doesCallSessionIntent_sendsFailure() throws
+            RemoteException {
+        // onAppCreate must be called first to create the Session before onNewIntent.
+        Intent intent1 = new Intent();
+        mCarAppBinder.onAppCreate(mMockCarHost, intent1, new Configuration(),
+                mock(IOnDoneCallback.class));
+        assertThat(mIntentSet).isEqualTo(intent1);
+
+        mCarContext.getLifecycleOwner().mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
+
+        Intent intent2 = new Intent("Foo");
+        mCarAppBinder.onNewIntent(intent2, mMockOnDoneCallback);
+
+        assertThat(mIntentSet).isEqualTo(intent1);
+        verify(mMockOnDoneCallback).onFailure(any());
+    }
+
+    @Test
+    public void onAppStart_movesLifecycle() throws RemoteException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(),
+                mock(IOnDoneCallback.class));
+
+        mCarAppBinder.onAppStart(mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onSuccess(any());
+        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
+                Lifecycle.State.STARTED);
+    }
+
+    @Test
+    public void onAppStart_notAtLeastCreated_doesNotMoveLifecycle_sendsFailure()
+            throws RemoteException {
+        mCarAppBinder.onAppStart(mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onFailure(any());
+        assertThat(mCarContext).isNull();
+    }
+
+    @Test
+    public void onAppStart_destroyed_doesNotMoveLifecycle_sendsFailure()
+            throws RemoteException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(),
+                mock(IOnDoneCallback.class));
+        mCarContext.getLifecycleOwner().mRegistry.setCurrentState(Lifecycle.State.DESTROYED);
+
+        mCarAppBinder.onAppStart(mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onFailure(any());
+        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
+                Lifecycle.State.DESTROYED);
+    }
+
+    @Test
+    public void onAppResume_movesLifecycle() throws RemoteException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(),
+                mock(IOnDoneCallback.class));
+
+        mCarAppBinder.onAppResume(mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onSuccess(any());
+        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
+                Lifecycle.State.RESUMED);
+    }
+
+    @Test
+    public void onAppResume_notAtLeastCreated_doesNotMoveLifecycle_sendsFailure()
+            throws RemoteException {
+        mCarAppBinder.onAppResume(mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onFailure(any());
+        assertThat(mCarContext).isNull();
+    }
+
+    @Test
+    public void onAppResume_destroyed_doesNotMoveLifecycle_sendsFailure()
+            throws RemoteException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(),
+                mock(IOnDoneCallback.class));
+        mCarContext.getLifecycleOwner().mRegistry.setCurrentState(Lifecycle.State.DESTROYED);
+
+        mCarAppBinder.onAppResume(mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onFailure(any());
+        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
+                Lifecycle.State.DESTROYED);
+    }
+
+    @Test
+    public void onAppPause_movesLifecycle() throws RemoteException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(),
+                mock(IOnDoneCallback.class));
+
+        mCarAppBinder.onAppPause(mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onSuccess(any());
+        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
+                Lifecycle.State.STARTED);
+    }
+
+    @Test
+    public void onAppPause_notAtLeastCreated_doesNotMoveLifecycle_sendsFailure()
+            throws RemoteException {
+        mCarAppBinder.onAppPause(mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onFailure(any());
+        assertThat(mCarContext).isNull();
+    }
+
+    @Test
+    public void onAppPause_destroyed_doesNotMoveLifecycle_sendsFailure()
+            throws RemoteException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(),
+                mock(IOnDoneCallback.class));
+        mCarContext.getLifecycleOwner().mRegistry.setCurrentState(Lifecycle.State.DESTROYED);
+
+        mCarAppBinder.onAppPause(mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onFailure(any());
+        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
+                Lifecycle.State.DESTROYED);
+    }
+
+    @Test
+    public void onAppStop_movesLifecycle() throws RemoteException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(),
+                mock(IOnDoneCallback.class));
+
+        mCarAppBinder.onAppStop(mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onSuccess(any());
+        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
+                Lifecycle.State.CREATED);
+    }
+
+    @Test
+    public void onAppStop_notAtLeastCreated_doesNotMoveLifecycle_sendsFailure()
+            throws RemoteException {
+        mCarAppBinder.onAppStop(mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onFailure(any());
+        assertThat(mCarContext).isNull();
+    }
+
+    @Test
+    public void onAppStop_destroyed_doesNotMoveLifecycle_sendsFailure()
+            throws RemoteException {
+        mCarAppBinder.onAppCreate(mMockCarHost, null, new Configuration(),
+                mock(IOnDoneCallback.class));
+        mCarContext.getLifecycleOwner().mRegistry.setCurrentState(Lifecycle.State.DESTROYED);
+
+        mCarAppBinder.onAppStop(mMockOnDoneCallback);
+
+        verify(mMockOnDoneCallback).onFailure(any());
+        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
+                Lifecycle.State.DESTROYED);
+    }
+
+    @Test
+    public void session_screen_lifecycleEvents_inCorrectOrder()
+            throws RemoteException {
+        // We have to manually create the Session here instead of rely on using ICarApp because
+        // of two issues:
+        // 1. If we inject a TestCarContext, it will overwrite a TestLifeCycleOwner instance that
+        // is different than the one the ScreenManager used to register a listener to.
+        // 2. If we don't inject a TestCarContext, the existing logic of ICarApp in CarAppService
+        // throws a NPE when trying to update the configuration of the Session/CarContext.
+        Session session = createTestSession();
+        ((LifecycleRegistry) session.getLifecycleInternal()).handleLifecycleEvent(ON_CREATE);
+        Screen screen = session.onCreateScreen(new Intent());
+        session.getCarContext().getCarService(ScreenManager.class).push(screen);
+
+        DefaultLifecycleObserver sessionObserver = mock(DefaultLifecycleObserver.class);
+        DefaultLifecycleObserver screenObserver = mock(DefaultLifecycleObserver.class);
+        session.getLifecycle().addObserver(sessionObserver);
+        screen.getLifecycle().addObserver(screenObserver);
+
+        ((LifecycleRegistry) session.getLifecycleInternal()).handleLifecycleEvent(ON_DESTROY);
+        InOrder inOrder = inOrder(screenObserver, sessionObserver);
+        inOrder.verify(sessionObserver).onCreate(any());
+        inOrder.verify(screenObserver).onCreate(any());
+        inOrder.verify(screenObserver).onDestroy(any());
+        inOrder.verify(sessionObserver).onDestroy(any());
+    }
+}
diff --git a/car/app/app/src/test/java/androidx/car/app/CarAppServiceTest.java b/car/app/app/src/test/java/androidx/car/app/CarAppServiceTest.java
index d5a69b1..9cc0d83 100644
--- a/car/app/app/src/test/java/androidx/car/app/CarAppServiceTest.java
+++ b/car/app/app/src/test/java/androidx/car/app/CarAppServiceTest.java
@@ -16,50 +16,27 @@
 
 package androidx.car.app;
 
-import static androidx.lifecycle.Lifecycle.Event.ON_CREATE;
-import static androidx.lifecycle.Lifecycle.Event.ON_DESTROY;
-
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
+import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
-import android.os.RemoteException;
 
 import androidx.annotation.NonNull;
 import androidx.car.app.model.ItemList;
 import androidx.car.app.model.PlaceListMapTemplate;
 import androidx.car.app.model.Template;
-import androidx.car.app.navigation.NavigationManager;
-import androidx.car.app.serialization.Bundleable;
-import androidx.car.app.serialization.BundlerException;
-import androidx.car.app.testing.SessionController;
-import androidx.car.app.testing.TestCarContext;
 import androidx.car.app.validation.HostValidator;
 import androidx.car.app.versioning.CarAppApiLevels;
-import androidx.lifecycle.DefaultLifecycleObserver;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleRegistry;
-import androidx.test.core.app.ApplicationProvider;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.internal.DoNotInstrument;
 
-import java.util.Deque;
-import java.util.Locale;
-
 
 /** Tests for {@link CarAppService} and related classes for establishing a host connection. */
 @RunWith(RobolectricTestRunner.class)
@@ -68,11 +45,8 @@
     @Mock
     ICarHost mMockCarHost;
     @Mock
-    DefaultLifecycleObserver mLifecycleObserver;
-    @Mock
     IOnDoneCallback mMockOnDoneCallback;
 
-    private TestCarContext mCarContext;
     private final Template mTemplate =
             new PlaceListMapTemplate.Builder()
                     .setTitle("Title")
@@ -80,10 +54,6 @@
                     .build();
 
     private CarAppService mCarAppService;
-    private Intent mIntentSet;
-    private SessionController mSessionController;
-    @Captor
-    ArgumentCaptor<Bundleable> mBundleableArgumentCaptor;
 
     @Before
     public void setUp() {
@@ -101,27 +71,12 @@
                     public Session onCreateSession() {
                         // Recreate a new CarContext, because the previous one would have been
                         // destroyed in an unbind-rebind scenario.
-                        mCarContext = TestCarContext.createCarContext(
-                                ApplicationProvider.getApplicationContext());
-                        Session session = createTestSession();
-                        mSessionController = new SessionController(session, mCarContext,
-                                new Intent());
-                        return session;
+                        return createTestSession();
                     }
                 };
-
-        AppInfo appInfo = new AppInfo(CarAppApiLevels.getOldest(), CarAppApiLevels.getLatest(),
-                "blah");
-        mCarAppService.onCreate();
-        mCarAppService.setAppInfo(appInfo);
-
-        // Sets default handshake and host info. OnAppCreate depends on these being non-null.
-        String hostPackageName = "com.google.projection.gearhead";
-        HandshakeInfo handshakeInfo = new HandshakeInfo(hostPackageName,
-                CarAppApiLevels.getLatest());
-        HostInfo hostInfo = new HostInfo(hostPackageName, 1);
+        HostInfo hostInfo = new HostInfo("foo", 1);
         mCarAppService.setHostInfo(hostInfo);
-        mCarAppService.setHandshakeInfo(handshakeInfo);
+        mCarAppService.onCreate();
     }
 
     private Session createTestSession() {
@@ -129,7 +84,6 @@
             @NonNull
             @Override
             public Screen onCreateScreen(@NonNull Intent intent) {
-                mIntentSet = intent;
                 return new Screen(getCarContext()) {
                     @Override
                     @NonNull
@@ -140,530 +94,25 @@
             }
 
             @Override
-            public void onNewIntent(@NonNull Intent intent) {
-                mIntentSet = intent;
-            }
+            void configure(@NonNull Context baseContext,
+                    @NonNull HandshakeInfo handshakeInfo,
+                    @NonNull HostInfo hostInfo,
+                    @NonNull ICarHost carHost,
+                    @NonNull Configuration configuration) {}
         };
     }
 
     @Test
-    public void onAppCreate_updatesCarApiLevel() throws RemoteException, BundlerException {
-        String hostPackageName = "com.google.projection.gearhead";
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        int hostApiLevel = CarAppApiLevels.LEVEL_1;
-        HandshakeInfo handshakeInfo = new HandshakeInfo(hostPackageName, hostApiLevel);
-
-        mCarAppService.setCurrentSession(null);
-        carApp.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
-
-        assertThat(
-                mCarAppService.getCurrentSession().getCarContext().getCarAppApiLevel()).isEqualTo(
-                hostApiLevel);
-    }
-
-    @Test
-    public void onAppCreate_updatesContextHostInfo()
-            throws RemoteException, BundlerException, InterruptedException {
-        String hostPackageName = "com.google.projection.gearhead";
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        HandshakeInfo handshakeInfo = new HandshakeInfo(hostPackageName, CarAppApiLevels.LEVEL_1);
-
-        mCarAppService.setCurrentSession(null);
-        carApp.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
-
-        assertThat(mCarAppService.getCurrentSession()
-                .getCarContext().getHostInfo().getPackageName()).isEqualTo(hostPackageName);
-    }
-
-    @Test
-    public void onAppCreate_createsFirstScreen() throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
-
-        assertThat(
-                mCarAppService
-                        .getCurrentSession()
-                        .getCarContext()
-                        .getCarService(ScreenManager.class)
-                        .getTopTemplate()
-                        .getTemplate())
-                .isInstanceOf(PlaceListMapTemplate.class);
-    }
-
-    @Test
-    public void onAppCreate_withIntent_callsWithOnCreateScreenWithIntent() throws
-            RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        Intent intent = new Intent("Foo");
-        carApp.onAppCreate(mMockCarHost, intent, new Configuration(), mMockOnDoneCallback);
-
-        assertThat(mIntentSet).isEqualTo(intent);
-        verify(mMockOnDoneCallback).onSuccess(any());
-    }
-
-    @Test
-    public void onAppCreate_alreadyPreviouslyCreated_callsOnNewIntent() throws RemoteException {
-        IOnDoneCallback callback = mock(IOnDoneCallback.class);
-
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        Intent intent = new Intent("Foo");
-        carApp.onAppCreate(mMockCarHost, intent, new Configuration(), callback);
-        verify(callback).onSuccess(any());
-
-        IOnDoneCallback callback2 = mock(IOnDoneCallback.class);
-        Intent intent2 = new Intent("Foo2");
-        carApp.onAppCreate(mMockCarHost, intent2, new Configuration(), callback2);
-
-        assertThat(mIntentSet).isEqualTo(intent2);
-        verify(callback2).onSuccess(any());
-    }
-
-    @Test
-    public void onAppCreate_updatesTheConfiguration() throws RemoteException {
-        Configuration configuration = new Configuration();
-        configuration.setToDefaults();
-        configuration.setLocale(Locale.CANADA_FRENCH);
-
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, configuration, mock(IOnDoneCallback.class));
-
-        assertThat(mCarContext.getResources().getConfiguration().getLocales().get(0))
-                .isEqualTo(Locale.CANADA_FRENCH);
-    }
-
-    @Test
-    public void onNewIntent_callsOnNewIntentWithIntent() throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        Intent intent = new Intent("Foo");
-        carApp.onAppCreate(mMockCarHost, intent, new Configuration(), mock(IOnDoneCallback.class));
-
-        Intent intent2 = new Intent("Foo2");
-        carApp.onNewIntent(intent2, mMockOnDoneCallback);
-
-        assertThat(mIntentSet).isEqualTo(intent2);
-        verify(mMockOnDoneCallback).onSuccess(any());
-    }
-
-    @Test
-    public void onNewIntent_lifecycleNotCreated_doesNotDispatch_sendsError()
-            throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        carApp.onNewIntent(new Intent("Foo"), mMockOnDoneCallback);
-
-        assertThat(mIntentSet).isNull();
-        verify(mMockOnDoneCallback).onFailure(any());
-    }
-
-    @Test
-    public void getNavigationManager() throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mock(IOnDoneCallback.class));
-
-        assertThat(mCarAppService.getCurrentSession().getCarContext().getCarService(
-                NavigationManager.class)).isNotNull();
-    }
-
-    @Test
-    public void onConfigurationChanged_lifecycleNotCreated_returnsAFailure()
-            throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        Configuration configuration = new Configuration();
-        configuration.setToDefaults();
-        configuration.setLocale(Locale.CANADA_FRENCH);
-
-        carApp.onConfigurationChanged(configuration, mMockOnDoneCallback);
-
-        assertThat(mCarContext).isNull();
-        verify(mMockOnDoneCallback).onFailure(any());
-    }
-
-    @Test
-    public void onConfigurationChanged_updatesTheConfiguration() throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mock(IOnDoneCallback.class));
-
-        Configuration configuration = new Configuration();
-        configuration.setToDefaults();
-        configuration.setLocale(Locale.CANADA_FRENCH);
-
-        carApp.onConfigurationChanged(configuration, mMockOnDoneCallback);
-
-        assertThat(mCarContext.getResources().getConfiguration().getLocales().get(0))
-                .isEqualTo(Locale.CANADA_FRENCH);
-        verify(mMockOnDoneCallback).onSuccess(any());
-    }
-
-    @Test
-    public void getAppInfo() throws RemoteException, BundlerException {
-        AppInfo appInfo = new AppInfo(3, 4, "foo");
-        mCarAppService.setAppInfo(appInfo);
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        carApp.getAppInfo(mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onSuccess(mBundleableArgumentCaptor.capture());
-        AppInfo receivedAppInfo = (AppInfo) mBundleableArgumentCaptor.getValue().get();
-        assertThat(receivedAppInfo.getMinCarAppApiLevel())
-                .isEqualTo(appInfo.getMinCarAppApiLevel());
-        assertThat(receivedAppInfo.getLatestCarAppApiLevel())
-                .isEqualTo(appInfo.getLatestCarAppApiLevel());
-        assertThat(receivedAppInfo.getLibraryDisplayVersion()).isEqualTo(
-                appInfo.getLibraryDisplayVersion());
-    }
-
-    @Test
-    public void onHandshakeCompleted_updatesHostInfo()
-            throws RemoteException, BundlerException, InterruptedException {
-        String hostPackageName = "com.google.projection.gearhead";
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        HandshakeInfo handshakeInfo = new HandshakeInfo(hostPackageName, CarAppApiLevels.LEVEL_1);
-
-        carApp.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
-
-        assertThat(mCarAppService.getHostInfo().getPackageName()).isEqualTo(hostPackageName);
-    }
-
-    @Test
-    public void onHandshakeCompleted_updatesHandshakeInfo() throws RemoteException,
-            BundlerException {
-        String hostPackageName = "com.google.projection.gearhead";
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        HandshakeInfo handshakeInfo = new HandshakeInfo(hostPackageName, CarAppApiLevels.LEVEL_1);
-        carApp.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
-        assertThat(mCarAppService.getHandshakeInfo()).isNotNull();
-        assertThat(mCarAppService.getHandshakeInfo().getHostCarAppApiLevel()).isEqualTo(
-                handshakeInfo.getHostCarAppApiLevel());
-        assertThat(mCarAppService.getHandshakeInfo().getHostPackageName()).isEqualTo(
-                handshakeInfo.getHostPackageName());
-    }
-
-    @Test
-    public void onHandshakeCompleted_lowerThanMinApiLevel_throws() throws BundlerException,
-            RemoteException {
-        AppInfo appInfo = new AppInfo(3, 4, "foo");
-        mCarAppService.setAppInfo(appInfo);
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        HandshakeInfo handshakeInfo = new HandshakeInfo("bar",
-                appInfo.getMinCarAppApiLevel() - 1);
-        carApp.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onFailure(any());
-    }
-
-    @Test
-    public void onHandshakeCompleted_higherThanCurrentApiLevel_throws() throws BundlerException,
-            RemoteException {
-        AppInfo appInfo = new AppInfo(3, 4, "foo");
-        mCarAppService.setAppInfo(appInfo);
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        HandshakeInfo handshakeInfo = new HandshakeInfo("bar",
-                appInfo.getLatestCarAppApiLevel() + 1);
-        carApp.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onFailure(any());
-    }
-
-    @Test
-    public void onUnbind_movesLifecycleStateToDestroyed() throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
+    public void onUnbind_destroysSession() {
+        CarAppBinder carApp = (CarAppBinder) mCarAppService.onBind(null);
+        carApp.setHandshakeInfo(new HandshakeInfo("foo",
+                CarAppApiLevels.getLatest()));
         carApp.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
         carApp.onAppStart(mMockOnDoneCallback);
 
-        // TODO(b/184154464): this should use the public getLifecycle() after the public
-        // LifecycleRegistry is properly hooked up to the TestLifecycleOwner.
-        mCarAppService.getCurrentSession().getLifecycleInternal().addObserver(mLifecycleObserver);
-
+        assertThat(carApp.getCurrentSession()).isNotNull();
         assertThat(mCarAppService.onUnbind(null)).isTrue();
 
-        verify(mLifecycleObserver).onDestroy(any());
-    }
-
-    @Test
-    public void onUnbind_rebind_callsOnCreateScreen() throws RemoteException, BundlerException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
-        carApp.onAppStart(mMockOnDoneCallback);
-
-        Session currentSession = mCarAppService.getCurrentSession();
-        // TODO(b/184154464): this should use the public getLifecycle() after the public
-        // LifecycleRegistry is properly hooked up to the TestLifecycleOwner.
-        currentSession.getLifecycleInternal().addObserver(mLifecycleObserver);
-        assertThat(mCarAppService.onUnbind(null)).isTrue();
-
-        verify(mLifecycleObserver).onDestroy(any());
-
-        assertThat(currentSession.getCarContext().getCarService(
-                ScreenManager.class).getScreenStack()).isEmpty();
-        assertThat(mCarAppService.getCurrentSession()).isNull();
-
-        String hostPackageName = "com.google.projection.gearhead";
-        int hostApiLevel = CarAppApiLevels.LEVEL_1;
-        HandshakeInfo handshakeInfo = new HandshakeInfo(hostPackageName, hostApiLevel);
-        carApp.onHandshakeCompleted(Bundleable.create(handshakeInfo), mMockOnDoneCallback);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
-
-        currentSession = mCarAppService.getCurrentSession();
-        assertThat(currentSession.getCarContext().getCarService(
-                ScreenManager.class).getScreenStack()).hasSize(1);
-    }
-
-    @Test
-    public void onUnbind_clearsScreenStack() throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
-
-        Deque<Screen> screenStack =
-                mCarAppService.getCurrentSession().getCarContext().getCarService(
-                        ScreenManager.class).getScreenStack();
-        assertThat(screenStack).hasSize(1);
-
-        Screen screen = screenStack.getFirst();
-        assertThat(screen.getLifecycle().getCurrentState()).isAtLeast(Lifecycle.State.CREATED);
-
-        mCarAppService.onUnbind(null);
-
-        assertThat(screenStack).isEmpty();
-        assertThat(screen.getLifecycle().getCurrentState()).isEqualTo(Lifecycle.State.DESTROYED);
-    }
-
-    @Test
-    public void finish() throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mMockOnDoneCallback);
-
-        mCarAppService.getCurrentSession().getCarContext().finishCarApp();
-
-        assertThat(mCarContext.hasCalledFinishCarApp()).isTrue();
-    }
-
-    @Test
-    public void onNewIntent_callsSessionIntent() throws
-            RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        // onAppCreate must be called first to create the Session before onNewIntent.
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mock(IOnDoneCallback.class));
-        assertThat(mIntentSet).isNull();
-
-        Intent intent = new Intent("Foo");
-        carApp.onNewIntent(intent, mMockOnDoneCallback);
-
-        assertThat(mIntentSet).isEqualTo(intent);
-        verify(mMockOnDoneCallback).onSuccess(any());
-    }
-
-    @Test
-    public void onNewIntent_notAtLeastCreated_doesCallSessionIntent_sendsFailure() throws
-            RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        Intent intent = new Intent("Foo");
-        carApp.onNewIntent(intent, mMockOnDoneCallback);
-
-        assertThat(mIntentSet).isNull();
-        verify(mMockOnDoneCallback).onFailure(any());
-    }
-
-    @Test
-    public void onNewIntent_destroyed_doesCallSessionIntent_sendsFailure() throws
-            RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        // onAppCreate must be called first to create the Session before onNewIntent.
-        Intent intent1 = new Intent();
-        carApp.onAppCreate(mMockCarHost, intent1, new Configuration(), mock(IOnDoneCallback.class));
-        assertThat(mIntentSet).isEqualTo(intent1);
-
-        mCarContext.getLifecycleOwner().mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
-
-        Intent intent2 = new Intent("Foo");
-        carApp.onNewIntent(intent2, mMockOnDoneCallback);
-
-        assertThat(mIntentSet).isEqualTo(intent1);
-        verify(mMockOnDoneCallback).onFailure(any());
-    }
-
-    @Test
-    public void onAppStart_movesLifecycle() throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mock(IOnDoneCallback.class));
-
-        carApp.onAppStart(mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onSuccess(any());
-        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
-                Lifecycle.State.STARTED);
-    }
-
-    @Test
-    public void onAppStart_notAtLeastCreated_doesNotMoveLifecycle_sendsFailure()
-            throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        carApp.onAppStart(mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onFailure(any());
-        assertThat(mCarContext).isNull();
-    }
-
-    @Test
-    public void onAppStart_destroyed_doesNotMoveLifecycle_sendsFailure()
-            throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mock(IOnDoneCallback.class));
-        mCarContext.getLifecycleOwner().mRegistry.setCurrentState(Lifecycle.State.DESTROYED);
-
-        carApp.onAppStart(mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onFailure(any());
-        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
-                Lifecycle.State.DESTROYED);
-    }
-
-    @Test
-    public void onAppResume_movesLifecycle() throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mock(IOnDoneCallback.class));
-
-        carApp.onAppResume(mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onSuccess(any());
-        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
-                Lifecycle.State.RESUMED);
-    }
-
-    @Test
-    public void onAppResume_notAtLeastCreated_doesNotMoveLifecycle_sendsFailure()
-            throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        carApp.onAppResume(mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onFailure(any());
-        assertThat(mCarContext).isNull();
-    }
-
-    @Test
-    public void onAppResume_destroyed_doesNotMoveLifecycle_sendsFailure()
-            throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mock(IOnDoneCallback.class));
-        mCarContext.getLifecycleOwner().mRegistry.setCurrentState(Lifecycle.State.DESTROYED);
-
-        carApp.onAppResume(mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onFailure(any());
-        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
-                Lifecycle.State.DESTROYED);
-    }
-
-    @Test
-    public void onAppPause_movesLifecycle() throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mock(IOnDoneCallback.class));
-
-        carApp.onAppPause(mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onSuccess(any());
-        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
-                Lifecycle.State.STARTED);
-    }
-
-    @Test
-    public void onAppPause_notAtLeastCreated_doesNotMoveLifecycle_sendsFailure()
-            throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        carApp.onAppPause(mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onFailure(any());
-        assertThat(mCarContext).isNull();
-    }
-
-    @Test
-    public void onAppPause_destroyed_doesNotMoveLifecycle_sendsFailure()
-            throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mock(IOnDoneCallback.class));
-        mCarContext.getLifecycleOwner().mRegistry.setCurrentState(Lifecycle.State.DESTROYED);
-
-        carApp.onAppPause(mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onFailure(any());
-        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
-                Lifecycle.State.DESTROYED);
-    }
-
-    @Test
-    public void onAppStop_movesLifecycle() throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mock(IOnDoneCallback.class));
-
-        carApp.onAppStop(mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onSuccess(any());
-        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
-                Lifecycle.State.CREATED);
-    }
-
-    @Test
-    public void onAppStop_notAtLeastCreated_doesNotMoveLifecycle_sendsFailure()
-            throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-
-        carApp.onAppStop(mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onFailure(any());
-        assertThat(mCarContext).isNull();
-    }
-
-    @Test
-    public void onAppStop_destroyed_doesNotMoveLifecycle_sendsFailure()
-            throws RemoteException {
-        ICarApp carApp = (ICarApp) mCarAppService.onBind(null);
-        carApp.onAppCreate(mMockCarHost, null, new Configuration(), mock(IOnDoneCallback.class));
-        mCarContext.getLifecycleOwner().mRegistry.setCurrentState(Lifecycle.State.DESTROYED);
-
-        carApp.onAppStop(mMockOnDoneCallback);
-
-        verify(mMockOnDoneCallback).onFailure(any());
-        assertThat(mCarContext.getLifecycleOwner().mRegistry.getCurrentState()).isEqualTo(
-                Lifecycle.State.DESTROYED);
-    }
-
-    @Test
-    public void session_screen_lifecycleEvents_inCorrectOrder()
-            throws RemoteException {
-        // We have to manually create the Session here instead of rely on using ICarApp because
-        // of two issues:
-        // 1. If we inject a TestCarContext, it will overwrite a TestLifeCycleOwner instance that
-        // is different than the one the ScreenManager used to register a listener to.
-        // 2. If we don't inject a TestCarContext, the existing logic of ICarApp in CarAppService
-        // throws a NPE when trying to update the configuration of the Session/CarContext.
-        Session session = createTestSession();
-        ((LifecycleRegistry) session.getLifecycleInternal()).handleLifecycleEvent(ON_CREATE);
-        Screen screen = session.onCreateScreen(new Intent());
-        session.getCarContext().getCarService(ScreenManager.class).push(screen);
-
-        DefaultLifecycleObserver sessionObserver = mock(DefaultLifecycleObserver.class);
-        DefaultLifecycleObserver screenObserver = mock(DefaultLifecycleObserver.class);
-        session.getLifecycle().addObserver(sessionObserver);
-        screen.getLifecycle().addObserver(screenObserver);
-
-        ((LifecycleRegistry) session.getLifecycleInternal()).handleLifecycleEvent(ON_DESTROY);
-        InOrder inOrder = inOrder(screenObserver, sessionObserver);
-        inOrder.verify(sessionObserver).onCreate(any());
-        inOrder.verify(screenObserver).onCreate(any());
-        inOrder.verify(screenObserver).onDestroy(any());
-        inOrder.verify(sessionObserver).onDestroy(any());
+        assertThat(carApp.getCurrentSession()).isNull();
     }
 }
diff --git a/collection/integration-tests/testapp/src/main/java/androidx/collection/integration/ArraySetJava.java b/collection/integration-tests/testapp/src/main/java/androidx/collection/integration/ArraySetJava.java
new file mode 100644
index 0000000..7962e26
--- /dev/null
+++ b/collection/integration-tests/testapp/src/main/java/androidx/collection/integration/ArraySetJava.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.collection.integration;
+
+import androidx.collection.ArraySet;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+
+/**
+ * Integration (actually build) test for source compatibility for usages of ArraySet.
+ */
+public class ArraySetJava {
+    private ArraySetJava() {
+    }
+
+    @SuppressWarnings("unused")
+    public static boolean sourceCompatibility() {
+        //noinspection UnusedAssignment
+        ArraySet<Integer> arraySet = new ArraySet<>();
+        arraySet = new ArraySet<>(5);
+        //noinspection UnusedAssignment
+        arraySet = new ArraySet<>(arraySet);
+        //noinspection UnusedAssignment
+        arraySet = new ArraySet<>(new HashSet<>());
+        arraySet = new ArraySet<>(new Integer[5]);
+
+        arraySet.clear();
+        arraySet.ensureCapacity(10);
+        arraySet.addAll(new ArraySet<>());
+        arraySet.removeAll(new ArraySet<>());
+
+        for (Integer item : arraySet) {
+            System.out.println(item);
+        }
+
+        //noinspection MismatchedQueryAndUpdateOfCollection
+        ArraySet<Integer> other = new ArraySet<>();
+        //noinspection MismatchedQueryAndUpdateOfCollection
+        ArrayList<Integer> otherList = new ArrayList<>();
+
+        //noinspection Since15,ConstantConditions,ExcessiveRangeCheck,NewObjectEquality
+        return arraySet.remove(0) && arraySet.isEmpty() && arraySet.removeAll(other)
+                && arraySet.removeAt(0) == 0 && arraySet.contains(0) && arraySet.size() == 0
+                && arraySet.isEmpty() && arraySet.toArray() == arraySet.toArray(new Object[5])
+                && arraySet == new Object()
+                && arraySet.toArray() == arraySet.toArray(new Integer[5])
+                && arraySet.toArray(value -> new Object[5]) == null
+                && arraySet.containsAll(otherList);
+    }
+}
diff --git a/collection/integration-tests/testapp/src/main/kotlin/androidx/collection/integration/ArraySetKotlin.kt b/collection/integration-tests/testapp/src/main/kotlin/androidx/collection/integration/ArraySetKotlin.kt
new file mode 100644
index 0000000..697d04e
--- /dev/null
+++ b/collection/integration-tests/testapp/src/main/kotlin/androidx/collection/integration/ArraySetKotlin.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.collection.integration
+
+import androidx.collection.ArraySet
+import java.util.function.IntFunction
+
+/**
+ * Integration (actually build) test for source compatibility for usages of ArraySet.
+ */
+@Suppress("unused")
+fun arraySetSourceCompatibility(): Boolean {
+    @Suppress("VARIABLE_WITH_REDUNDANT_INITIALIZER")
+    var arraySet: ArraySet<Int> = ArraySet()
+    arraySet = ArraySet<Int>(5)
+    @Suppress("UNUSED_VALUE")
+    arraySet = ArraySet(arraySet)
+    @Suppress("UNUSED_VALUE")
+    arraySet = ArraySet(setOf())
+    arraySet = ArraySet(arrayOf())
+
+    arraySet.clear()
+    arraySet.ensureCapacity(10)
+
+    for (item in arraySet) {
+        println(item)
+    }
+
+    @Suppress("RedundantSamConstructor", "DEPRECATION")
+    return arraySet.isEmpty() && arraySet.remove(0) && arraySet.removeAll(arrayOf(1, 2)) &&
+        arraySet.removeAt(0) == 0 && arraySet.contains(0) && arraySet.size == 0 &&
+        arraySet.isEmpty() && arraySet.toArray() === arraySet.toArray(arrayOf<Number>()) &&
+        arraySet + arrayOf(1) == arraySet - arrayOf(1) && arraySet == arrayOf(0) &&
+        arraySet.toArray { value -> arrayOf(value) }.equals(
+            arraySet.toArray(IntFunction { value -> arrayOf(value) })
+        ) && arraySet.containsAll(listOf(1, 2))
+}
diff --git a/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/SuspendingGestureTestUtil.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/SuspendingGestureTestUtil.kt
index f293177..152d737 100644
--- a/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/SuspendingGestureTestUtil.kt
+++ b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/SuspendingGestureTestUtil.kt
@@ -41,6 +41,7 @@
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalViewConfiguration
 import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.DpSize
 import androidx.compose.ui.unit.IntSize
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.channels.Channel
@@ -96,7 +97,9 @@
             compose(recomposer) {
                 CompositionLocalProvider(
                     LocalDensity provides Density(1f),
-                    LocalViewConfiguration provides TestViewConfiguration()
+                    LocalViewConfiguration provides TestViewConfiguration(
+                        minimumTouchTargetSize = DpSize.Zero
+                    )
                 ) {
                     pointerInputFilter = currentComposer
                         .materialize(Modifier.pointerInput(Unit, gestureDetector)) as
diff --git a/compose/material/OWNERS b/compose/material/OWNERS
index 83a0aed..9e0b875 100644
--- a/compose/material/OWNERS
+++ b/compose/material/OWNERS
@@ -4,4 +4,5 @@
 andreykulikov@google.com
 malkov@google.com
 lpf@google.com
-soboleva@google.com
\ No newline at end of file
+soboleva@google.com
+sgibly@google.com
\ No newline at end of file
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SurfaceSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SurfaceSamples.kt
index 4364c51..3565446 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SurfaceSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/SurfaceSamples.kt
@@ -26,7 +26,6 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
-import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.text.style.TextAlign
 
 @Sampled
@@ -78,7 +77,7 @@
         checked = checked,
         onCheckedChange = { checked = !checked },
         color = if (checked) {
-            Color.LightGray
+            MaterialTheme.colors.primary
         } else {
             MaterialTheme.colors.background
         }
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Surface.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Surface.kt
index 562fb89..bec9534 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Surface.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Surface.kt
@@ -52,8 +52,7 @@
  * elevation, which influences how that piece of surface visually relates to other surfaces and
  * how that surface casts shadows.
  *
- * If you want to have a Surface that handles clicks or selections, consider using another
- * overload.
+ * See the other overloads for clickable, selectable, and toggleable surfaces.
  *
  * The Surface is responsible for:
  *
diff --git a/compose/material3/material3/api/current.txt b/compose/material3/material3/api/current.txt
index 7abe946..cc7ae44 100644
--- a/compose/material3/material3/api/current.txt
+++ b/compose/material3/material3/api/current.txt
@@ -207,7 +207,8 @@
   }
 
   public final class FloatingActionButtonKt {
-    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation);
+    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> icon, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean expanded, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation);
     method @androidx.compose.runtime.Composable public static void FloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void LargeFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void SmallFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
diff --git a/compose/material3/material3/api/public_plus_experimental_current.txt b/compose/material3/material3/api/public_plus_experimental_current.txt
index de332c7..54bb9eb 100644
--- a/compose/material3/material3/api/public_plus_experimental_current.txt
+++ b/compose/material3/material3/api/public_plus_experimental_current.txt
@@ -270,7 +270,8 @@
   }
 
   public final class FloatingActionButtonKt {
-    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation);
+    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> icon, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean expanded, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation);
     method @androidx.compose.runtime.Composable public static void FloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void LargeFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void SmallFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
diff --git a/compose/material3/material3/api/restricted_current.txt b/compose/material3/material3/api/restricted_current.txt
index 7abe946..cc7ae44 100644
--- a/compose/material3/material3/api/restricted_current.txt
+++ b/compose/material3/material3/api/restricted_current.txt
@@ -207,7 +207,8 @@
   }
 
   public final class FloatingActionButtonKt {
-    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? icon, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation);
+    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.RowScope,kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void ExtendedFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> text, kotlin.jvm.functions.Function0<kotlin.Unit> icon, kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional boolean expanded, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation);
     method @androidx.compose.runtime.Composable public static void FloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void LargeFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
     method @androidx.compose.runtime.Composable public static void SmallFloatingActionButton(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, optional androidx.compose.material3.FloatingActionButtonElevation elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
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 3b1e300..57c1b3d 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
@@ -24,6 +24,7 @@
 import androidx.compose.material3.catalog.library.util.SampleSourceUrl
 import androidx.compose.material3.samples.AlertDialogSample
 import androidx.compose.material3.samples.AlertDialogWithIconSample
+import androidx.compose.material3.samples.AnimatedExtendedFloatingActionButtonSample
 import androidx.compose.material3.samples.BottomAppBarWithFAB
 import androidx.compose.material3.samples.ButtonSample
 import androidx.compose.material3.samples.ButtonWithIconSample
@@ -40,6 +41,7 @@
 import androidx.compose.material3.samples.ExitUntilCollapsedLargeTopAppBar
 import androidx.compose.material3.samples.ExitUntilCollapsedMediumTopAppBar
 import androidx.compose.material3.samples.ExtendedFloatingActionButtonSample
+import androidx.compose.material3.samples.ExtendedFloatingActionButtonTextSample
 import androidx.compose.material3.samples.FancyTabs
 import androidx.compose.material3.samples.FancyIndicatorTabs
 import androidx.compose.material3.samples.FancyIndicatorContainerTabs
@@ -278,6 +280,16 @@
             description = ExtendedFABExampleDescription,
             sourceUrl = ExtendedFABExampleSourceUrl,
         ) { ExtendedFloatingActionButtonSample() },
+        Example(
+            name = ::ExtendedFloatingActionButtonTextSample.name,
+            description = ExtendedFABExampleDescription,
+            sourceUrl = ExtendedFABExampleSourceUrl,
+        ) { ExtendedFloatingActionButtonTextSample() },
+        Example(
+            name = ::AnimatedExtendedFloatingActionButtonSample.name,
+            description = ExtendedFABExampleDescription,
+            sourceUrl = ExtendedFABExampleSourceUrl,
+        ) { AnimatedExtendedFloatingActionButtonSample() },
     )
 
 private const val FloatingActionButtonsExampleDescription = "Floating action button examples"
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/FloatingActionButtonSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/FloatingActionButtonSamples.kt
index e9e352d..de643b8 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/FloatingActionButtonSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/FloatingActionButtonSamples.kt
@@ -17,8 +17,13 @@
 package androidx.compose.material3.samples
 
 import androidx.annotation.Sampled
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
-import androidx.compose.material.ExperimentalMaterialApi
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.rememberLazyListState
+import androidx.compose.material.FabPosition
+import androidx.compose.material.Scaffold
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Add
 import androidx.compose.material3.ExtendedFloatingActionButton
@@ -29,9 +34,12 @@
 import androidx.compose.material3.SmallFloatingActionButton
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
 
-@OptIn(ExperimentalMaterialApi::class)
 @Sampled
 @Composable
 fun FloatingActionButtonSample() {
@@ -42,7 +50,6 @@
     }
 }
 
-@OptIn(ExperimentalMaterialApi::class)
 @Sampled
 @Composable
 fun SmallFloatingActionButtonSample() {
@@ -53,7 +60,6 @@
     }
 }
 
-@OptIn(ExperimentalMaterialApi::class)
 @Sampled
 @Composable
 fun LargeFloatingActionButtonSample() {
@@ -68,7 +74,14 @@
     }
 }
 
-@OptIn(ExperimentalMaterialApi::class)
+@Sampled
+@Composable
+fun ExtendedFloatingActionButtonTextSample() {
+    ExtendedFloatingActionButton(onClick = { /* do something */ }) {
+        Text(text = "Extended FAB")
+    }
+}
+
 @Sampled
 @Composable
 fun ExtendedFloatingActionButtonSample() {
@@ -78,3 +91,39 @@
         text = { Text(text = "Extended FAB") },
     )
 }
+
+@Sampled
+@Composable
+fun AnimatedExtendedFloatingActionButtonSample() {
+    val listState = rememberLazyListState()
+    // The FAB is initially expanded. Once the first visible item is past the first item we
+    // collapse the FAB. We use a remembered derived state to minimize unnecessary compositions.
+    val expandedFab by remember {
+        derivedStateOf {
+            listState.firstVisibleItemIndex == 0
+        }
+    }
+    Scaffold(
+        floatingActionButton = {
+            ExtendedFloatingActionButton(
+                onClick = { /* do something */ },
+                expanded = expandedFab,
+                icon = { Icon(Icons.Filled.Add, "Add") },
+                text = { Text(text = "Extended FAB") },
+            )
+        },
+        isFloatingActionButtonDocked = false,
+        floatingActionButtonPosition = FabPosition.End,
+    ) {
+        LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
+            for (index in 0 until 100) {
+                item {
+                    Text(
+                        text = "List item - $index",
+                        modifier = Modifier.padding(24.dp)
+                    )
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ScaffoldSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ScaffoldSamples.kt
index 4bd58d6..5e1ebd9 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ScaffoldSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/ScaffoldSamples.kt
@@ -88,9 +88,10 @@
         floatingActionButtonPosition = FabPosition.End,
         floatingActionButton = {
             ExtendedFloatingActionButton(
-                text = { Text("Inc") },
                 onClick = { /* fab click handler */ }
-            )
+            ) {
+                Text("Inc")
+            }
         },
         content = { innerPadding ->
             LazyColumn(contentPadding = innerPadding) {
@@ -118,7 +119,6 @@
         floatingActionButton = {
             var clickCount by remember { mutableStateOf(0) }
             ExtendedFloatingActionButton(
-                text = { Text("Show snackbar") },
                 onClick = {
                     // show snackbar as a suspend function
                     scope.launch {
@@ -127,7 +127,7 @@
                         )
                     }
                 }
-            )
+            ) { Text("Show snackbar") }
         },
         content = { innerPadding ->
             Text(
@@ -149,7 +149,6 @@
         floatingActionButton = {
             var clickCount by remember { mutableStateOf(0) }
             ExtendedFloatingActionButton(
-                text = { Text("Show snackbar") },
                 onClick = {
                     // show snackbar as a suspend function
                     scope.launch {
@@ -161,7 +160,7 @@
                         )
                     }
                 }
-            )
+            ) { Text("Show snackbar") }
         },
         content = { innerPadding ->
             Text(
@@ -225,7 +224,6 @@
         floatingActionButton = {
             var clickCount by remember { mutableStateOf(0) }
             ExtendedFloatingActionButton(
-                text = { Text("Show snackbar") },
                 onClick = {
                     scope.launch {
                         snackbarHostState.showSnackbar(
@@ -236,7 +234,7 @@
                         )
                     }
                 }
-            )
+            ) { Text("Show snackbar") }
         },
         content = { innerPadding ->
             Text(
@@ -277,12 +275,11 @@
         floatingActionButton = {
             var clickCount by remember { mutableStateOf(0) }
             ExtendedFloatingActionButton(
-                text = { Text("Show snackbar") },
                 onClick = {
                     // offset snackbar data to the business logic
                     channel.trySend(++clickCount)
                 }
-            )
+            ) { Text("Show snackbar") }
         },
         content = { innerPadding ->
             Text(
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/FloatingActionButtonScreenshotTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/FloatingActionButtonScreenshotTest.kt
index 78fdbf7..861e2439 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/FloatingActionButtonScreenshotTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/FloatingActionButtonScreenshotTest.kt
@@ -21,6 +21,9 @@
 import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Favorite
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
 import androidx.compose.testutils.assertAgainstGolden
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusRequester
@@ -214,8 +217,8 @@
     fun text() {
         rule.setMaterialContent(lightColorScheme()) {
             ExtendedFloatingActionButton(
-                text = { Text("EXTENDED") },
-                onClick = {}
+                onClick = {},
+                content = { Text("EXTENDED") },
             )
         }
 
@@ -304,6 +307,29 @@
         assertRootAgainstGolden("fab_focus")
     }
 
+    @Test
+    fun extended_fab_half_way_animation() {
+        rule.mainClock.autoAdvance = false
+
+        var expanded by mutableStateOf(true)
+        rule.setMaterialContent(lightColorScheme()) {
+            ExtendedFloatingActionButton(
+                expanded = expanded,
+                onClick = {},
+                containerColor = MaterialTheme.colorScheme.surface,
+                contentColor = MaterialTheme.colorScheme.primary,
+                icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
+                text = { Text(text = "Extended FAB") },
+            )
+        }
+
+        rule.runOnIdle { expanded = false }
+
+        rule.mainClock.advanceTimeBy(127)
+
+        assertRootAgainstGolden("fab_extended_animation")
+    }
+
     private fun assertClickableAgainstGolden(goldenName: String) {
         rule.onNode(hasClickAction())
             .captureToImage()
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/FloatingActionButtonTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/FloatingActionButtonTest.kt
index 2ce42b0..6de6c7f 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/FloatingActionButtonTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/FloatingActionButtonTest.kt
@@ -28,6 +28,9 @@
 import androidx.compose.material3.tokens.FabPrimarySmallTokens
 import androidx.compose.material3.tokens.FabPrimaryTokens
 import androidx.compose.runtime.CompositionLocalProvider
+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.geometry.Rect
@@ -36,6 +39,7 @@
 import androidx.compose.ui.layout.onGloballyPositioned
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.assertHeightIsEqualTo
+import androidx.compose.ui.test.assertIsDisplayed
 import androidx.compose.ui.test.assertIsEnabled
 import androidx.compose.ui.test.assertTouchHeightIsEqualTo
 import androidx.compose.ui.test.assertTouchWidthIsEqualTo
@@ -87,7 +91,7 @@
 
         rule.setMaterialContent(lightColorScheme()) {
             Box {
-                ExtendedFloatingActionButton(text = { Text(text) }, onClick = onClick)
+                ExtendedFloatingActionButton(onClick = onClick, content = { Text(text) })
             }
         }
 
@@ -167,7 +171,7 @@
 
         rule.onNodeWithTag("FAB")
             .assertHeightIsEqualTo(ExtendedFabPrimaryTokens.ContainerHeight)
-            .assertWidthIsAtLeast(48.dp)
+            .assertWidthIsAtLeast(FabPrimaryTokens.ContainerHeight)
     }
 
     @Test
@@ -175,8 +179,8 @@
         rule.setMaterialContent(lightColorScheme()) {
             ExtendedFloatingActionButton(
                 modifier = Modifier.testTag("FAB"),
-                text = { Text(".") },
-                onClick = {}
+                onClick = {},
+                content = { Text(".") },
             )
         }
 
@@ -231,21 +235,18 @@
         var expectedTextStyle: TextStyle? = null
 
         rule.setMaterialContent(lightColorScheme()) {
-            ExtendedFloatingActionButton(
-                onClick = {},
-                text = {
-                    Text(
-                        "Extended FAB",
-                        onTextLayout = {
-                            fontFamily = it.layoutInput.style.fontFamily
-                            fontWeight = it.layoutInput.style.fontWeight
-                            fontSize = it.layoutInput.style.fontSize
-                            lineHeight = it.layoutInput.style.lineHeight
-                            letterSpacing = it.layoutInput.style.letterSpacing
-                        }
-                    )
-                }
-            )
+            ExtendedFloatingActionButton(onClick = {}) {
+                Text(
+                    "Extended FAB",
+                    onTextLayout = {
+                        fontFamily = it.layoutInput.style.fontFamily
+                        fontWeight = it.layoutInput.style.fontWeight
+                        fontSize = it.layoutInput.style.fontSize
+                        lineHeight = it.layoutInput.style.lineHeight
+                        letterSpacing = it.layoutInput.style.letterSpacing
+                    }
+                )
+            }
             expectedTextStyle = MaterialTheme.typography.fromToken(
                 ExtendedFabPrimaryTokens.LabelTextFont
             )
@@ -329,15 +330,14 @@
         rule.setMaterialContent(lightColorScheme()) {
             Box {
                 ExtendedFloatingActionButton(
-                    text = {
-                        Box(
-                            Modifier.size(2.dp)
-                                .onGloballyPositioned { contentCoordinates = it }
-                        )
-                    },
                     onClick = {},
-                    modifier = Modifier.onGloballyPositioned { buttonCoordinates = it }
-                )
+                    modifier = Modifier.onGloballyPositioned { buttonCoordinates = it },
+                ) {
+                    Box(
+                        Modifier.size(2.dp)
+                            .onGloballyPositioned { contentCoordinates = it }
+                    )
+                }
             }
         }
 
@@ -400,6 +400,90 @@
             }
         }
     }
+
+    @Test
+    fun expandedExtendedFabTextHasSizeFromSpecAndTextVisible() {
+        rule.setMaterialContent(lightColorScheme()) {
+            ExtendedFloatingActionButton(
+                expanded = true,
+                onClick = { },
+                icon = {
+                    Icon(
+                        Icons.Filled.Favorite,
+                        "Add",
+                        modifier = Modifier.testTag("icon"),
+                    )
+                },
+                text = { Text(text = "FAB", modifier = Modifier.testTag("text")) },
+                modifier = Modifier.testTag("FAB"),
+            )
+        }
+
+        rule.onNodeWithTag("FAB")
+            .assertHeightIsEqualTo(ExtendedFabPrimaryTokens.ContainerHeight)
+            .assertWidthIsAtLeast(80.dp)
+
+        rule.onNodeWithTag("text", useUnmergedTree = true).assertIsDisplayed()
+        rule.onNodeWithTag("icon", useUnmergedTree = true).assertIsDisplayed()
+    }
+
+    @Test
+    fun collapsedExtendedFabTextHasSizeFromSpecAndTextNotVisible() {
+        rule.setMaterialContent(lightColorScheme()) {
+            ExtendedFloatingActionButton(
+                expanded = false,
+                onClick = { },
+                icon = {
+                    Icon(
+                        Icons.Filled.Favorite,
+                        "Add",
+                        modifier = Modifier.testTag("icon")
+                    )
+                },
+                text = { Text(text = "FAB", modifier = Modifier.testTag("text")) },
+                modifier = Modifier.testTag("FAB"),
+            )
+        }
+
+        rule.onNodeWithTag("FAB")
+            .assertIsSquareWithSize(FabPrimaryTokens.ContainerHeight)
+        rule.onNodeWithTag("text", useUnmergedTree = true).assertDoesNotExist()
+        rule.onNodeWithTag("icon", useUnmergedTree = true).assertIsDisplayed()
+    }
+
+    @Test
+    fun extendedFabAnimates() {
+        rule.mainClock.autoAdvance = false
+
+        var expanded by mutableStateOf(true)
+        rule.setMaterialContent(lightColorScheme()) {
+            ExtendedFloatingActionButton(
+                expanded = expanded,
+                onClick = {},
+                icon = {
+                    Icon(
+                        Icons.Filled.Favorite,
+                        "Add",
+                        modifier = Modifier.testTag("icon")
+                    )
+                },
+                text = { Text(text = "FAB", modifier = Modifier.testTag("text")) },
+                modifier = Modifier.testTag("FAB"),
+            )
+        }
+
+        rule.onNodeWithTag("FAB")
+            .assertHeightIsEqualTo(ExtendedFabPrimaryTokens.ContainerHeight)
+            .assertWidthIsAtLeast(80.dp)
+
+        rule.runOnIdle { expanded = false }
+        rule.mainClock.advanceTimeBy(200)
+
+        rule.onNodeWithTag("FAB")
+            .assertIsSquareWithSize(FabPrimaryTokens.ContainerHeight)
+            .assertHeightIsEqualTo(FabPrimaryTokens.ContainerHeight)
+            .assertWidthIsEqualTo(FabPrimaryTokens.ContainerWidth)
+    }
 }
 
 fun assertWithinOnePixel(expected: Offset, actual: Offset) {
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/FloatingActionButton.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/FloatingActionButton.kt
index 60c7993..99f973d 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/FloatingActionButton.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/FloatingActionButton.kt
@@ -16,8 +16,14 @@
 
 package androidx.compose.material3
 
+import androidx.compose.animation.AnimatedVisibility
 import androidx.compose.animation.core.Animatable
 import androidx.compose.animation.core.VectorConverter
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.expandHorizontally
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.animation.shrinkHorizontally
 import androidx.compose.foundation.interaction.FocusInteraction
 import androidx.compose.foundation.interaction.HoverInteraction
 import androidx.compose.foundation.interaction.Interaction
@@ -26,6 +32,7 @@
 import androidx.compose.foundation.interaction.PressInteraction
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.defaultMinSize
 import androidx.compose.foundation.layout.padding
@@ -35,6 +42,7 @@
 import androidx.compose.material3.tokens.FabPrimaryLargeTokens
 import androidx.compose.material3.tokens.FabPrimarySmallTokens
 import androidx.compose.material3.tokens.FabPrimaryTokens
+import androidx.compose.material3.tokens.MotionTokens
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.LaunchedEffect
@@ -222,13 +230,73 @@
  * The extended FAB is wider than a regular FAB, and it includes a text label. To learn more about
  * the extended FAB visit the [Material website](https://m3.material.io/components/extended-fab).
  *
- * @sample androidx.compose.material3.samples.ExtendedFloatingActionButtonSample
+ * The other extended floating action button overload supports a text label and icon.
  *
- * @param text Text label displayed inside this FAB
+ * @sample androidx.compose.material3.samples.ExtendedFloatingActionButtonTextSample
+ *
  * @param onClick callback invoked when this FAB is clicked
  * @param modifier [Modifier] to be applied to this FAB
+ * @param interactionSource the [MutableInteractionSource] representing the stream of
+ * [Interaction]s for this FAB. You can create and pass in your own remembered
+ * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
+ * appearance / behavior of this FAB in different [Interaction]s.
+ * @param shape The [Shape] of this FAB
+ * @param containerColor The container color. Use [Color.Transparent] to have no color
+ * @param contentColor The preferred content color for content inside this FAB
+ * @param elevation [FloatingActionButtonElevation] used to resolve the elevation for this FAB
+ * in different states. This controls the size of the shadow below the FAB. When [containerColor]
+ * is [ColorScheme.surface], a higher elevation (surface blended with more primary) will result in
+ * a darker surface color in light theme and lighter color in dark theme.
+ * @param content the content of this FAB - this is typically an [Text] label.
+ */
+@Composable
+fun ExtendedFloatingActionButton(
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
+    shape: Shape = ExtendedFabPrimaryTokens.ContainerShape,
+    containerColor: Color = ExtendedFabPrimaryTokens.ContainerColor.toColor(),
+    contentColor: Color = contentColorFor(containerColor),
+    elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
+    content: @Composable RowScope.() -> Unit,
+) {
+    FloatingActionButton(
+        modifier = modifier.sizeIn(minWidth = ExtendedFabMinimumWidth),
+        onClick = onClick,
+        interactionSource = interactionSource,
+        shape = shape,
+        containerColor = containerColor,
+        contentColor = contentColor,
+        elevation = elevation,
+    ) {
+        Row(
+            modifier = Modifier.padding(horizontal = ExtendedFabTextPadding),
+            verticalAlignment = Alignment.CenterVertically,
+            content = content,
+        )
+    }
+}
+
+/**
+ * ![Extended FAB image](https://developer.android.com/images/reference/androidx/compose/material3/extended-fab.png)
+ *
+ * The extended FAB is wider than a regular FAB, and it includes a text label and icon. To learn
+ * more about the extended FAB visit the
+ * [Material website](https://m3.material.io/components/extended-fab).
+ *
+ * The other extended floating action button overload are for FABs without an icon.
+ *
+ * @sample androidx.compose.material3.samples.ExtendedFloatingActionButtonSample
+ * @sample androidx.compose.material3.samples.AnimatedExtendedFloatingActionButtonSample
+ *
+ * @param text Text label displayed inside this FAB
  * @param icon Optional icon for this FAB, typically this will be a
  * [Icon].
+ * @param onClick callback invoked when this FAB is clicked
+ * @param modifier [Modifier] to be applied to this FAB
+ * @param expanded The FAB will animate between expanded state and collapsed state. In an expanded
+ * state the FAB will show both the [icon] and [text] parameters. In a collapsed state the FAB will
+ * show only the [icon] parameter.
  * @param interactionSource the [MutableInteractionSource] representing the stream of
  * [Interaction]s for this FAB. You can create and pass in your own remembered
  * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
@@ -244,9 +312,10 @@
 @Composable
 fun ExtendedFloatingActionButton(
     text: @Composable () -> Unit,
+    icon: @Composable () -> Unit,
     onClick: () -> Unit,
     modifier: Modifier = Modifier,
-    icon: @Composable (() -> Unit)? = null,
+    expanded: Boolean = true,
     interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
     shape: Shape = ExtendedFabPrimaryTokens.ContainerShape,
     containerColor: Color = ExtendedFabPrimaryTokens.ContainerColor.toColor(),
@@ -255,8 +324,7 @@
 ) {
     FloatingActionButton(
         modifier = modifier.sizeIn(
-            minWidth = 80.dp,
-            minHeight = ExtendedFabPrimaryTokens.ContainerHeight,
+            minWidth = if (expanded) ExtendedFabMinimumWidth else FabPrimaryTokens.ContainerWidth
         ),
         onClick = onClick,
         interactionSource = interactionSource,
@@ -265,23 +333,24 @@
         contentColor = contentColor,
         elevation = elevation,
     ) {
-        val startPadding = if (icon == null) {
-            ExtendedFabTextPadding
-        } else {
-            ExtendedFabPrimaryTokens.IconSize / 2
-        }
+        val startPadding = if (expanded) ExtendedFabPrimaryTokens.IconSize / 2 else 0.dp
+        val endPadding = if (expanded) ExtendedFabTextPadding else 0.dp
+
         Row(
-            modifier = Modifier.padding(
-                start = startPadding,
-                end = ExtendedFabTextPadding
-            ),
+            modifier = Modifier.padding(start = startPadding, end = endPadding),
             verticalAlignment = Alignment.CenterVertically
         ) {
-            if (icon != null) {
-                icon()
-                Spacer(Modifier.width(ExtendedFabIconPadding))
+            icon()
+            AnimatedVisibility(
+                visible = expanded,
+                enter = ExtendedFabExpandAnimation,
+                exit = ExtendedFabCollapseAnimation,
+            ) {
+                Row {
+                    Spacer(Modifier.width(ExtendedFabIconPadding))
+                    text()
+                }
             }
-            text()
         }
     }
 }
@@ -481,3 +550,32 @@
 private val ExtendedFabIconPadding = 12.dp
 
 private val ExtendedFabTextPadding = 20.dp
+
+private val ExtendedFabMinimumWidth = 80.dp
+
+private val ExtendedFabCollapseAnimation = fadeOut(
+    animationSpec = tween(
+        durationMillis = MotionTokens.Duration100DurationMs.toInt(),
+        easing = MotionTokens.EasingLinearCubicBezier,
+    )
+) + shrinkHorizontally(
+    animationSpec = tween(
+        durationMillis = MotionTokens.Duration500DurationMs.toInt(),
+        easing = MotionTokens.EasingEmphasizedCubicBezier,
+    ),
+    shrinkTowards = Alignment.Start,
+)
+
+private val ExtendedFabExpandAnimation = fadeIn(
+    animationSpec = tween(
+        durationMillis = MotionTokens.Duration200DurationMs.toInt(),
+        delayMillis = MotionTokens.Duration100DurationMs.toInt(),
+        easing = MotionTokens.EasingLinearCubicBezier,
+    ),
+) + expandHorizontally(
+    animationSpec = tween(
+        durationMillis = MotionTokens.Duration500DurationMs.toInt(),
+        easing = MotionTokens.EasingEmphasizedCubicBezier,
+    ),
+    expandFrom = Alignment.Start,
+)
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Surface.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Surface.kt
index 92c4faa..833017b 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Surface.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Surface.kt
@@ -50,8 +50,7 @@
  * elevation, which influences how that piece of surface visually relates to other surfaces and how
  * that surface is modified by tonal variance.
  *
- * If you want to have a Surface that handles clicks or selections, consider using another
- * overload.
+ * See the other overloads for clickable, selectable, and toggleable surfaces.
  *
  * The Surface is responsible for:
  *
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/MotionTokens.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/MotionTokens.kt
new file mode 100644
index 0000000..9b7a306
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/tokens/MotionTokens.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// VERSION: v0_85
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+package androidx.compose.material3.tokens
+
+import androidx.compose.animation.core.CubicBezierEasing
+
+internal object MotionTokens {
+    const val Duration100DurationMs = 100.0
+    const val Duration1000DurationMs = 1000.0
+    const val Duration150DurationMs = 150.0
+    const val Duration200DurationMs = 200.0
+    const val Duration250DurationMs = 250.0
+    const val Duration300DurationMs = 300.0
+    const val Duration350DurationMs = 350.0
+    const val Duration400DurationMs = 400.0
+    const val Duration450DurationMs = 450.0
+    const val Duration50DurationMs = 50.0
+    const val Duration500DurationMs = 500.0
+    const val Duration550DurationMs = 550.0
+    const val Duration600DurationMs = 600.0
+    const val Duration700DurationMs = 700.0
+    const val Duration800DurationMs = 800.0
+    const val Duration900DurationMs = 900.0
+    val EasingEmphasizedCubicBezier = CubicBezierEasing(0.2f, 0.0f, 0.0f, 1.0f)
+    val EasingEmphasizedAccelerateCubicBezier = CubicBezierEasing(0.3f, 0.0f, 0.8f, 0.15f)
+    val EasingEmphasizedDecelerateCubicBezier = CubicBezierEasing(0.05f, 0.7f, 0.1f, 1.0f)
+    val EasingLegacyCubicBezier = CubicBezierEasing(0.4f, 0.0f, 0.2f, 1.0f)
+    val EasingLegacyAccelerateCubicBezier = CubicBezierEasing(0.4f, 0.0f, 1.0f, 1.0f)
+    val EasingLegacyDecelerateCubicBezier = CubicBezierEasing(0.0f, 0.0f, 0.2f, 1.0f)
+    val EasingLinearCubicBezier = CubicBezierEasing(0.0f, 0.0f, 1.0f, 1.0f)
+    val EasingStandardCubicBezier = CubicBezierEasing(0.2f, 0.0f, 0.0f, 1.0f)
+    val EasingStandardAccelerateCubicBezier = CubicBezierEasing(0.3f, 0.0f, 1.0f, 1.0f)
+    val EasingStandardDecelerateCubicBezier = CubicBezierEasing(0.0f, 0.0f, 0.0f, 1.0f)
+}
diff --git a/compose/test-utils/src/commonMain/kotlin/androidx/compose/testutils/TestViewConfiguration.kt b/compose/test-utils/src/commonMain/kotlin/androidx/compose/testutils/TestViewConfiguration.kt
index b7f339bd..b79120f 100644
--- a/compose/test-utils/src/commonMain/kotlin/androidx/compose/testutils/TestViewConfiguration.kt
+++ b/compose/test-utils/src/commonMain/kotlin/androidx/compose/testutils/TestViewConfiguration.kt
@@ -23,6 +23,17 @@
 import androidx.compose.ui.unit.DpSize
 
 /**
+ * Default values for [TestViewConfiguration]. This object exists so we can leverage the default
+ * implementation of members from [ViewConfiguration].
+ */
+private val Default = object : ViewConfiguration {
+    override val longPressTimeoutMillis: Long = 500L
+    override val doubleTapTimeoutMillis: Long = 300L
+    override val doubleTapMinTimeMillis: Long = 40L
+    override val touchSlop: Float = 18f
+}
+
+/**
  * A [ViewConfiguration] that can be used for testing. The default values are representative for
  * Android devices, but can be set to any value desired for a test. See the `With*` functions for
  * shorthands that create a [TestViewConfiguration] and provide it as a [LocalViewConfiguration].
@@ -31,13 +42,14 @@
  * @see WithDoubleTapTimeoutMillis
  * @see WithDoubleTapMinTimeMillis
  * @see WithTouchSlop
+ * @see WithMinimumTouchTargetSize
  */
 class TestViewConfiguration(
-    override val longPressTimeoutMillis: Long = 500L,
-    override val doubleTapTimeoutMillis: Long = 300L,
-    override val doubleTapMinTimeMillis: Long = 40L,
-    override val touchSlop: Float = 18f,
-    override val minimumTouchTargetSize: DpSize = DpSize.Zero
+    override val longPressTimeoutMillis: Long = Default.longPressTimeoutMillis,
+    override val doubleTapTimeoutMillis: Long = Default.doubleTapTimeoutMillis,
+    override val doubleTapMinTimeMillis: Long = Default.doubleTapMinTimeMillis,
+    override val touchSlop: Float = Default.touchSlop,
+    override val minimumTouchTargetSize: DpSize = Default.minimumTouchTargetSize
 ) : ViewConfiguration
 
 @Composable
@@ -73,6 +85,14 @@
 }
 
 @Composable
+fun WithMinimumTouchTargetSize(minimumTouchTargetSize: DpSize, content: @Composable () -> Unit) {
+    WithViewConfiguration(
+        TestViewConfiguration(minimumTouchTargetSize = minimumTouchTargetSize),
+        content = content
+    )
+}
+
+@Composable
 fun WithViewConfiguration(
     testViewConfiguration: TestViewConfiguration,
     content: @Composable () -> Unit
diff --git a/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/assertions/BoundsAssertionsTest.kt b/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/assertions/BoundsAssertionsTest.kt
index dc27723..f72f8bf 100644
--- a/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/assertions/BoundsAssertionsTest.kt
+++ b/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/assertions/BoundsAssertionsTest.kt
@@ -17,6 +17,7 @@
 package androidx.compose.ui.test.assertions
 
 import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.offset
@@ -24,6 +25,7 @@
 import androidx.compose.foundation.layout.requiredSize
 import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.runtime.Composable
+import androidx.compose.testutils.WithMinimumTouchTargetSize
 import androidx.compose.testutils.expectError
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -37,6 +39,8 @@
 import androidx.compose.ui.test.assertLeftPositionInRootIsEqualTo
 import androidx.compose.ui.test.assertPositionInRootIsEqualTo
 import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
+import androidx.compose.ui.test.assertTouchHeightIsEqualTo
+import androidx.compose.ui.test.assertTouchWidthIsEqualTo
 import androidx.compose.ui.test.assertWidthIsAtLeast
 import androidx.compose.ui.test.assertWidthIsEqualTo
 import androidx.compose.ui.test.getAlignmentLinePosition
@@ -44,24 +48,26 @@
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.DpSize
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import com.google.common.truth.Truth.assertThat
+import kotlin.math.max
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
-import kotlin.math.max
 
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 class BoundsAssertionsTest {
+    companion object {
+        private const val tag = "box"
+    }
 
     @get:Rule
     val rule = createComposeRule()
 
-    val tag = "box"
-
     private fun composeBox() {
         rule.setContent {
             Box(
@@ -81,6 +87,19 @@
         }
     }
 
+    @Composable
+    private fun SmallBox(
+        modifier: Modifier = Modifier,
+        tag: String = BoundsAssertionsTest.tag
+    ) {
+        Box(
+            modifier = modifier
+                .testTag(tag)
+                .requiredSize(10.dp, 10.dp)
+                .background(color = Color.Black)
+        )
+    }
+
     @Test
     fun assertSizeEquals() {
         composeBox()
@@ -132,6 +151,38 @@
     }
 
     @Test
+    fun assertTouchSizeEquals() {
+        rule.setContent {
+            WithMinimumTouchTargetSize(DpSize(20.dp, 20.dp)) {
+                SmallBox(Modifier.clickable {})
+            }
+        }
+
+        rule.onNodeWithTag(tag)
+            .assertTouchWidthIsEqualTo(20.dp)
+            .assertTouchHeightIsEqualTo(20.dp)
+    }
+
+    @Test
+    fun assertTouchSizeEquals_fail() {
+        rule.setContent {
+            WithMinimumTouchTargetSize(DpSize(20.dp, 20.dp)) {
+                SmallBox(Modifier.clickable {})
+            }
+        }
+
+        expectError<AssertionError> {
+            rule.onNodeWithTag(tag)
+                .assertTouchWidthIsEqualTo(19.dp)
+        }
+
+        expectError<AssertionError> {
+            rule.onNodeWithTag(tag)
+                .assertTouchHeightIsEqualTo(21.dp)
+        }
+    }
+
+    @Test
     fun assertPosition() {
         composeBox()
 
@@ -265,7 +316,7 @@
         }
     }
 
-    private fun getSizeTest(content: @Composable() () -> Unit) {
+    private fun getSizeTest(content: @Composable () -> Unit) {
         // When we have a node that is [not] measured and not placed
         rule.setContent(content)
 
diff --git a/compose/ui/ui/src/androidMain/res/values-af/strings.xml b/compose/ui/ui/src/androidMain/res/values-af/strings.xml
index a7d0976..6e8b2c52 100644
--- a/compose/ui/ui/src/androidMain/res/values-af/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-af/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Maak sigblad toe"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Ongeldige invoer"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Opspringvenster"</string>
+    <string name="range_start" msgid="7097486360902471446">"Begingrens"</string>
+    <string name="range_end" msgid="5941395253238309765">"Eindgrens"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-am/strings.xml b/compose/ui/ui/src/androidMain/res/values-am/strings.xml
index f708834..81b5d43 100644
--- a/compose/ui/ui/src/androidMain/res/values-am/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-am/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"ሉህን ዝጋ"</string>
     <string name="default_error_message" msgid="8038256446254964252">"ልክ ያልሆነ ግቤት"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"ብቅ-ባይ መስኮት"</string>
+    <string name="range_start" msgid="7097486360902471446">"የክልል መጀመሪያ"</string>
+    <string name="range_end" msgid="5941395253238309765">"የክልል መጨረሻ"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-ar/strings.xml b/compose/ui/ui/src/androidMain/res/values-ar/strings.xml
index 6b13b69..d460e1f 100644
--- a/compose/ui/ui/src/androidMain/res/values-ar/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ar/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"إغلاق الورقة"</string>
     <string name="default_error_message" msgid="8038256446254964252">"إدخال غير صالح"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"نافذة منبثقة"</string>
+    <string name="range_start" msgid="7097486360902471446">"بداية النطاق"</string>
+    <string name="range_end" msgid="5941395253238309765">"نهاية النطاق"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-as/strings.xml b/compose/ui/ui/src/androidMain/res/values-as/strings.xml
index a0adbf45..e59d517 100644
--- a/compose/ui/ui/src/androidMain/res/values-as/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-as/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"শ্বীট বন্ধ কৰক"</string>
     <string name="default_error_message" msgid="8038256446254964252">"অমান্য ইনপুট"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"পপ-আপ ৱিণ্ড’"</string>
+    <string name="range_start" msgid="7097486360902471446">"পৰিসৰৰ আৰম্ভণি"</string>
+    <string name="range_end" msgid="5941395253238309765">"পৰিসৰৰ সমাপ্তি"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-az/strings.xml b/compose/ui/ui/src/androidMain/res/values-az/strings.xml
index 887848b..ee8dda4 100644
--- a/compose/ui/ui/src/androidMain/res/values-az/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-az/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Səhifəni bağlayın"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Yanlış daxiletmə"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Popap Pəncərəsi"</string>
+    <string name="range_start" msgid="7097486360902471446">"Sıranın başlanğıcı"</string>
+    <string name="range_end" msgid="5941395253238309765">"Sıranın sonu"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-b+sr+Latn/strings.xml b/compose/ui/ui/src/androidMain/res/values-b+sr+Latn/strings.xml
index aac33f4..667cbcc 100644
--- a/compose/ui/ui/src/androidMain/res/values-b+sr+Latn/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-b+sr+Latn/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Zatvorite tabelu"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Unos je nevažeći"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Iskačući prozor"</string>
+    <string name="range_start" msgid="7097486360902471446">"Početak opsega"</string>
+    <string name="range_end" msgid="5941395253238309765">"Kraj opsega"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-be/strings.xml b/compose/ui/ui/src/androidMain/res/values-be/strings.xml
index 4d283f2..0cc8894 100644
--- a/compose/ui/ui/src/androidMain/res/values-be/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-be/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Закрыць аркуш"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Памылка ўводу"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Усплывальнае акно"</string>
+    <string name="range_start" msgid="7097486360902471446">"Пачатак пераліку"</string>
+    <string name="range_end" msgid="5941395253238309765">"Канец пераліку"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-bg/strings.xml b/compose/ui/ui/src/androidMain/res/values-bg/strings.xml
index 1392899..ef623c7 100644
--- a/compose/ui/ui/src/androidMain/res/values-bg/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-bg/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Затваряне на таблицата"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Въведеното е невалидно"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Изскачащ прозорец"</string>
+    <string name="range_start" msgid="7097486360902471446">"Начало на обхвата"</string>
+    <string name="range_end" msgid="5941395253238309765">"Край на обхвата"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-bn/strings.xml b/compose/ui/ui/src/androidMain/res/values-bn/strings.xml
index 583c2cc..307b248 100644
--- a/compose/ui/ui/src/androidMain/res/values-bn/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-bn/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"শিট বন্ধ করুন"</string>
     <string name="default_error_message" msgid="8038256446254964252">"ভুল ইনপুট"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"পপ-আপ উইন্ডো"</string>
+    <string name="range_start" msgid="7097486360902471446">"রেঞ্জ শুরু"</string>
+    <string name="range_end" msgid="5941395253238309765">"রেঞ্জ শেষ"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-bs/strings.xml b/compose/ui/ui/src/androidMain/res/values-bs/strings.xml
index 181d6f8..b5c2913 100644
--- a/compose/ui/ui/src/androidMain/res/values-bs/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-bs/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Zatvaranje tabele"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Pogrešan unos"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Skočni prozor"</string>
+    <string name="range_start" msgid="7097486360902471446">"Početak raspona"</string>
+    <string name="range_end" msgid="5941395253238309765">"Kraj raspona"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-ca/strings.xml b/compose/ui/ui/src/androidMain/res/values-ca/strings.xml
index df7e308..e115375 100644
--- a/compose/ui/ui/src/androidMain/res/values-ca/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ca/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Tanca el full"</string>
     <string name="default_error_message" msgid="8038256446254964252">"L\'entrada no és vàlida"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Finestra emergent"</string>
+    <string name="range_start" msgid="7097486360902471446">"Inici de l\'interval"</string>
+    <string name="range_end" msgid="5941395253238309765">"Fi de l\'interval"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-cs/strings.xml b/compose/ui/ui/src/androidMain/res/values-cs/strings.xml
index 508c90d..86c5623 100644
--- a/compose/ui/ui/src/androidMain/res/values-cs/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-cs/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Zavřít sešit"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Neplatný údaj"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Vyskakovací okno"</string>
+    <string name="range_start" msgid="7097486360902471446">"Začátek rozsahu"</string>
+    <string name="range_end" msgid="5941395253238309765">"Konec rozsahu"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-da/strings.xml b/compose/ui/ui/src/androidMain/res/values-da/strings.xml
index fb81f4a..a58393a 100644
--- a/compose/ui/ui/src/androidMain/res/values-da/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-da/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Luk arket"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Ugyldigt input"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Pop op-vindue"</string>
+    <string name="range_start" msgid="7097486360902471446">"Startinterval"</string>
+    <string name="range_end" msgid="5941395253238309765">"Slutinterval"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-de/strings.xml b/compose/ui/ui/src/androidMain/res/values-de/strings.xml
index d740c8e..9a1b88d 100644
--- a/compose/ui/ui/src/androidMain/res/values-de/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-de/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Tabelle schließen"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Ungültige Eingabe"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Pop-up-Fenster"</string>
+    <string name="range_start" msgid="7097486360902471446">"Bereichsstart"</string>
+    <string name="range_end" msgid="5941395253238309765">"Bereichsende"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-el/strings.xml b/compose/ui/ui/src/androidMain/res/values-el/strings.xml
index 8e983781..dd1f8c5 100644
--- a/compose/ui/ui/src/androidMain/res/values-el/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-el/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Κλείσιμο φύλλου"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Μη έγκυρη καταχώριση"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Αναδυόμενο παράθυρο"</string>
+    <string name="range_start" msgid="7097486360902471446">"Αρχή εύρους"</string>
+    <string name="range_end" msgid="5941395253238309765">"Τέλος εύρους"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-en-rAU/strings.xml b/compose/ui/ui/src/androidMain/res/values-en-rAU/strings.xml
index 355cf42..9d4dfc6 100644
--- a/compose/ui/ui/src/androidMain/res/values-en-rAU/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-en-rAU/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Close sheet"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Invalid input"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Pop-up window"</string>
+    <string name="range_start" msgid="7097486360902471446">"Range start"</string>
+    <string name="range_end" msgid="5941395253238309765">"Range end"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-en-rCA/strings.xml b/compose/ui/ui/src/androidMain/res/values-en-rCA/strings.xml
index 355cf42..9d4dfc6 100644
--- a/compose/ui/ui/src/androidMain/res/values-en-rCA/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-en-rCA/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Close sheet"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Invalid input"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Pop-up window"</string>
+    <string name="range_start" msgid="7097486360902471446">"Range start"</string>
+    <string name="range_end" msgid="5941395253238309765">"Range end"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-en-rGB/strings.xml b/compose/ui/ui/src/androidMain/res/values-en-rGB/strings.xml
index 355cf42..9d4dfc6 100644
--- a/compose/ui/ui/src/androidMain/res/values-en-rGB/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-en-rGB/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Close sheet"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Invalid input"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Pop-up window"</string>
+    <string name="range_start" msgid="7097486360902471446">"Range start"</string>
+    <string name="range_end" msgid="5941395253238309765">"Range end"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-en-rIN/strings.xml b/compose/ui/ui/src/androidMain/res/values-en-rIN/strings.xml
index 355cf42..9d4dfc6 100644
--- a/compose/ui/ui/src/androidMain/res/values-en-rIN/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-en-rIN/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Close sheet"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Invalid input"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Pop-up window"</string>
+    <string name="range_start" msgid="7097486360902471446">"Range start"</string>
+    <string name="range_end" msgid="5941395253238309765">"Range end"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-en-rXC/strings.xml b/compose/ui/ui/src/androidMain/res/values-en-rXC/strings.xml
index 8928d90..fc769fe 100644
--- a/compose/ui/ui/src/androidMain/res/values-en-rXC/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-en-rXC/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‎‎‎‏‎‏‎‎‏‎‎‎‏‏‏‎Close sheet‎‏‎‎‏‎"</string>
     <string name="default_error_message" msgid="8038256446254964252">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‎‏‏‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‏‎‎‎Invalid input‎‏‎‎‏‎"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎Pop-Up Window‎‏‎‎‏‎"</string>
+    <string name="range_start" msgid="7097486360902471446">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‏‎‎Range start‎‏‎‎‏‎"</string>
+    <string name="range_end" msgid="5941395253238309765">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‏‎‏‎Range end‎‏‎‎‏‎"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-es-rUS/strings.xml b/compose/ui/ui/src/androidMain/res/values-es-rUS/strings.xml
index 028edb8..105601f 100644
--- a/compose/ui/ui/src/androidMain/res/values-es-rUS/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-es-rUS/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Cerrar hoja"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Entrada no válida"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Ventana emergente"</string>
+    <string name="range_start" msgid="7097486360902471446">"Inicio de intervalo"</string>
+    <string name="range_end" msgid="5941395253238309765">"Final de intervalo"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-es/strings.xml b/compose/ui/ui/src/androidMain/res/values-es/strings.xml
index e5750e8..4e2e0d6 100644
--- a/compose/ui/ui/src/androidMain/res/values-es/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-es/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Cerrar hoja"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Entrada no válida"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Ventana emergente"</string>
+    <string name="range_start" msgid="7097486360902471446">"Inicio del intervalo"</string>
+    <string name="range_end" msgid="5941395253238309765">"Fin del intervalo"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-et/strings.xml b/compose/ui/ui/src/androidMain/res/values-et/strings.xml
index d046205..2b32c19 100644
--- a/compose/ui/ui/src/androidMain/res/values-et/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-et/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Sule leht"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Sobimatu sisend"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Hüpikaken"</string>
+    <string name="range_start" msgid="7097486360902471446">"Vahemiku algus"</string>
+    <string name="range_end" msgid="5941395253238309765">"Vahemiku lõpp"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-eu/strings.xml b/compose/ui/ui/src/androidMain/res/values-eu/strings.xml
index 20cfc12..4750873 100644
--- a/compose/ui/ui/src/androidMain/res/values-eu/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-eu/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Itxi orria"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Sarrerak ez du balio"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Leiho gainerakorra"</string>
+    <string name="range_start" msgid="7097486360902471446">"Barrutiaren hasiera"</string>
+    <string name="range_end" msgid="5941395253238309765">"Barrutiaren amaiera"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-fa/strings.xml b/compose/ui/ui/src/androidMain/res/values-fa/strings.xml
index 0443911..63bd852 100644
--- a/compose/ui/ui/src/androidMain/res/values-fa/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-fa/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"بستن برگ"</string>
     <string name="default_error_message" msgid="8038256446254964252">"ورودی نامعتبر"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"پنجره بالاپر"</string>
+    <string name="range_start" msgid="7097486360902471446">"شروع محدوده"</string>
+    <string name="range_end" msgid="5941395253238309765">"پایان محدوده"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-fi/strings.xml b/compose/ui/ui/src/androidMain/res/values-fi/strings.xml
index e8b883e..5dac04c 100644
--- a/compose/ui/ui/src/androidMain/res/values-fi/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-fi/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Sulje taulukko"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Virheellinen syöte"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Ponnahdusikkuna"</string>
+    <string name="range_start" msgid="7097486360902471446">"Alueen alku"</string>
+    <string name="range_end" msgid="5941395253238309765">"Alueen loppu"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-fr-rCA/strings.xml b/compose/ui/ui/src/androidMain/res/values-fr-rCA/strings.xml
index 49a9c32..c22615d 100644
--- a/compose/ui/ui/src/androidMain/res/values-fr-rCA/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-fr-rCA/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Fermer la feuille"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Entrée incorrecte"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Fenêtre contextuelle"</string>
+    <string name="range_start" msgid="7097486360902471446">"Début de plage"</string>
+    <string name="range_end" msgid="5941395253238309765">"Fin de plage"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-fr/strings.xml b/compose/ui/ui/src/androidMain/res/values-fr/strings.xml
index fe75531..98c1df9 100644
--- a/compose/ui/ui/src/androidMain/res/values-fr/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-fr/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Fermer la feuille"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Données incorrectes"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Fenêtre pop-up"</string>
+    <string name="range_start" msgid="7097486360902471446">"Début de plage"</string>
+    <string name="range_end" msgid="5941395253238309765">"Fin de plage"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-gl/strings.xml b/compose/ui/ui/src/androidMain/res/values-gl/strings.xml
index 26136fc..a38f25e 100644
--- a/compose/ui/ui/src/androidMain/res/values-gl/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-gl/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Pechar folla"</string>
     <string name="default_error_message" msgid="8038256446254964252">"O texto escrito non é válido"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Ventá emerxente"</string>
+    <string name="range_start" msgid="7097486360902471446">"Inicio do intervalo"</string>
+    <string name="range_end" msgid="5941395253238309765">"Fin do intervalo"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-gu/strings.xml b/compose/ui/ui/src/androidMain/res/values-gu/strings.xml
index 1143395..5ad7da5 100644
--- a/compose/ui/ui/src/androidMain/res/values-gu/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-gu/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"શીટ બંધ કરો"</string>
     <string name="default_error_message" msgid="8038256446254964252">"અમાન્ય ઇનપુટ"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"પૉપ-અપ વિન્ડો"</string>
+    <string name="range_start" msgid="7097486360902471446">"રેંજની શરૂઆત"</string>
+    <string name="range_end" msgid="5941395253238309765">"રેંજની સમાપ્તિ"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-hi/strings.xml b/compose/ui/ui/src/androidMain/res/values-hi/strings.xml
index 392d090..5fb581f 100644
--- a/compose/ui/ui/src/androidMain/res/values-hi/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-hi/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"शीट बंद करें"</string>
     <string name="default_error_message" msgid="8038256446254964252">"अमान्य इनपुट"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"पॉप-अप विंडो"</string>
+    <string name="range_start" msgid="7097486360902471446">"रेंज की शुरुआत"</string>
+    <string name="range_end" msgid="5941395253238309765">"रेंज की सीमा"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-hr/strings.xml b/compose/ui/ui/src/androidMain/res/values-hr/strings.xml
index 83392fe..fec0a12 100644
--- a/compose/ui/ui/src/androidMain/res/values-hr/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-hr/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Zatvaranje lista"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Nevažeći unos"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Skočni prozor"</string>
+    <string name="range_start" msgid="7097486360902471446">"Početak raspona"</string>
+    <string name="range_end" msgid="5941395253238309765">"Kraj raspona"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-hu/strings.xml b/compose/ui/ui/src/androidMain/res/values-hu/strings.xml
index fafa341..5ce0e68 100644
--- a/compose/ui/ui/src/androidMain/res/values-hu/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-hu/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Munkalap bezárása"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Érvénytelen adat"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Előugró ablak"</string>
+    <string name="range_start" msgid="7097486360902471446">"Tartomány kezdete"</string>
+    <string name="range_end" msgid="5941395253238309765">"Tartomány vége"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-hy/strings.xml b/compose/ui/ui/src/androidMain/res/values-hy/strings.xml
index 01ed1d9..815516f 100644
--- a/compose/ui/ui/src/androidMain/res/values-hy/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-hy/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Փակել թերթը"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Սխալ ներածում"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Ելնող պատուհան"</string>
+    <string name="range_start" msgid="7097486360902471446">"Ընդգրկույթի սկիզբ"</string>
+    <string name="range_end" msgid="5941395253238309765">"Ընդգրկույթի վերջ"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-in/strings.xml b/compose/ui/ui/src/androidMain/res/values-in/strings.xml
index 77b0d18..0d28a55 100644
--- a/compose/ui/ui/src/androidMain/res/values-in/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-in/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Tutup sheet"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Input tidak valid"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Jendela Pop-Up"</string>
+    <string name="range_start" msgid="7097486360902471446">"Rentang awal"</string>
+    <string name="range_end" msgid="5941395253238309765">"Rentang akhir"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-is/strings.xml b/compose/ui/ui/src/androidMain/res/values-is/strings.xml
index a7b42c8..e505dd6 100644
--- a/compose/ui/ui/src/androidMain/res/values-is/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-is/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Loka blaði"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Ógildur innsláttur"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Sprettigluggi"</string>
+    <string name="range_start" msgid="7097486360902471446">"Upphaf sviðs"</string>
+    <string name="range_end" msgid="5941395253238309765">"Lok sviðs"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-it/strings.xml b/compose/ui/ui/src/androidMain/res/values-it/strings.xml
index 6c4ade3..23a93d8 100644
--- a/compose/ui/ui/src/androidMain/res/values-it/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-it/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Chiudi il foglio"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Valore non valido"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Finestra popup"</string>
+    <string name="range_start" msgid="7097486360902471446">"Inizio intervallo"</string>
+    <string name="range_end" msgid="5941395253238309765">"Fine intervallo"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-iw/strings.xml b/compose/ui/ui/src/androidMain/res/values-iw/strings.xml
index cba7e5a..887ec62 100644
--- a/compose/ui/ui/src/androidMain/res/values-iw/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-iw/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"סגירת הגיליון"</string>
     <string name="default_error_message" msgid="8038256446254964252">"הקלט לא תקין"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"חלון קופץ"</string>
+    <string name="range_start" msgid="7097486360902471446">"תחילת הטווח"</string>
+    <string name="range_end" msgid="5941395253238309765">"סוף הטווח"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-ja/strings.xml b/compose/ui/ui/src/androidMain/res/values-ja/strings.xml
index 1aa4d25..aaedf66 100644
--- a/compose/ui/ui/src/androidMain/res/values-ja/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ja/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"シートを閉じる"</string>
     <string name="default_error_message" msgid="8038256446254964252">"入力値が無効です"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"ポップアップウィンドウ"</string>
+    <string name="range_start" msgid="7097486360902471446">"範囲の先頭"</string>
+    <string name="range_end" msgid="5941395253238309765">"範囲の末尾"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-ka/strings.xml b/compose/ui/ui/src/androidMain/res/values-ka/strings.xml
index 86c9859..fd9c8fc 100644
--- a/compose/ui/ui/src/androidMain/res/values-ka/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ka/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"ფურცლის დახურვა"</string>
     <string name="default_error_message" msgid="8038256446254964252">"შენატანი არასწორია"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"ამომხტარი ფანჯარა"</string>
+    <string name="range_start" msgid="7097486360902471446">"დიაპაზონის დასაწყისი"</string>
+    <string name="range_end" msgid="5941395253238309765">"დიაპაზონის დასასრული"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-kk/strings.xml b/compose/ui/ui/src/androidMain/res/values-kk/strings.xml
index 2f4e653..3654be7 100644
--- a/compose/ui/ui/src/androidMain/res/values-kk/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-kk/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Парақты жабу"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Енгізілген мән жарамсыз."</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Қалқымалы терезе"</string>
+    <string name="range_start" msgid="7097486360902471446">"Аралықтың басы"</string>
+    <string name="range_end" msgid="5941395253238309765">"Аралықтың соңы"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-km/strings.xml b/compose/ui/ui/src/androidMain/res/values-km/strings.xml
index a3c89f7..00ee74c 100644
--- a/compose/ui/ui/src/androidMain/res/values-km/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-km/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"បិទសន្លឹក"</string>
     <string name="default_error_message" msgid="8038256446254964252">"ការបញ្ចូល​មិនត្រឹមត្រូវ"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"វិនដូ​លោតឡើង"</string>
+    <string name="range_start" msgid="7097486360902471446">"ចំណុចចាប់ផ្ដើម"</string>
+    <string name="range_end" msgid="5941395253238309765">"ចំណុចបញ្ចប់"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-kn/strings.xml b/compose/ui/ui/src/androidMain/res/values-kn/strings.xml
index 0199e8f..b45702b 100644
--- a/compose/ui/ui/src/androidMain/res/values-kn/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-kn/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"ಶೀಟ್ ಮುಚ್ಚಿರಿ"</string>
     <string name="default_error_message" msgid="8038256446254964252">"ಅಮಾನ್ಯ ಇನ್‌ಪುಟ್"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"ಪಾಪ್-ಅಪ್ ವಿಂಡೋ"</string>
+    <string name="range_start" msgid="7097486360902471446">"ಶ್ರೇಣಿಯ ಪ್ರಾರಂಭ"</string>
+    <string name="range_end" msgid="5941395253238309765">"ಶ್ರೇಣಿಯ ಅಂತ್ಯ"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-ko/strings.xml b/compose/ui/ui/src/androidMain/res/values-ko/strings.xml
index 31555c3..1cb7b71 100644
--- a/compose/ui/ui/src/androidMain/res/values-ko/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ko/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"시트 닫기"</string>
     <string name="default_error_message" msgid="8038256446254964252">"입력이 잘못됨"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"팝업 창"</string>
+    <string name="range_start" msgid="7097486360902471446">"범위 시작"</string>
+    <string name="range_end" msgid="5941395253238309765">"범위 끝"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-ky/strings.xml b/compose/ui/ui/src/androidMain/res/values-ky/strings.xml
index 5dd0b50..ff805e15 100644
--- a/compose/ui/ui/src/androidMain/res/values-ky/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ky/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Баракты жабуу"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Киргизилген маалымат жараксыз"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Калкыма терезе"</string>
+    <string name="range_start" msgid="7097486360902471446">"Диапазондун башы"</string>
+    <string name="range_end" msgid="5941395253238309765">"Диапазондун аягы"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-lo/strings.xml b/compose/ui/ui/src/androidMain/res/values-lo/strings.xml
index 05d6f84..4bae605 100644
--- a/compose/ui/ui/src/androidMain/res/values-lo/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-lo/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"ປິດຊີດ"</string>
     <string name="default_error_message" msgid="8038256446254964252">"ຂໍ້ມູນທີ່ປ້ອນເຂົ້າບໍ່ຖືກຕ້ອງ"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"ໜ້າຈໍປັອບອັບ"</string>
+    <string name="range_start" msgid="7097486360902471446">"ເລີ່ມຕົ້ນໄລຍະ"</string>
+    <string name="range_end" msgid="5941395253238309765">"ສິ້ນສຸດໄລຍະ"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-lt/strings.xml b/compose/ui/ui/src/androidMain/res/values-lt/strings.xml
index 2514594..6f3ebd5 100644
--- a/compose/ui/ui/src/androidMain/res/values-lt/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-lt/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Uždaryti lapą"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Netinkama įvestis"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Iššokantysis langas"</string>
+    <string name="range_start" msgid="7097486360902471446">"Diapazono pradžia"</string>
+    <string name="range_end" msgid="5941395253238309765">"Diapazono pabaiga"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-lv/strings.xml b/compose/ui/ui/src/androidMain/res/values-lv/strings.xml
index 6c928be..72971d7 100644
--- a/compose/ui/ui/src/androidMain/res/values-lv/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-lv/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Aizvērt izklājlapu"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Nederīga ievade"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Uznirstošais logs"</string>
+    <string name="range_start" msgid="7097486360902471446">"Diapazona sākums"</string>
+    <string name="range_end" msgid="5941395253238309765">"Diapazona beigas"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-mk/strings.xml b/compose/ui/ui/src/androidMain/res/values-mk/strings.xml
index 838261e..dd4a1c8 100644
--- a/compose/ui/ui/src/androidMain/res/values-mk/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-mk/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Затворете го листот"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Неважечки запис"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Скокачки прозорец"</string>
+    <string name="range_start" msgid="7097486360902471446">"Почеток на опсегот"</string>
+    <string name="range_end" msgid="5941395253238309765">"Крај на опсегот"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-ml/strings.xml b/compose/ui/ui/src/androidMain/res/values-ml/strings.xml
index 2a1c7f9..81c9d0f 100644
--- a/compose/ui/ui/src/androidMain/res/values-ml/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ml/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"ഷീറ്റ് അടയ്ക്കുക"</string>
     <string name="default_error_message" msgid="8038256446254964252">"ഇൻപുട്ട് അസാധുവാണ്"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"പോപ്പ്-അപ്പ് വിൻഡോ"</string>
+    <string name="range_start" msgid="7097486360902471446">"ശ്രേണിയുടെ ആരംഭം"</string>
+    <string name="range_end" msgid="5941395253238309765">"ശ്രേണിയുടെ അവസാനം"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-mn/strings.xml b/compose/ui/ui/src/androidMain/res/values-mn/strings.xml
index ddbcfc3..bee6723 100644
--- a/compose/ui/ui/src/androidMain/res/values-mn/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-mn/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Хүснэгтийг хаах"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Буруу оролт"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Попап цонх"</string>
+    <string name="range_start" msgid="7097486360902471446">"Мужийн эхлэл"</string>
+    <string name="range_end" msgid="5941395253238309765">"Мужийн төгсгөл"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-mr/strings.xml b/compose/ui/ui/src/androidMain/res/values-mr/strings.xml
index 53de7d5..d040eed 100644
--- a/compose/ui/ui/src/androidMain/res/values-mr/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-mr/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"शीट बंद करा"</string>
     <string name="default_error_message" msgid="8038256446254964252">"इनपुट चुकीचे आहे"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"पॉप-अप विंडो"</string>
+    <string name="range_start" msgid="7097486360902471446">"रेंजची सुरुवात"</string>
+    <string name="range_end" msgid="5941395253238309765">"रेंजचा शेवट"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-ms/strings.xml b/compose/ui/ui/src/androidMain/res/values-ms/strings.xml
index cd366df..4a1b34e8 100644
--- a/compose/ui/ui/src/androidMain/res/values-ms/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ms/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Tutup helaian"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Input tidak sah"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Tetingkap Timbul"</string>
+    <string name="range_start" msgid="7097486360902471446">"Permulaan julat"</string>
+    <string name="range_end" msgid="5941395253238309765">"Penghujung julat"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-my/strings.xml b/compose/ui/ui/src/androidMain/res/values-my/strings.xml
index f866ebb..441a625 100644
--- a/compose/ui/ui/src/androidMain/res/values-my/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-my/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"စာမျက်နှာ ပိတ်ရန်"</string>
     <string name="default_error_message" msgid="8038256446254964252">"ထည့်သွင်းမှု မမှန်ကန်ပါ"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"ပေါ့ပ်အပ် ဝင်းဒိုး"</string>
+    <string name="range_start" msgid="7097486360902471446">"အပိုင်းအခြား အစ"</string>
+    <string name="range_end" msgid="5941395253238309765">"အပိုင်းအခြား အဆုံး"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-nb/strings.xml b/compose/ui/ui/src/androidMain/res/values-nb/strings.xml
index b1c526c..de3de7e 100644
--- a/compose/ui/ui/src/androidMain/res/values-nb/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-nb/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Lukk arket"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Ugyldige inndata"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Forgrunnsvindu"</string>
+    <string name="range_start" msgid="7097486360902471446">"Områdestart"</string>
+    <string name="range_end" msgid="5941395253238309765">"Områdeslutt"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-ne/strings.xml b/compose/ui/ui/src/androidMain/res/values-ne/strings.xml
index 94c0dea..73c7bb5 100644
--- a/compose/ui/ui/src/androidMain/res/values-ne/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ne/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"पाना बन्द गर्नुहोस्"</string>
     <string name="default_error_message" msgid="8038256446254964252">"अवैद्य इन्पुट"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"पपअप विन्डो"</string>
+    <string name="range_start" msgid="7097486360902471446">"दायराको सुरुवात बिन्दु"</string>
+    <string name="range_end" msgid="5941395253238309765">"दायराको अन्तिम बिन्दु"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-nl/strings.xml b/compose/ui/ui/src/androidMain/res/values-nl/strings.xml
index 46b14c4..aa9dd5c 100644
--- a/compose/ui/ui/src/androidMain/res/values-nl/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-nl/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Blad sluiten"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Ongeldige invoer"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Pop-upvenster"</string>
+    <string name="range_start" msgid="7097486360902471446">"Start bereik"</string>
+    <string name="range_end" msgid="5941395253238309765">"Einde bereik"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-or/strings.xml b/compose/ui/ui/src/androidMain/res/values-or/strings.xml
index 7ccc125..9a3fc13 100644
--- a/compose/ui/ui/src/androidMain/res/values-or/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-or/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"ସିଟ୍ ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="default_error_message" msgid="8038256446254964252">"ଅବୈଧ ଇନପୁଟ୍"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"ପପ୍-ଅପ୍ ୱିଣ୍ଡୋ"</string>
+    <string name="range_start" msgid="7097486360902471446">"ରେଞ୍ଜ ଆରମ୍ଭ"</string>
+    <string name="range_end" msgid="5941395253238309765">"ରେଞ୍ଜ ଶେଷ"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-pa/strings.xml b/compose/ui/ui/src/androidMain/res/values-pa/strings.xml
index 09d94be..c58a426 100644
--- a/compose/ui/ui/src/androidMain/res/values-pa/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-pa/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"ਸ਼ੀਟ ਬੰਦ ਕਰੋ"</string>
     <string name="default_error_message" msgid="8038256446254964252">"ਅਵੈਧ ਇਨਪੁੱਟ"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"ਪੌਪ-ਅੱਪ ਵਿੰਡੋ"</string>
+    <string name="range_start" msgid="7097486360902471446">"ਰੇਂਜ ਸ਼ੁਰੂ"</string>
+    <string name="range_end" msgid="5941395253238309765">"ਰੇਂਜ ਸਮਾਪਤ"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-pl/strings.xml b/compose/ui/ui/src/androidMain/res/values-pl/strings.xml
index a533009..4c08550 100644
--- a/compose/ui/ui/src/androidMain/res/values-pl/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-pl/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Zamknij arkusz"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Nieprawidłowe dane wejściowe"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Wyskakujące okienko"</string>
+    <string name="range_start" msgid="7097486360902471446">"Początek zakresu"</string>
+    <string name="range_end" msgid="5941395253238309765">"Koniec zakresu"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-pt-rBR/strings.xml b/compose/ui/ui/src/androidMain/res/values-pt-rBR/strings.xml
index c60184a..737a848 100644
--- a/compose/ui/ui/src/androidMain/res/values-pt-rBR/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-pt-rBR/strings.xml
@@ -33,4 +33,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Fechar planilha"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Entrada inválida"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Janela pop-up"</string>
+    <string name="range_start" msgid="7097486360902471446">"Início do intervalo"</string>
+    <string name="range_end" msgid="5941395253238309765">"Fim do intervalo"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-pt-rPT/strings.xml b/compose/ui/ui/src/androidMain/res/values-pt-rPT/strings.xml
index d3de6809..48cd28d 100644
--- a/compose/ui/ui/src/androidMain/res/values-pt-rPT/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-pt-rPT/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Fechar folha"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Entrada inválida"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Janela pop-up"</string>
+    <string name="range_start" msgid="7097486360902471446">"Início do intervalo"</string>
+    <string name="range_end" msgid="5941395253238309765">"Fim do intervalo"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-pt/strings.xml b/compose/ui/ui/src/androidMain/res/values-pt/strings.xml
index c60184a..737a848 100644
--- a/compose/ui/ui/src/androidMain/res/values-pt/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-pt/strings.xml
@@ -33,4 +33,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Fechar planilha"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Entrada inválida"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Janela pop-up"</string>
+    <string name="range_start" msgid="7097486360902471446">"Início do intervalo"</string>
+    <string name="range_end" msgid="5941395253238309765">"Fim do intervalo"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-ro/strings.xml b/compose/ui/ui/src/androidMain/res/values-ro/strings.xml
index 515d0ed..e7d00c8 100644
--- a/compose/ui/ui/src/androidMain/res/values-ro/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ro/strings.xml
@@ -33,4 +33,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Închideți foaia"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Intrare nevalidă"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Fereastră pop-up"</string>
+    <string name="range_start" msgid="7097486360902471446">"Început de interval"</string>
+    <string name="range_end" msgid="5941395253238309765">"Sfârșit de interval"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-ru/strings.xml b/compose/ui/ui/src/androidMain/res/values-ru/strings.xml
index 1b63a6e..74486dc 100644
--- a/compose/ui/ui/src/androidMain/res/values-ru/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ru/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Закрыть лист"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Неправильный ввод"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Всплывающее окно"</string>
+    <string name="range_start" msgid="7097486360902471446">"Начало диапазона"</string>
+    <string name="range_end" msgid="5941395253238309765">"Конец диапазона"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-si/strings.xml b/compose/ui/ui/src/androidMain/res/values-si/strings.xml
index 5dfc85b..5ad02b8 100644
--- a/compose/ui/ui/src/androidMain/res/values-si/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-si/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"පත්‍රය වසන්න"</string>
     <string name="default_error_message" msgid="8038256446254964252">"වලංගු නොවන ආදානයකි"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"උත්පතන කවුළුව"</string>
+    <string name="range_start" msgid="7097486360902471446">"පරාස ආරම්භය"</string>
+    <string name="range_end" msgid="5941395253238309765">"පරාස අන්තය"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-sk/strings.xml b/compose/ui/ui/src/androidMain/res/values-sk/strings.xml
index 85eaf05..6a65be8 100644
--- a/compose/ui/ui/src/androidMain/res/values-sk/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-sk/strings.xml
@@ -33,4 +33,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Zavrieť hárok"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Neplatný vstup"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Vyskakovacie okno"</string>
+    <string name="range_start" msgid="7097486360902471446">"Začiatok rozsahu"</string>
+    <string name="range_end" msgid="5941395253238309765">"Koniec rozsahu"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-sl/strings.xml b/compose/ui/ui/src/androidMain/res/values-sl/strings.xml
index dae269f..f4489d9 100644
--- a/compose/ui/ui/src/androidMain/res/values-sl/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-sl/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Zapri list"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Neveljaven vnos"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Pojavno okno"</string>
+    <string name="range_start" msgid="7097486360902471446">"Začetek razpona"</string>
+    <string name="range_end" msgid="5941395253238309765">"Konec razpona"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-sq/strings.xml b/compose/ui/ui/src/androidMain/res/values-sq/strings.xml
index f6ab8dd9a..a01f398 100644
--- a/compose/ui/ui/src/androidMain/res/values-sq/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-sq/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Mbyll fletën"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Hyrje e pavlefshme"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Dritare kërcyese"</string>
+    <string name="range_start" msgid="7097486360902471446">"Fillimi i diapazonit"</string>
+    <string name="range_end" msgid="5941395253238309765">"Fundi i diapazonit"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-sr/strings.xml b/compose/ui/ui/src/androidMain/res/values-sr/strings.xml
index aa693dc..b288103 100644
--- a/compose/ui/ui/src/androidMain/res/values-sr/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-sr/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Затворите табелу"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Унос је неважећи"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Искачући прозор"</string>
+    <string name="range_start" msgid="7097486360902471446">"Почетак опсега"</string>
+    <string name="range_end" msgid="5941395253238309765">"Крај опсега"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-sv/strings.xml b/compose/ui/ui/src/androidMain/res/values-sv/strings.xml
index 68542b9..a95b01d 100644
--- a/compose/ui/ui/src/androidMain/res/values-sv/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-sv/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Stäng kalkylarket"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Ogiltiga indata"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Popup-fönster"</string>
+    <string name="range_start" msgid="7097486360902471446">"Intervallets början"</string>
+    <string name="range_end" msgid="5941395253238309765">"Intervallets slut"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-sw/strings.xml b/compose/ui/ui/src/androidMain/res/values-sw/strings.xml
index a48ceb0..b2eac80 100644
--- a/compose/ui/ui/src/androidMain/res/values-sw/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-sw/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Funga laha"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Ulichoweka si sahihi"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Dirisha Ibukizi"</string>
+    <string name="range_start" msgid="7097486360902471446">"Mwanzo wa masafa"</string>
+    <string name="range_end" msgid="5941395253238309765">"Mwisho wa masafa"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-ta/strings.xml b/compose/ui/ui/src/androidMain/res/values-ta/strings.xml
index 9bfb9a1..246c216 100644
--- a/compose/ui/ui/src/androidMain/res/values-ta/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ta/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"ஷீட்டை மூடும்"</string>
     <string name="default_error_message" msgid="8038256446254964252">"தவறான உள்ளீடு"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"பாப்-அப் சாளரம்"</string>
+    <string name="range_start" msgid="7097486360902471446">"வரம்பு தொடக்கம்"</string>
+    <string name="range_end" msgid="5941395253238309765">"வரம்பு முடிவு"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-te/strings.xml b/compose/ui/ui/src/androidMain/res/values-te/strings.xml
index 4a39a93..fce8a54 100644
--- a/compose/ui/ui/src/androidMain/res/values-te/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-te/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"షీట్‌ను మూసివేయి"</string>
     <string name="default_error_message" msgid="8038256446254964252">"ఇన్‌పుట్ చెల్లదు"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"పాప్-అప్ విండో"</string>
+    <string name="range_start" msgid="7097486360902471446">"పరిధి ప్రారంభమయింది"</string>
+    <string name="range_end" msgid="5941395253238309765">"పరిధి ముగిసింది"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-th/strings.xml b/compose/ui/ui/src/androidMain/res/values-th/strings.xml
index 164c459..be43403 100644
--- a/compose/ui/ui/src/androidMain/res/values-th/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-th/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"ปิดชีต"</string>
     <string name="default_error_message" msgid="8038256446254964252">"อินพุตไม่ถูกต้อง"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"หน้าต่างป๊อปอัป"</string>
+    <string name="range_start" msgid="7097486360902471446">"จุดเริ่มต้นของช่วง"</string>
+    <string name="range_end" msgid="5941395253238309765">"จุดสิ้นสุดของช่วง"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-tl/strings.xml b/compose/ui/ui/src/androidMain/res/values-tl/strings.xml
index 09789e4..073a722 100644
--- a/compose/ui/ui/src/androidMain/res/values-tl/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-tl/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Isara ang sheet"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Invalid na input"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Window ng Pop-Up"</string>
+    <string name="range_start" msgid="7097486360902471446">"Simula ng range"</string>
+    <string name="range_end" msgid="5941395253238309765">"Katapusan ng range"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-tr/strings.xml b/compose/ui/ui/src/androidMain/res/values-tr/strings.xml
index 6a0a351..738e1a1 100644
--- a/compose/ui/ui/src/androidMain/res/values-tr/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-tr/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Sayfayı kapat"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Geçersiz giriş"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Pop-up Pencere"</string>
+    <string name="range_start" msgid="7097486360902471446">"Aralık başlangıcı"</string>
+    <string name="range_end" msgid="5941395253238309765">"Aralık sonu"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-uk/strings.xml b/compose/ui/ui/src/androidMain/res/values-uk/strings.xml
index 8753298..eb77ff6 100644
--- a/compose/ui/ui/src/androidMain/res/values-uk/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-uk/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Закрити аркуш"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Введено недійсні дані"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Спливаюче вікно"</string>
+    <string name="range_start" msgid="7097486360902471446">"Початок діапазону"</string>
+    <string name="range_end" msgid="5941395253238309765">"Кінець діапазону"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-ur/strings.xml b/compose/ui/ui/src/androidMain/res/values-ur/strings.xml
index 1657099..0406005 100644
--- a/compose/ui/ui/src/androidMain/res/values-ur/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-ur/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"شیٹ بند کریں"</string>
     <string name="default_error_message" msgid="8038256446254964252">"غلط ان پٹ"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"پاپ اپ ونڈو"</string>
+    <string name="range_start" msgid="7097486360902471446">"رینج کی شروعات"</string>
+    <string name="range_end" msgid="5941395253238309765">"رینج کا اختتام"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-uz/strings.xml b/compose/ui/ui/src/androidMain/res/values-uz/strings.xml
index ffd212b..68df94a 100644
--- a/compose/ui/ui/src/androidMain/res/values-uz/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-uz/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Varaqni yopish"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Kiritilgan axborot xato"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Qalqib chiquvchi oyna"</string>
+    <string name="range_start" msgid="7097486360902471446">"Oraliq boshi"</string>
+    <string name="range_end" msgid="5941395253238309765">"Oraliq oxiri"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-vi/strings.xml b/compose/ui/ui/src/androidMain/res/values-vi/strings.xml
index cbf4201..99bd579 100644
--- a/compose/ui/ui/src/androidMain/res/values-vi/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-vi/strings.xml
@@ -33,4 +33,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Đóng trang tính"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Giá trị nhập không hợp lệ"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Cửa sổ bật lên"</string>
+    <string name="range_start" msgid="7097486360902471446">"Điểm bắt đầu phạm vi"</string>
+    <string name="range_end" msgid="5941395253238309765">"Điểm kết thúc phạm vi"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-zh-rCN/strings.xml b/compose/ui/ui/src/androidMain/res/values-zh-rCN/strings.xml
index e315466..e6f5a19 100644
--- a/compose/ui/ui/src/androidMain/res/values-zh-rCN/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-zh-rCN/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"关闭工作表"</string>
     <string name="default_error_message" msgid="8038256446254964252">"输入无效"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"弹出式窗口"</string>
+    <string name="range_start" msgid="7097486360902471446">"范围起点"</string>
+    <string name="range_end" msgid="5941395253238309765">"范围终点"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-zh-rHK/strings.xml b/compose/ui/ui/src/androidMain/res/values-zh-rHK/strings.xml
index 96830e6..6291f69 100644
--- a/compose/ui/ui/src/androidMain/res/values-zh-rHK/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-zh-rHK/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"閂表單"</string>
     <string name="default_error_message" msgid="8038256446254964252">"輸入嘅資料無效"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"彈出式視窗"</string>
+    <string name="range_start" msgid="7097486360902471446">"範圍開始"</string>
+    <string name="range_end" msgid="5941395253238309765">"範圍結束"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-zh-rTW/strings.xml b/compose/ui/ui/src/androidMain/res/values-zh-rTW/strings.xml
index 22beba0..22304ae 100644
--- a/compose/ui/ui/src/androidMain/res/values-zh-rTW/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-zh-rTW/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"關閉功能表"</string>
     <string name="default_error_message" msgid="8038256446254964252">"輸入內容無效"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"彈出式視窗"</string>
+    <string name="range_start" msgid="7097486360902471446">"範圍起點"</string>
+    <string name="range_end" msgid="5941395253238309765">"範圍終點"</string>
 </resources>
diff --git a/compose/ui/ui/src/androidMain/res/values-zu/strings.xml b/compose/ui/ui/src/androidMain/res/values-zu/strings.xml
index 3d87da5..e887688 100644
--- a/compose/ui/ui/src/androidMain/res/values-zu/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values-zu/strings.xml
@@ -31,4 +31,6 @@
     <string name="close_sheet" msgid="7573152094250666567">"Vala ishidi"</string>
     <string name="default_error_message" msgid="8038256446254964252">"Okufakwayo okungalungile"</string>
     <string name="default_popup_window_title" msgid="6312721426453364202">"Iwindi Lesikhashana"</string>
+    <string name="range_start" msgid="7097486360902471446">"Ukuqala kobubanzi"</string>
+    <string name="range_end" msgid="5941395253238309765">"Umkhawulo wobubanzi"</string>
 </resources>
diff --git a/development/build_log_simplifier/message-flakes.ignore b/development/build_log_simplifier/message-flakes.ignore
index 132eb3f..5915df7 100644
--- a/development/build_log_simplifier/message-flakes.ignore
+++ b/development/build_log_simplifier/message-flakes.ignore
@@ -111,8 +111,8 @@
 # > Task :wear:wear-watchface:testDebugUnitTest
 System\.logW: A resource was acquired at attached stack trace but never released\. See java\.io\.Closeable for information on avoiding resource leaks\.java\.lang\.Throwable: Explicit termination method 'dispose' not called
 System\.logW: A resource was acquired at attached stack trace but never released\. See java\.io\.Closeable for information on avoiding resource leaks\.java\.lang\.Throwable: Explicit termination method 'release' not called
-# > Task :camera:camera-camera2-pipe-integration:kaptReleaseKotlin
-warning\: The following options were not recognized by any processor\: \'\[dagger\.fastInit\, kapt\.kotlin\.generated\, dagger\.fullBindingGraphValidation\]\'
+# https://youtrack.jetbrains.com/issue/KT-46940
+warning\: The following options were not recognized by any processor\: \'\[.*\]\'
 # > Task :checkNativeApi / :generateNativeApi / :updateNativeApi
 Native API checking is currently not supported on non-linux devices
 # Known warning for Googlers
diff --git a/development/build_log_simplifier/messages.ignore b/development/build_log_simplifier/messages.ignore
index da32135..756c071 100644
--- a/development/build_log_simplifier/messages.ignore
+++ b/development/build_log_simplifier/messages.ignore
@@ -605,4 +605,6 @@
 package=".*" found in source AndroidManifest\.xml: .*/AndroidManifest\.xml\.
 Setting the namespace via a source AndroidManifest\.xml's package attribute is deprecated\.
 Please instead set the namespace \(or testNamespace\) in the module's build\.gradle file, as described here: https://developer\.android\.com/studio/build/configure\-app\-module\#set\-namespace
-This migration can be done automatically using the AGP Upgrade Assistant, please refer to https://developer\.android\.com/studio/build/agp\-upgrade\-assistant for more information\.
\ No newline at end of file
+This migration can be done automatically using the AGP Upgrade Assistant, please refer to https://developer\.android\.com/studio/build/agp\-upgrade\-assistant for more information\.
+# > Task :compose:ui:ui:integration-tests:ui-demos:lintAnalyzeDebug
+Index data read correctly
diff --git a/development/diagnose-build-failure/diagnose-build-failure.sh b/development/diagnose-build-failure/diagnose-build-failure.sh
index eaaed58..76c46a5 100755
--- a/development/diagnose-build-failure/diagnose-build-failure.sh
+++ b/development/diagnose-build-failure/diagnose-build-failure.sh
@@ -338,6 +338,8 @@
   cp -r "$tempDir/prev" "$requiredTasksWork"
   mkdir -p "$requiredTasksWork/tasks"
   bash -c "cd $requiredTasksWork/tasks && split -l 1 '$taskListFile'"
+  # also include the original tasks in case either we failed to compute the list of tasks (due to the build failing during project configuration) or there are too many tasks to fit in one command line invocation
+  echo "$gradleTasks" > "$requiredTasksWork/tasks/givenTasks"
 
   rm -rf "$requiredTasksDir"
   # Build the command for passing to diff-filterer.
diff --git a/development/project-creator/compose-template/groupId/artifactId/build.gradle b/development/project-creator/compose-template/groupId/artifactId/build.gradle
index a1d099b..97901de 100644
--- a/development/project-creator/compose-template/groupId/artifactId/build.gradle
+++ b/development/project-creator/compose-template/groupId/artifactId/build.gradle
@@ -92,6 +92,10 @@
     }
 }
 
+android {
+    namespace "<PACKAGE>"
+}
+
 androidx {
     name = "<NAME>"
     type = LibraryType.<LIBRARY_TYPE>
diff --git a/development/project-creator/compose-template/groupId/artifactId/src/androidAndroidTest/AndroidManifest.xml b/development/project-creator/compose-template/groupId/artifactId/src/androidAndroidTest/AndroidManifest.xml
deleted file mode 100644
index fc95144..0000000
--- a/development/project-creator/compose-template/groupId/artifactId/src/androidAndroidTest/AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright <YEAR> The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT 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"
-    package="<PACKAGE>.test">
-
-</manifest>
diff --git a/development/project-creator/compose-template/groupId/artifactId/src/androidMain/AndroidManifest.xml b/development/project-creator/compose-template/groupId/artifactId/src/androidMain/AndroidManifest.xml
deleted file mode 100644
index b5e2156..0000000
--- a/development/project-creator/compose-template/groupId/artifactId/src/androidMain/AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright <YEAR> The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT 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"
-    package="<PACKAGE>">
-
-</manifest>
\ No newline at end of file
diff --git a/development/project-creator/create_project.py b/development/project-creator/create_project.py
index ef22bc4..db54a02e 100755
--- a/development/project-creator/create_project.py
+++ b/development/project-creator/create_project.py
@@ -352,10 +352,8 @@
 
     Given androidx.foo.bar:bar-qux, the structure will be:
     frameworks/support/foo/bar/bar-qux/build.gradle
-    frameworks/support/foo/bar/bar-qux/src/main/AndroidManifest.xml
     frameworks/support/foo/bar/bar-qux/src/main/androidx/foo/bar/package-info.java
     frameworks/support/foo/bar/bar-qux/src/main/androidx/foo/bar/artifact-documentation.md
-    frameworks/support/foo/bar/bar-qux/src/androidTest/AndroidManifest.xml
     frameworks/support/foo/bar/bar-qux/api/current.txt
 
     Args:
@@ -434,22 +432,11 @@
     year = get_year()
     sed("<YEAR>", year, full_artifact_path + "/build.gradle")
     sed("<YEAR>", year, full_package_docs_file)
-    if is_compose_project:
-        sed("<YEAR>", year, full_artifact_path + "/src/androidAndroidTest/AndroidManifest.xml")
-        sed("<YEAR>", year, full_artifact_path + "/src/androidMain/AndroidManifest.xml")
-    else:
-        sed("<YEAR>", year, full_artifact_path + "/src/androidTest/AndroidManifest.xml")
-        sed("<YEAR>", year, full_artifact_path + "/src/main/AndroidManifest.xml")
 
     # Populate the PACKAGE
     package = generate_package_name(group_id, artifact_id)
     sed("<PACKAGE>", package, full_package_docs_file)
-    if is_compose_project:
-        sed("<PACKAGE>", package, full_artifact_path + "/src/androidAndroidTest/AndroidManifest.xml")
-        sed("<PACKAGE>", package, full_artifact_path + "/src/androidMain/AndroidManifest.xml")
-    else:
-        sed("<PACKAGE>", package, full_artifact_path + "/src/androidTest/AndroidManifest.xml")
-        sed("<PACKAGE>", package, full_artifact_path + "/src/main/AndroidManifest.xml")
+    sed("<PACKAGE>", package, full_artifact_path + "/build.gradle")
 
     # Populate the VERSION macro
     group_id_version_macro = get_group_id_version_macro(group_id)
diff --git a/development/project-creator/java-template/groupId/artifactId/build.gradle b/development/project-creator/java-template/groupId/artifactId/build.gradle
index 32ce1d5..ab747fd 100644
--- a/development/project-creator/java-template/groupId/artifactId/build.gradle
+++ b/development/project-creator/java-template/groupId/artifactId/build.gradle
@@ -26,6 +26,10 @@
     // Add dependencies here
 }
 
+android {
+    namespace "<PACKAGE>"
+}
+
 androidx {
     name = "<NAME>"
     type = LibraryType.<LIBRARY_TYPE>
diff --git a/development/project-creator/java-template/groupId/artifactId/src/androidTest/AndroidManifest.xml b/development/project-creator/java-template/groupId/artifactId/src/androidTest/AndroidManifest.xml
deleted file mode 100644
index fc95144..0000000
--- a/development/project-creator/java-template/groupId/artifactId/src/androidTest/AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright <YEAR> The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT 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"
-    package="<PACKAGE>.test">
-
-</manifest>
diff --git a/development/project-creator/java-template/groupId/artifactId/src/main/AndroidManifest.xml b/development/project-creator/java-template/groupId/artifactId/src/main/AndroidManifest.xml
deleted file mode 100644
index b5e2156..0000000
--- a/development/project-creator/java-template/groupId/artifactId/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright <YEAR> The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT 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"
-    package="<PACKAGE>">
-
-</manifest>
\ No newline at end of file
diff --git a/development/project-creator/kotlin-template/groupId/artifactId/build.gradle b/development/project-creator/kotlin-template/groupId/artifactId/build.gradle
index fb039d1..1413c1c 100644
--- a/development/project-creator/kotlin-template/groupId/artifactId/build.gradle
+++ b/development/project-creator/kotlin-template/groupId/artifactId/build.gradle
@@ -27,6 +27,10 @@
     // Add dependencies here
 }
 
+android {
+    namespace "<PACKAGE>"
+}
+
 androidx {
     name = "<NAME>"
     type = LibraryType.<LIBRARY_TYPE>
diff --git a/development/project-creator/kotlin-template/groupId/artifactId/src/androidTest/AndroidManifest.xml b/development/project-creator/kotlin-template/groupId/artifactId/src/androidTest/AndroidManifest.xml
deleted file mode 100644
index fc95144..0000000
--- a/development/project-creator/kotlin-template/groupId/artifactId/src/androidTest/AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright <YEAR> The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT 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"
-    package="<PACKAGE>.test">
-
-</manifest>
diff --git a/development/project-creator/kotlin-template/groupId/artifactId/src/main/AndroidManifest.xml b/development/project-creator/kotlin-template/groupId/artifactId/src/main/AndroidManifest.xml
deleted file mode 100644
index b5e2156..0000000
--- a/development/project-creator/kotlin-template/groupId/artifactId/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright <YEAR> The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT 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"
-    package="<PACKAGE>">
-
-</manifest>
\ No newline at end of file
diff --git a/development/project-creator/native-template/groupId/artifactId/build.gradle b/development/project-creator/native-template/groupId/artifactId/build.gradle
index a2bdd1e..d3ea844 100644
--- a/development/project-creator/native-template/groupId/artifactId/build.gradle
+++ b/development/project-creator/native-template/groupId/artifactId/build.gradle
@@ -37,6 +37,7 @@
 }
 
 android {
+    namespace "<PACKAGE>"
     defaultConfig {
         externalNativeBuild {
             cmake {
diff --git a/development/project-creator/native-template/groupId/artifactId/src/androidTest/AndroidManifest.xml b/development/project-creator/native-template/groupId/artifactId/src/androidTest/AndroidManifest.xml
deleted file mode 100644
index fc95144..0000000
--- a/development/project-creator/native-template/groupId/artifactId/src/androidTest/AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright <YEAR> The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT 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"
-    package="<PACKAGE>.test">
-
-</manifest>
diff --git a/development/project-creator/native-template/groupId/artifactId/src/main/AndroidManifest.xml b/development/project-creator/native-template/groupId/artifactId/src/main/AndroidManifest.xml
deleted file mode 100644
index b5e2156..0000000
--- a/development/project-creator/native-template/groupId/artifactId/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  Copyright <YEAR> The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT 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"
-    package="<PACKAGE>">
-
-</manifest>
\ No newline at end of file
diff --git a/development/project-creator/native-template/groupId/artifactId/src/main/cpp/include/.keep b/development/project-creator/native-template/groupId/artifactId/src/main/cpp/include/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/development/project-creator/native-template/groupId/artifactId/src/main/cpp/include/.keep
diff --git a/development/update_studio.sh b/development/update_studio.sh
index 66d8b24..464747e 100755
--- a/development/update_studio.sh
+++ b/development/update_studio.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 # Get versions
-AGP_VERSION=${1:-7.3.0-alpha05}
-STUDIO_VERSION_STRING=${2:-"Android Studio Dolphin (2021.3.1) Canary 5"}
+AGP_VERSION=${1:-7.3.0-alpha07}
+STUDIO_VERSION_STRING=${2:-"Android Studio Dolphin (2021.3.1) Canary 7"}
 STUDIO_IFRAME_LINK=`curl "https://developer.android.com/studio/archive.html" | grep iframe | sed "s/.*src=\"\([a-zA-Z0-9\/\._]*\)\".*/https:\/\/android-dot-devsite-v2-prod.appspot.com\1/g"`
 STUDIO_LINK=`curl -s $STUDIO_IFRAME_LINK | grep -C30 "$STUDIO_VERSION_STRING" | grep Linux | tail -n 1 | sed 's/.*a href="\(.*\).*"/\1/g'`
 STUDIO_VERSION=`echo $STUDIO_LINK | sed "s/.*ide-zips\/\(.*\)\/android-studio-.*/\1/g"`
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index cb23e95..7f5bbac 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 = "7.3.0-alpha05"
+androidGradlePlugin = "7.3.0-alpha07"
 # 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 = "30.3.0-alpha05"
+androidLint = "30.3.0-alpha07"
 # 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 = "2021.3.1.5"
+androidStudio = "2021.3.1.7"
 # -----------------------------------------------------------------------------
 
 androidGradlePluginMin = "7.0.4"
diff --git a/health/health-data-client/src/main/java/androidx/health/data/client/HealthDataClient.kt b/health/health-data-client/src/main/java/androidx/health/data/client/HealthDataClient.kt
index 7ae4555..83de6a7 100644
--- a/health/health-data-client/src/main/java/androidx/health/data/client/HealthDataClient.kt
+++ b/health/health-data-client/src/main/java/androidx/health/data/client/HealthDataClient.kt
@@ -27,6 +27,7 @@
 import androidx.health.data.client.response.ReadRecordResponse
 import androidx.health.data.client.response.ReadRecordsResponse
 import androidx.health.data.client.time.TimeRangeFilter
+import java.lang.IllegalStateException
 import kotlin.reflect.KClass
 
 /** Interface to access health and fitness records. */
@@ -38,6 +39,7 @@
      *
      * @throws RemoteException For any IPC transportation failures.
      * @throws IOException For any disk I/O issues.
+     * @throws IllegalStateException If service is not available.
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     suspend fun getGrantedPermissions(permissions: Set<Permission>): Set<Permission>
@@ -52,6 +54,7 @@
      * @throws RemoteException For any IPC transportation failures.
      * @throws SecurityException For requests with unpermitted access.
      * @throws IOException For any disk I/O issues.
+     * @throws IllegalStateException If service is not available.
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     suspend fun insertRecords(records: List<Record>): InsertRecordResponse
@@ -64,6 +67,7 @@
      * @throws RemoteException For any IPC transportation failures.
      * @throws SecurityException For requests with unpermitted access.
      * @throws IOException For any disk I/O issues.
+     * @throws IllegalStateException If service is not available.
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY) suspend fun updateRecords(records: List<Record>)
 
@@ -77,6 +81,7 @@
      * @throws RemoteException For any IPC transportation failures.
      * @throws SecurityException For requests with unpermitted access.
      * @throws IOException For any disk I/O issues.
+     * @throws IllegalStateException If service is not available.
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     suspend fun deleteRecords(
@@ -99,6 +104,7 @@
      * @throws RemoteException For any IPC transportation failures.
      * @throws SecurityException For requests with unpermitted access.
      * @throws IOException For any disk I/O issues.
+     * @throws IllegalStateException If service is not available.
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     suspend fun deleteRecords(recordType: KClass<out Record>, timeRangeFilter: TimeRangeFilter)
@@ -112,6 +118,7 @@
      * @throws RemoteException For any IPC transportation failures.
      * @throws SecurityException For requests with unpermitted access.
      * @throws IOException For any disk I/O issues.
+     * @throws IllegalStateException If service is not available.
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     suspend fun <T : Record> readRecord(recordType: KClass<T>, uid: String): ReadRecordResponse<T>
@@ -137,6 +144,7 @@
      * @throws SecurityException For requests with unpermitted access.
      * @throws IOException For any disk I/O issues.
      * @throws IllegalStateException For incorrectly set parameters.
+     * @throws IllegalStateException If service is not available.
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     suspend fun <T : Record> readRecords(
@@ -270,6 +278,20 @@
             pageToken = null
         )
 
+    /**
+     * Reads [AggregateMetric]s according to requested read criteria: [Record]s from
+     * [dataOriginFilter] and within [timeRangeFilter]
+     *
+     * @param aggregateMetrics The [AggregateMetric]s to aggregate
+     * @param timeRangeFilter The [TimeRangeFilter] to read from.
+     * @param dataOriginFilter List of [DataOrigin] to read from, or empty for no filter.
+     *
+     * @return a response containing a collection of [Record]s.
+     * @throws RemoteException For any IPC transportation failures.
+     * @throws SecurityException For requests with unpermitted access.
+     * @throws IOException For any disk I/O issues.
+     * @throws IllegalStateException If service is not available.
+     */
     // TODO(b/219327548): Expand this to reuse readRecords time range filter and data origin
     // filters.
     @RestrictTo(RestrictTo.Scope.LIBRARY)
@@ -295,6 +317,7 @@
      * @param request Includes interested types of record to observe changes and optional filters.
      * @throws RemoteException For any IPC transportation failures.
      * @throws SecurityException For requests with unpermitted access.
+     * @throws IllegalStateException If service is not available.
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     suspend fun getChangesToken(request: ChangesTokenRequest): String
@@ -315,6 +338,7 @@
      * Health Platform.
      * @throws RemoteException For any IPC transportation failures.
      * @throws SecurityException For requests with unpermitted access.
+     * @throws IllegalStateException If service is not available.
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     suspend fun getChanges(changesToken: String): ChangesResponse
diff --git a/health/health-data-client/src/main/java/androidx/health/data/client/HealthDataService.kt b/health/health-data-client/src/main/java/androidx/health/data/client/HealthDataService.kt
index b3e2db9..7da103c 100644
--- a/health/health-data-client/src/main/java/androidx/health/data/client/HealthDataService.kt
+++ b/health/health-data-client/src/main/java/androidx/health/data/client/HealthDataService.kt
@@ -18,6 +18,7 @@
 import android.content.Context
 import android.content.pm.PackageManager
 import android.os.Build
+import androidx.annotation.ChecksSdkIntAtLeast
 import androidx.annotation.RestrictTo
 import androidx.health.data.client.impl.HealthDataClientImpl
 import androidx.health.platform.client.HealthDataService
@@ -44,7 +45,7 @@
         context: Context,
         packageNames: List<String> = listOf(DEFAULT_PROVIDER_PACKAGE_NAME),
     ): Boolean {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1) {
+        if (!isSdkVersionSufficient()) {
             return false
         }
         return packageNames.any { isPackageInstalled(context.packageManager, it) }
@@ -55,7 +56,8 @@
      *
      * @param packageName optional package provider to choose implementation from
      * @return instance of [HealthDataClient] ready for issuing requests
-     * @throws UnsupportedOperationException if service not available
+     * @throws UnsupportedOperationException if service not available due to SDK version too low
+     * @throws IllegalStateException if service not available due to not installed
      */
     @JvmOverloads
     @JvmStatic
@@ -63,13 +65,19 @@
         context: Context,
         packageNames: List<String> = listOf(DEFAULT_PROVIDER_PACKAGE_NAME),
     ): HealthDataClient {
+        if (!isSdkVersionSufficient()) {
+            throw UnsupportedOperationException("SDK version too low")
+        }
         if (!isAvailable(context, packageNames)) {
-            throw UnsupportedOperationException("Not supported yet")
+            throw IllegalStateException("Service not available")
         }
         val enabledPackage = packageNames.first { isPackageInstalled(context.packageManager, it) }
         return HealthDataClientImpl(HealthDataService.getClient(context, enabledPackage))
     }
 
+    @ChecksSdkIntAtLeast
+    private fun isSdkVersionSufficient() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
+
     @Suppress("Deprecation") // getApplicationInfo deprecated in T but is the only choice.
     private fun isPackageInstalled(packageManager: PackageManager, packageName: String): Boolean {
         return try {
diff --git a/health/health-data-client/src/main/java/androidx/health/platform/client/impl/ipc/internal/ServiceConnection.java b/health/health-data-client/src/main/java/androidx/health/platform/client/impl/ipc/internal/ServiceConnection.java
index ba4c9d5..099e013 100644
--- a/health/health-data-client/src/main/java/androidx/health/platform/client/impl/ipc/internal/ServiceConnection.java
+++ b/health/health-data-client/src/main/java/androidx/health/platform/client/impl/ipc/internal/ServiceConnection.java
@@ -35,7 +35,6 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Queue;
-import java.util.concurrent.CancellationException;
 import java.util.concurrent.ConcurrentLinkedQueue;
 
 import javax.annotation.concurrent.NotThreadSafe;
@@ -142,7 +141,7 @@
                             + "' and action '"
                             + mConnectionConfiguration.getBindAction()
                             + "'.");
-            handleNonRetriableDisconnection(new CancellationException("Service not available"));
+            handleNonRetriableDisconnection(new IllegalStateException("Service not available"));
         }
     }
 
@@ -305,7 +304,7 @@
                                 TAG,
                                 "Binder died for client:"
                                         + mConnectionConfiguration.getClientName());
-                        handleRetriableDisconnection(new CancellationException());
+                        handleRetriableDisconnection(new RemoteException("Binder died"));
                     },
                     /* flags= */ 0);
         } catch (RemoteException exception) {
@@ -326,7 +325,7 @@
     @Override
     public void onBindingDied(ComponentName name) {
         Log.e(TAG, "Binding died for client '" + mConnectionConfiguration.getClientName() + "'.");
-        handleRetriableDisconnection(new CancellationException());
+        handleRetriableDisconnection(new RemoteException("Binding died"));
     }
 
     @Override
@@ -337,6 +336,6 @@
                         + mConnectionConfiguration.getClientName()
                         + "', binder is null");
         // This connection will never be usable, don't bother with retries.
-        handleRetriableDisconnection(new CancellationException("Null binding"));
+        handleRetriableDisconnection(new IllegalStateException("Null binding"));
     }
 }
diff --git a/health/health-data-client/src/test/java/androidx/health/data/client/impl/HealthDataClientImplTest.kt b/health/health-data-client/src/test/java/androidx/health/data/client/impl/HealthDataClientImplTest.kt
index 9f2942b..70ba21d 100644
--- a/health/health-data-client/src/test/java/androidx/health/data/client/impl/HealthDataClientImplTest.kt
+++ b/health/health-data-client/src/test/java/androidx/health/data/client/impl/HealthDataClientImplTest.kt
@@ -114,7 +114,7 @@
         Intents.release()
     }
 
-    @Test
+    @Test(timeout = 60000L)
     fun apiMethods_hasError_throwsException() {
         for (error in errorCodeExceptionMap) {
             fakeAhpServiceStub.setErrorCode(error.key)
@@ -126,8 +126,8 @@
             }
 
             // wait for the client to enqueue message and handle message
-            Thread.sleep(Duration.ofMillis(500).toMillis())
-            Shadows.shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(500))
+            Thread.sleep(Duration.ofMillis(1000).toMillis())
+            Shadows.shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(1000))
 
             for (response in responseList) {
                 assertThrows(error.value.java) { runBlocking { response.await() } }
@@ -135,7 +135,7 @@
         }
     }
 
-    @Test
+    @Test(timeout = 60000L)
     fun insertRecords_steps() {
         val deferred =
             CoroutineScope(Dispatchers.Default).async {
@@ -153,8 +153,8 @@
             }
 
         // wait for the client to enqueue message and handle message
-        Thread.sleep(Duration.ofMillis(500).toMillis())
-        Shadows.shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(500))
+        Thread.sleep(Duration.ofMillis(1000).toMillis())
+        Shadows.shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(1000))
 
         val response = runBlocking { deferred.await() }
         assertThat(response.recordUidsList).containsExactly("0")
@@ -169,7 +169,7 @@
             )
     }
 
-    @Test
+    @Test(timeout = 60000L)
     fun insertRecords_weight() {
         val deferred =
             CoroutineScope(Dispatchers.Default).async {
@@ -185,8 +185,8 @@
             }
 
         // wait for the client to enqueue message and handle message
-        Thread.sleep(Duration.ofMillis(500).toMillis())
-        Shadows.shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(500))
+        Thread.sleep(Duration.ofMillis(1000).toMillis())
+        Shadows.shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(1000))
 
         val response = runBlocking { deferred.await() }
         assertThat(response.recordUidsList).containsExactly("0")
@@ -200,7 +200,7 @@
             )
     }
 
-    @Test
+    @Test(timeout = 60000L)
     fun insertRecords_nutrition() {
         val deferred =
             CoroutineScope(Dispatchers.Default).async {
@@ -219,8 +219,8 @@
             }
 
         // wait for the client to enqueue message and handle message
-        Thread.sleep(Duration.ofMillis(500).toMillis())
-        Shadows.shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(500))
+        Thread.sleep(Duration.ofMillis(1000).toMillis())
+        Shadows.shadowOf(Looper.getMainLooper()).idleFor(Duration.ofMillis(1000))
 
         val response = runBlocking { deferred.await() }
         assertThat(response.recordUidsList).containsExactly("0")
diff --git a/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt b/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt
index 9b801e1..6482e0a 100644
--- a/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt
+++ b/lifecycle/lifecycle-livedata-core-ktx-lint/src/main/java/androidx/lifecycle/lint/NonNullableMutableLiveDataDetector.kt
@@ -30,6 +30,7 @@
 import com.android.tools.lint.detector.api.isKotlin
 import com.intellij.psi.PsiClassType
 import com.intellij.psi.PsiVariable
+import com.intellij.psi.PsiWhiteSpace
 import com.intellij.psi.impl.source.PsiImmediateClassType
 import org.jetbrains.kotlin.asJava.elements.KtLightTypeParameter
 import org.jetbrains.kotlin.psi.KtCallExpression
@@ -151,8 +152,14 @@
                 // node.sourcePsi : `value`
                 // dot: `.`
                 // variable: `liveDataField`
-                val dot = node.sourcePsi?.prevSibling
-                val variable = dot?.prevSibling?.firstChild
+                val dot = generateSequence(node.sourcePsi?.prevSibling) {
+                    it.prevSibling
+                }.firstOrNull { it !is PsiWhiteSpace }
+                val variable = generateSequence(generateSequence(dot?.prevSibling) {
+                    it.prevSibling
+                }.firstOrNull { it !is PsiWhiteSpace }) {
+                    it.firstChild
+                }.firstOrNull { it !is PsiWhiteSpace }
                 return variable?.text
             }
         }
diff --git a/lifecycle/lifecycle-livedata-core-ktx-lint/src/test/java/androidx/lifecycle/livedata/core/lint/NonNullableMutableLiveDataDetectorTest.kt b/lifecycle/lifecycle-livedata-core-ktx-lint/src/test/java/androidx/lifecycle/livedata/core/lint/NonNullableMutableLiveDataDetectorTest.kt
index f6e42c3..b6c0412 100644
--- a/lifecycle/lifecycle-livedata-core-ktx-lint/src/test/java/androidx/lifecycle/livedata/core/lint/NonNullableMutableLiveDataDetectorTest.kt
+++ b/lifecycle/lifecycle-livedata-core-ktx-lint/src/test/java/androidx/lifecycle/livedata/core/lint/NonNullableMutableLiveDataDetectorTest.kt
@@ -23,7 +23,6 @@
 import com.android.tools.lint.checks.infrastructure.LintDetectorTest
 import com.android.tools.lint.checks.infrastructure.TestFile
 import com.android.tools.lint.checks.infrastructure.TestLintResult
-import com.android.tools.lint.checks.infrastructure.TestMode
 import com.android.tools.lint.detector.api.Detector
 import com.android.tools.lint.detector.api.Issue
 import org.junit.Ignore
@@ -40,7 +39,6 @@
 
     private fun check(vararg files: TestFile): TestLintResult {
         return lint().files(*files, *STUBS)
-            .skipTestModes(TestMode.WHITESPACE) // b/203246682
             .run()
     }
 
diff --git a/lint-checks/src/main/java/androidx/build/lint/BanUncheckedReflection.kt b/lint-checks/src/main/java/androidx/build/lint/BanUncheckedReflection.kt
index 6914489..62f8608 100644
--- a/lint-checks/src/main/java/androidx/build/lint/BanUncheckedReflection.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/BanUncheckedReflection.kt
@@ -23,11 +23,11 @@
 import com.android.tools.lint.detector.api.Issue
 import com.android.tools.lint.detector.api.JavaContext
 import com.android.tools.lint.detector.api.Scope
-import com.android.tools.lint.checks.VersionChecks.Companion.isWithinVersionCheckConditional
 import com.android.sdklib.SdkVersionInfo.HIGHEST_KNOWN_API
 import com.android.tools.lint.detector.api.Incident
 import com.android.tools.lint.detector.api.Severity
 import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.android.tools.lint.detector.api.VersionChecks
 import com.intellij.psi.PsiMethod
 import org.jetbrains.uast.UCallExpression
 
@@ -51,8 +51,13 @@
         if (!context.evaluator.isMemberInClass(method, METHOD_REFLECTION_CLASS)) return
 
         // Flag if the call isn't inside an SDK_INT check.
-        if (!isWithinVersionCheckConditional(context, node, HIGHEST_KNOWN_API, false) &&
-            !isWithinVersionCheckConditional(context, node, 1, true)
+        if (!VersionChecks.isWithinVersionCheckConditional(
+                context,
+                node,
+                HIGHEST_KNOWN_API,
+                false
+            ) &&
+            !VersionChecks.isWithinVersionCheckConditional(context, node, 1, true)
         ) {
             val incident = Incident(context)
                 .issue(ISSUE)
diff --git a/lint-checks/src/main/java/androidx/build/lint/CameraXQuirksClassDetector.kt b/lint-checks/src/main/java/androidx/build/lint/CameraXQuirksClassDetector.kt
index e1bfce9..842f9c3 100644
--- a/lint-checks/src/main/java/androidx/build/lint/CameraXQuirksClassDetector.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/CameraXQuirksClassDetector.kt
@@ -38,15 +38,9 @@
     override fun createUastHandler(context: JavaContext) = object : UElementHandler() {
 
         override fun visitClass(node: UClass) {
-            val elements = node.implementsList?.getReferenceElements()
-            var isQuirk = false
-            if (elements != null) {
-                for (element in elements) {
-                    if (("Quirk").equals(element.referenceName)) {
-                        isQuirk = true
-                    }
-                }
-            }
+            val isQuirk = node.implementsList?.referenceElements?.find { it ->
+                it.referenceName!!.endsWith("Quirk")
+            } != null
 
             if (isQuirk) {
                 val comments = node.comments
diff --git a/lint-checks/src/main/java/androidx/build/lint/ClassVerificationFailureDetector.kt b/lint-checks/src/main/java/androidx/build/lint/ClassVerificationFailureDetector.kt
index 6d40535..781aa7d 100644
--- a/lint-checks/src/main/java/androidx/build/lint/ClassVerificationFailureDetector.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/ClassVerificationFailureDetector.kt
@@ -19,7 +19,6 @@
 package androidx.build.lint
 
 import com.android.SdkConstants.ATTR_VALUE
-import com.android.tools.lint.checks.ApiDetector.Companion.REQUIRES_API_ANNOTATION
 import com.android.tools.lint.checks.ApiLookup
 import com.android.tools.lint.checks.ApiLookup.equivalentName
 import com.android.tools.lint.checks.DesugaredMethodLookup
@@ -39,6 +38,8 @@
 import com.android.tools.lint.detector.api.Severity
 import com.android.tools.lint.detector.api.SourceCodeScanner
 import com.android.tools.lint.detector.api.UastLintUtils.Companion.getLongAttribute
+import com.android.tools.lint.detector.api.VersionChecks
+import com.android.tools.lint.detector.api.VersionChecks.Companion.REQUIRES_API_ANNOTATION
 import com.android.tools.lint.detector.api.getInternalMethodName
 import com.android.tools.lint.detector.api.isKotlin
 import com.intellij.psi.PsiAnonymousClass
@@ -815,7 +816,7 @@
                                         return api
                                     }
                                 } else {
-                                    return codeNameToApi(name)
+                                    return VersionChecks.codeNameToApi(name)
                                 }
                             }
                         }
diff --git a/mediarouter/mediarouter/src/main/res/values-ar/strings.xml b/mediarouter/mediarouter/src/main/res/values-ar/strings.xml
index a3e0115..49d12dc 100644
--- a/mediarouter/mediarouter/src/main/res/values-ar/strings.xml
+++ b/mediarouter/mediarouter/src/main/res/values-ar/strings.xml
@@ -22,10 +22,10 @@
     <string name="mr_cast_button_disconnected" msgid="8071109333469380363">"إرسال غير متصل"</string>
     <string name="mr_cast_button_connecting" msgid="6629927151350192407">"إرسال جارٍ الاتصال"</string>
     <string name="mr_cast_button_connected" msgid="6073720094880410356">"إرسال متصل"</string>
-    <string name="mr_chooser_title" msgid="1419936397646839840">"إرسال إلى"</string>
+    <string name="mr_chooser_title" msgid="1419936397646839840">"البث إلى"</string>
     <string name="mr_chooser_searching" msgid="6114250663023140921">"جارٍ البحث عن أجهزة"</string>
     <string name="mr_controller_disconnect" msgid="7812275474138309497">"قطع اتصال"</string>
-    <string name="mr_controller_stop_casting" msgid="804210341192624074">"إيقاف الإرسال"</string>
+    <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>
diff --git a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkTest.kt b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkTest.kt
index 79c6eca..3d7b1fd 100644
--- a/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkTest.kt
+++ b/navigation/navigation-common/src/androidTest/java/androidx/navigation/NavDeepLinkTest.kt
@@ -358,6 +358,24 @@
             .isFalse()
     }
 
+    @Test
+    fun deepLinkEmptyStringQueryParamArg() {
+        val deepLinkArgument = "$DEEP_LINK_EXACT_HTTPS/users?myArg={arg}"
+        val deepLink = NavDeepLink(deepLinkArgument)
+
+        val arg = ""
+        val matchArgs = deepLink.getMatchingArguments(
+            Uri.parse(deepLinkArgument.replace("{arg}", arg)),
+            mapOf("arg" to stringArgument())
+        )
+        assertWithMessage("Args should not be null")
+            .that(matchArgs)
+            .isNotNull()
+        assertWithMessage("Args should contain the id")
+            .that(matchArgs?.containsKey("arg"))
+            .isTrue()
+    }
+
     // Ensure case when matching the exact argument query (i.e. param names in braces) is handled
     @Test
     fun deepLinkQueryParamNullableArgumentMatchParamsInBraces() {
@@ -729,13 +747,9 @@
         val deepLink = NavDeepLink(deepLinkArgument)
 
         val first = "Jane"
-        val last = "Doe"
         val matchArgs = deepLink.getMatchingArguments(
             Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?name=Jane_"),
-            mapOf(
-                "first" to stringArgument(),
-                "last" to stringArgument(last)
-            )
+            mapOf("first" to stringArgument(), "last" to stringArgument())
         )
         assertWithMessage("Args should not be null")
             .that(matchArgs)
@@ -743,9 +757,31 @@
         assertWithMessage("Args should contain the first name")
             .that(matchArgs?.getString("first"))
             .isEqualTo(first)
-        assertWithMessage("Args should not contain the last name")
-            .that(matchArgs?.containsKey("last"))
-            .isFalse()
+        assertWithMessage("Args should contain the empty last name")
+            .that(matchArgs?.getString("last"))
+            .isEqualTo("")
+    }
+
+    @Test
+    fun deepLinkQueryParamNoDefaultArgumentMatchMultiArgsNoParam() {
+        val deepLinkArgument = "$DEEP_LINK_EXACT_HTTPS/users?name={first}_{last}"
+        val deepLink = NavDeepLink(deepLinkArgument)
+
+        val first = ""
+        val last = ""
+        val matchArgs = deepLink.getMatchingArguments(
+            Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?name=_"),
+            mapOf("first" to stringArgument(), "last" to stringArgument())
+        )
+        assertWithMessage("Args should not be null")
+            .that(matchArgs)
+            .isNotNull()
+        assertWithMessage("Args should contain the empty first name")
+            .that(matchArgs?.getString("first"))
+            .isEqualTo(first)
+        assertWithMessage("Args should contain the empty last name")
+            .that(matchArgs?.getString("last"))
+            .isEqualTo(last)
     }
 
     @Test
@@ -947,17 +983,16 @@
         val deepLinkArgument = "$DEEP_LINK_EXACT_HTTPS/users?path=go/to/{path}"
         val deepLink = NavDeepLink(deepLinkArgument)
 
-        val path = "directions"
         val matchArgs = deepLink.getMatchingArguments(
             Uri.parse("$DEEP_LINK_EXACT_HTTPS/users?path=go/to/"),
-            mapOf("path" to stringArgument(path))
+            mapOf("path" to stringArgument())
         )
         assertWithMessage("Args should not be null")
             .that(matchArgs)
             .isNotNull()
         assertWithMessage("Args should not contain the path")
-            .that(matchArgs?.containsKey("path"))
-            .isFalse()
+            .that(matchArgs?.getString("path"))
+            .isEqualTo("")
     }
 
     @Test
diff --git a/navigation/navigation-common/src/main/java/androidx/navigation/NavDeepLink.kt b/navigation/navigation-common/src/main/java/androidx/navigation/NavDeepLink.kt
index f9963da..bfc5033 100644
--- a/navigation/navigation-common/src/main/java/androidx/navigation/NavDeepLink.kt
+++ b/navigation/navigation-common/src/main/java/androidx/navigation/NavDeepLink.kt
@@ -170,7 +170,14 @@
             val argumentName = this.arguments[index]
             val value = Uri.decode(matcher.group(index + 1))
             val argument = arguments[argumentName]
-            if (parseArgument(bundle, argumentName, value, argument)) {
+            try {
+                if (parseArgument(bundle, argumentName, value, argument)) {
+                    return null
+                }
+            } catch (e: IllegalArgumentException) {
+                // Failed to parse means this isn't a valid deep link
+                // for the given URI - i.e., the URI contains a non-integer
+                // value for an integer argument
                 return null
             }
         }
@@ -188,22 +195,30 @@
                         return null
                     }
                 }
-                // Params could have multiple arguments, we need to handle them all
-                for (index in 0 until storedParam!!.size()) {
-                    var value: String? = null
-                    if (argMatcher != null) {
-                        value = argMatcher.group(index + 1)
+                val queryParamBundle = Bundle()
+                try {
+                    // Params could have multiple arguments, we need to handle them all
+                    for (index in 0 until storedParam!!.size()) {
+                        var value: String? = null
+                        if (argMatcher != null) {
+                            value = argMatcher.group(index + 1) ?: ""
+                        }
+                        val argName = storedParam.getArgumentName(index)
+                        val argument = arguments[argName]
+                        // Passing in a value the exact same as the placeholder will be treated the
+                        // as if no value was passed, being replaced if it is optional or throwing an
+                        // error if it is required.
+                        if (value != null && value != "{$argName}" &&
+                            parseArgument(queryParamBundle, argName, value, argument)
+                        ) {
+                            return null
+                        }
                     }
-                    val argName = storedParam.getArgumentName(index)
-                    val argument = arguments[argName]
-                    // Passing in a value the exact same as the placeholder will be treated the
-                    // as if no value was passed, being replaced if it is optional or throwing an
-                    // error if it is required.
-                    if (value != null && value != "{$argName}" &&
-                        parseArgument(bundle, argName, value, argument)
-                    ) {
-                        return null
-                    }
+                    bundle.putAll(queryParamBundle)
+                } catch (e: IllegalArgumentException) {
+                    // Failed to parse means that at least one of the arguments that were supposed
+                    // to fill in the query parameter was not valid and therefore, we will exclude
+                    // that particular parameter from the argument bundle.
                 }
             }
         }
@@ -226,14 +241,7 @@
     ): Boolean {
         if (argument != null) {
             val type = argument.type
-            try {
-                type.parseAndPut(bundle, name, value)
-            } catch (e: IllegalArgumentException) {
-                // Failed to parse means this isn't a valid deep link
-                // for the given URI - i.e., the URI contains a non-integer
-                // value for an integer argument
-                return true
-            }
+            type.parseAndPut(bundle, name, value)
         } else {
             bundle.putString(name, value)
         }
diff --git a/room/room-runtime-lint/src/main/java/androidx/room/lint/CursorKotlinUseIssueDetector.kt b/room/room-runtime-lint/src/main/java/androidx/room/lint/CursorKotlinUseIssueDetector.kt
index 97e69b0..4ddc81c 100644
--- a/room/room-runtime-lint/src/main/java/androidx/room/lint/CursorKotlinUseIssueDetector.kt
+++ b/room/room-runtime-lint/src/main/java/androidx/room/lint/CursorKotlinUseIssueDetector.kt
@@ -27,6 +27,7 @@
 import com.android.tools.lint.detector.api.Scope
 import com.android.tools.lint.detector.api.Severity
 import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.android.tools.lint.detector.api.VersionChecks
 import com.android.tools.lint.detector.api.minSdkLessThan
 import com.intellij.psi.PsiMethod
 import org.jetbrains.uast.UCallExpression
@@ -63,8 +64,8 @@
         }
         // If the call is within an SDK_INT check, then its OK
         if (
-            isWithinVersionCheckConditional(context, node, 16) ||
-            isPrecededByVersionCheckExit(context, node, 16)
+            VersionChecks.isWithinVersionCheckConditional(context, node, 16) ||
+            VersionChecks.isPrecededByVersionCheckExit(context, node, 16)
         ) {
             return
         }
diff --git a/slice/slice-view/src/main/res/values-it/strings.xml b/slice/slice-view/src/main/res/values-it/strings.xml
index 62c8052..9087d7a 100644
--- a/slice/slice-view/src/main/res/values-it/strings.xml
+++ b/slice/slice-view/src/main/res/values-it/strings.xml
@@ -22,16 +22,16 @@
     <string name="abc_slice_show_more" msgid="1112789899890391107">"Mostra altro"</string>
     <string name="abc_slice_updated" msgid="7932359091871934205">"Ultimo aggiornamento: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <plurals name="abc_slice_duration_min" formatted="false" msgid="7664017844210142826">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> min fa</item>
       <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> min fa</item>
+      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> min fa</item>
     </plurals>
     <plurals name="abc_slice_duration_years" formatted="false" msgid="2628491538787454021">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> anno fa</item>
       <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> anni fa</item>
+      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> anno fa</item>
     </plurals>
     <plurals name="abc_slice_duration_days" formatted="false" msgid="8356547162075064530">
-      <item quantity="one"><xliff:g id="ID_2">%d</xliff:g> giorno fa</item>
       <item quantity="other"><xliff:g id="ID_2">%d</xliff:g> giorni fa</item>
+      <item quantity="one"><xliff:g id="ID_1">%d</xliff:g> giorno fa</item>
     </plurals>
     <string name="abc_slice_error" msgid="1794214973158263497">"Impossibile collegarsi"</string>
 </resources>
diff --git a/slice/slice-view/src/main/res/values-pt-rPT/strings.xml b/slice/slice-view/src/main/res/values-pt-rPT/strings.xml
index 08c5c19..34a67ff 100644
--- a/slice/slice-view/src/main/res/values-pt-rPT/strings.xml
+++ b/slice/slice-view/src/main/res/values-pt-rPT/strings.xml
@@ -22,16 +22,16 @@
     <string name="abc_slice_show_more" msgid="1112789899890391107">"Mostrar mais"</string>
     <string name="abc_slice_updated" msgid="7932359091871934205">"Atualização: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <plurals name="abc_slice_duration_min" formatted="false" msgid="7664017844210142826">
-      <item quantity="one">Há <xliff:g id="ID_1">%d</xliff:g> min</item>
       <item quantity="other">Há <xliff:g id="ID_2">%d</xliff:g> min</item>
+      <item quantity="one">Há <xliff:g id="ID_1">%d</xliff:g> min</item>
     </plurals>
     <plurals name="abc_slice_duration_years" formatted="false" msgid="2628491538787454021">
-      <item quantity="one">Há <xliff:g id="ID_1">%d</xliff:g> ano</item>
       <item quantity="other">Há <xliff:g id="ID_2">%d</xliff:g> anos</item>
+      <item quantity="one">Há <xliff:g id="ID_1">%d</xliff:g> ano</item>
     </plurals>
     <plurals name="abc_slice_duration_days" formatted="false" msgid="8356547162075064530">
-      <item quantity="one">Há <xliff:g id="ID_1">%d</xliff:g> dia</item>
       <item quantity="other">Há <xliff:g id="ID_2">%d</xliff:g> dias</item>
+      <item quantity="one">Há <xliff:g id="ID_1">%d</xliff:g> dia</item>
     </plurals>
     <string name="abc_slice_error" msgid="1794214973158263497">"Não foi possível ligar"</string>
 </resources>
diff --git a/work/work-runtime/src/main/java/androidx/work/impl/utils/SerialExecutor.java b/work/work-runtime/src/main/java/androidx/work/impl/utils/SerialExecutor.java
index 982c865..c40ab09 100644
--- a/work/work-runtime/src/main/java/androidx/work/impl/utils/SerialExecutor.java
+++ b/work/work-runtime/src/main/java/androidx/work/impl/utils/SerialExecutor.java
@@ -16,6 +16,7 @@
 
 package androidx.work.impl.utils;
 
+import androidx.annotation.GuardedBy;
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
@@ -29,8 +30,11 @@
 public class SerialExecutor implements Executor {
     private final ArrayDeque<Task> mTasks;
     private final Executor mExecutor;
-    private final Object mLock;
-    private volatile Runnable mActive;
+
+    @GuardedBy("mLock")
+    private Runnable mActive;
+
+    final Object mLock;
 
     public SerialExecutor(@NonNull Executor executor) {
         mExecutor = executor;
@@ -49,11 +53,10 @@
     }
 
     // Synthetic access
+    @GuardedBy("mLock")
     void scheduleNext() {
-        synchronized (mLock) {
-            if ((mActive = mTasks.poll()) != null) {
-                mExecutor.execute(mActive);
-            }
+        if ((mActive = mTasks.poll()) != null) {
+            mExecutor.execute(mActive);
         }
     }
 
@@ -90,7 +93,9 @@
             try {
                 mRunnable.run();
             } finally {
-                mSerialExecutor.scheduleNext();
+                synchronized (mSerialExecutor.mLock) {
+                    mSerialExecutor.scheduleNext();
+                }
             }
         }
     }