Merge "Mark CameraGraphSimulatorTest$simulatorCanIssueMultipleFrames flaky" into androidx-main
diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml
new file mode 100644
index 0000000..4eebecbb
--- /dev/null
+++ b/.github/workflows/integration_tests.yml
@@ -0,0 +1,32 @@
+name: Run Integration Tests
+on:
+  workflow_run:
+    workflows: ["AndroidX Presubmits"]
+    types: [completed]
+
+jobs:
+  run_integration_tests:
+    runs-on: ubuntu-latest
+    if: ${{ github.event.workflow_run.conclusion == 'success' }}
+    name: Run integration tests on FTL
+    steps:
+      - name: Set up JDK 11
+        uses: actions/setup-java@v2
+        with:
+          java-version: '11'
+          distribution: 'adopt'
+      - name: "set output directory"
+        run: echo "::set-output name=output-dir::$(readlink -f .)/outputs"
+        id: dirs
+      - id: run_tests
+        uses: androidX/androidx-ci-action@latest
+        with:
+          run-id: ${{ github.event.workflow_run.id }}
+          gcp-token: ${{ secrets.GCP_SA_KEY }}
+          github-token: ${{ secrets.GITHUB_TOKEN }}
+          output-folder: ${{ steps.dirs.outputs.output-dir }}
+      - uses: actions/upload-artifact@v2
+        if: always()
+        with:
+          name: outputs
+          path: ${{ steps.dirs.outputs.output-dir }}
diff --git a/OWNERS b/OWNERS
index 7c95cab..478bf24 100644
--- a/OWNERS
+++ b/OWNERS
@@ -11,12 +11,15 @@
 lpf@google.com
 mount@google.com
 nickanthony@google.com
+owengray@google.com
 pavlis@google.com
 romainguy@android.com
+saff@google.com
 sergeyv@google.com
 siyamed@google.com
 sjgilbert@google.com
 sumir@google.com
+tiem@google.com
 yboyar@google.com
 
 per-file *settings.gradle = set noparent
diff --git a/activity/activity-lint/build.gradle b/activity/activity-lint/build.gradle
index 91f9d3c..7e37c76 100644
--- a/activity/activity-lint/build.gradle
+++ b/activity/activity-lint/build.gradle
@@ -25,13 +25,7 @@
 }
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly(LINT_API_LATEST)
-    } else {
-        compileOnly(LINT_API_MIN)
-    }
+    compileOnly(LINT_API_MIN)
     compileOnly(KOTLIN_STDLIB)
 
     testImplementation(KOTLIN_STDLIB)
diff --git a/annotation/annotation-experimental-lint/build.gradle b/annotation/annotation-experimental-lint/build.gradle
index 15ad4d6..17d9220 100644
--- a/annotation/annotation-experimental-lint/build.gradle
+++ b/annotation/annotation-experimental-lint/build.gradle
@@ -34,13 +34,7 @@
 }
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly(LINT_API_LATEST)
-    } else {
-        compileOnly(LINT_API_MIN)
-    }
+    compileOnly(LINT_API_MIN)
     compileOnly(KOTLIN_STDLIB)
 
     testImplementation(KOTLIN_STDLIB)
diff --git a/buildSrc/src/main/kotlin/androidx/build/AndroidXUiPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/AndroidXUiPlugin.kt
index bb847e0..2246471 100644
--- a/buildSrc/src/main/kotlin/androidx/build/AndroidXUiPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/AndroidXUiPlugin.kt
@@ -25,6 +25,7 @@
 import org.gradle.api.Project
 import org.gradle.api.artifacts.type.ArtifactTypeDefinition
 import org.gradle.api.attributes.Attribute
+import org.gradle.api.file.DuplicatesStrategy
 import org.gradle.api.tasks.ClasspathNormalizer
 import org.gradle.kotlin.dsl.apply
 import org.gradle.kotlin.dsl.findByType
@@ -282,6 +283,14 @@
                     "multiplatformExtension is null (multiplatform plugin not enabled?)"
             }
 
+            /**
+             * Temporary workaround for https://youtrack.jetbrains.com/issue/KT-46096
+             * Should be removed once the build switches to Kotlin 1.5
+             */
+            tasks.withType(org.gradle.jvm.tasks.Jar::class.java).configureEach { jar ->
+                jar.duplicatesStrategy = DuplicatesStrategy.INCLUDE
+            }
+
             /*
             The following configures source sets - note:
 
@@ -313,6 +322,23 @@
                     tasks.named("desktopTestClasses").also(::addToBuildOnServer)
                 }
             }
+
+            // workaround after migration to AGP 7.0.0-alpha15
+            // https://youtrack.jetbrains.com/issue/KT-43944#focus=Comments-27-4612683.0-0
+            // TODO(demin): remove after migration to Kotlin 1.5.0:
+            //  https://android-review.googlesource.com/c/platform/frameworks/support/+/1651538
+            fun createNonExistentConfiguration(name: String) {
+                if (project.configurations.findByName(name) == null) {
+                    project.configurations.create(name)
+                }
+            }
+
+            createNonExistentConfiguration("androidTestApi")
+            createNonExistentConfiguration("androidTestDebugApi")
+            createNonExistentConfiguration("androidTestReleaseApi")
+            createNonExistentConfiguration("testApi")
+            createNonExistentConfiguration("testDebugApi")
+            createNonExistentConfiguration("testReleaseApi")
         }
     }
 }
diff --git a/buildSrc/src/main/kotlin/androidx/build/ComposeJvmTarget.kt b/buildSrc/src/main/kotlin/androidx/build/ComposeJvmTarget.kt
new file mode 100644
index 0000000..d3f42f8
--- /dev/null
+++ b/buildSrc/src/main/kotlin/androidx/build/ComposeJvmTarget.kt
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.build
+
+import org.gradle.api.Project
+import org.gradle.api.file.ConfigurableFileCollection
+import org.gradle.api.plugins.JavaPlugin
+import org.gradle.api.plugins.JavaPluginConvention
+import org.gradle.api.tasks.SourceSet
+import org.gradle.api.tasks.compile.AbstractCompile
+import org.gradle.api.tasks.testing.Test
+import org.gradle.jvm.tasks.Jar
+import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
+import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmCompilation
+import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
+import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
+import java.lang.reflect.Modifier
+import java.util.concurrent.Callable
+
+object ComposeJvmTarget {
+    /**
+     * Temporary workaround for fixing Compose Desktop build with Kotlin 1.4 and Gradle 7
+     * Intended to be used only in :compose:desktop:desktop and only until Compose project
+     * switches to Kotlin 1.5.0
+     *
+     * This is basically a copy
+     * org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget.withJava from Kotlin 1.5.0,
+     * which fixes java.lang.NoSuchMethodError, thrown by Gradle 7 with Kotlin 1.4
+     * (https://youtrack.jetbrains.com/issue/KTIJ-10018).
+     *
+     * There are a few changes from the original:
+     * some internal methods are copied or called using Java Reflection
+     */
+    @JvmStatic
+    fun withJava(target: KotlinJvmTarget) {
+        val project = target.project
+
+        project.plugins.apply(JavaPlugin::class.java)
+        val javaPluginConvention = project.convention.getPlugin(JavaPluginConvention::class.java)
+        setUpJavaSourceSets(target)
+
+        javaPluginConvention.sourceSets.all { javaSourceSet ->
+            val compilation = target.compilations.getByName(javaSourceSet.name)
+            val compileJavaTask = project.tasks.withType(AbstractCompile::class.java)
+                .named(javaSourceSet.compileJavaTaskName)
+
+            setupJavaSourceSetSourcesAndResources(project, javaSourceSet, compilation)
+
+            val javaClasses = project.files(compileJavaTask.map { it.destinationDir })
+
+            compilation.output.classesDirs.from(javaClasses)
+
+            (javaSourceSet.output.classesDirs as? ConfigurableFileCollection)?.from(
+                compilation.output.classesDirs.minus(javaClasses)
+            )
+
+            javaSourceSet.output.setResourcesDir(
+                Callable { compilation.output.resourcesDirProvider }
+            )
+
+            setupDependenciesCrossInclusionForJava(project, compilation, javaSourceSet)
+        }
+
+        // Eliminate the Java output configurations from dependency resolution
+        // to avoid ambiguity between them and the equivalent configurations
+        // created for the target:
+        listOf(
+            JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME,
+            JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME
+        ).forEach { outputConfigurationName ->
+            project.configurations.findByName(outputConfigurationName)?.isCanBeConsumed = false
+        }
+
+        disableJavaPluginTasks(project, javaPluginConvention, target)
+    }
+
+    private fun setupDependenciesCrossInclusionForJava(
+        project: Project,
+        compilation: KotlinJvmCompilation,
+        javaSourceSet: SourceSet
+    ) {
+        // Make sure Kotlin compilation dependencies appear in the Java source set classpaths:
+
+        listOfNotNull(
+            compilation.apiConfigurationName,
+            compilation.implementationConfigurationName,
+            compilation.compileOnlyConfigurationName
+        ).forEach { configurationName ->
+            project.addExtendsFromRelation(
+                javaSourceSet.compileClasspathConfigurationName,
+                configurationName
+            )
+        }
+
+        listOfNotNull(
+            compilation.apiConfigurationName,
+            compilation.implementationConfigurationName,
+            compilation.runtimeOnlyConfigurationName
+        ).forEach { configurationName ->
+            project.addExtendsFromRelation(
+                javaSourceSet.runtimeClasspathConfigurationName,
+                configurationName
+            )
+        }
+
+        // Add the Java source set dependencies to the Kotlin compilation
+        // compile & runtime configurations:
+        listOfNotNull(
+            javaSourceSet.compileOnlyConfigurationName,
+            javaSourceSet.apiConfigurationName
+                .takeIf { project.configurations.findByName(it) != null },
+            javaSourceSet.implementationConfigurationName
+        ).forEach { configurationName ->
+            project.addExtendsFromRelation(
+                compilation.compileDependencyConfigurationName,
+                configurationName
+            )
+        }
+
+        listOfNotNull(
+            javaSourceSet.runtimeOnlyConfigurationName,
+            javaSourceSet.apiConfigurationName
+                .takeIf { project.configurations.findByName(it) != null },
+            javaSourceSet.implementationConfigurationName
+        ).forEach { configurationName ->
+            project.addExtendsFromRelation(
+                compilation.runtimeDependencyConfigurationName,
+                configurationName
+            )
+        }
+    }
+
+    /**
+     * Calls AbstractKotlinPlugin.setUpJavaSourceSets(target, false) using reflection
+     */
+    private fun setUpJavaSourceSets(target: KotlinJvmTarget) {
+        val abstractKotlinPluginClass = Class.forName(ABSTRACT_KOTLIN_PLUGIN)
+            ?: error("Could not find '$ABSTRACT_KOTLIN_PLUGIN' class")
+        val companionField = abstractKotlinPluginClass.fields
+            .find { it.name == COMPANION && Modifier.isStatic(it.modifiers) }
+            ?: error("Could not find '$COMPANION' field")
+        val companionInstance = companionField.get(abstractKotlinPluginClass)!!
+        val companionClass = companionInstance.javaClass
+        val setUpJavaSourceSetsMethod = companionClass.methods.find {
+            it.name == SET_UP_JAVA_SOURCE_SETS && it.parameterCount == 2
+        } ?: error("Could not find '$SET_UP_JAVA_SOURCE_SETS' method")
+        setUpJavaSourceSetsMethod.invoke(companionInstance, target, false)
+    }
+
+    private fun disableJavaPluginTasks(
+        project: Project,
+        javaPluginConvention: JavaPluginConvention,
+        target: KotlinJvmTarget
+    ) {
+        // A 'normal' build should not do redundant job like running the tests twice or building two JARs,
+        // so disable some tasks and just make them depend on the others:
+        val targetJar = project.tasks.withType(Jar::class.java).named(target.artifactsTaskName)
+
+        val mainJarTaskName = javaPluginConvention.sourceSets.getByName("main").jarTaskName
+        project.tasks.withType(Jar::class.java).named(mainJarTaskName) { javaJar ->
+            (javaJar.source as? ConfigurableFileCollection)?.setFrom(targetJar.map { it.source })
+            javaJar.conventionMapping("archiveName") { targetJar.get().archiveFileName.get() }
+            javaJar.dependsOn(targetJar)
+            javaJar.enabled = false
+        }
+
+        project.tasks.withType(Test::class.java).named(JavaPlugin.TEST_TASK_NAME) { javaTestTask ->
+            javaTestTask.dependsOn(project.tasks.named(target.testTaskName))
+            javaTestTask.enabled = false
+        }
+    }
+
+    private fun setupJavaSourceSetSourcesAndResources(
+        project: Project,
+        javaSourceSet: SourceSet,
+        compilation: KotlinJvmCompilation
+    ) {
+        javaSourceSet.java.setSrcDirs(listOf("src/${compilation.defaultSourceSet.name}/java"))
+        compilation.defaultSourceSet.kotlin.srcDirs(javaSourceSet.java.sourceDirectories)
+
+        // To avoid confusion in the sources layout, remove the default Java source directories
+        // (like src/main/java, src/test/java) and instead add sibling directories to those where the Kotlin
+        // sources are placed (i.e. src/jvmMain/java, src/jvmTest/java):
+        javaSourceSet.resources.setSrcDirs(
+            compilation.defaultSourceSet.resources.sourceDirectories
+        )
+        compilation.defaultSourceSet.resources.srcDirs(javaSourceSet.resources.sourceDirectories)
+
+        // Resources processing is done with the Kotlin resource processing task:
+        val processJavaResourcesTask =
+            project.tasks.getByName(javaSourceSet.processResourcesTaskName)
+        processJavaResourcesTask.dependsOn(
+            project.tasks.getByName(compilation.processResourcesTaskName)
+        )
+        processJavaResourcesTask.enabled = false
+    }
+
+    private const val ABSTRACT_KOTLIN_PLUGIN =
+        "org.jetbrains.kotlin.gradle.plugin.AbstractKotlinPlugin"
+    private const val COMPANION = "Companion"
+    private const val SET_UP_JAVA_SOURCE_SETS = "setUpJavaSourceSets${'$'}kotlin_gradle_plugin"
+    private const val ARTIFACT_TASK_NAME = "jar"
+
+    private val KotlinTarget.testTaskName: String
+        get() = lowerCamelCaseName(name, "test")
+
+    private fun lowerCamelCaseName(vararg nameParts: String?): String {
+        val nonEmptyParts = nameParts.mapNotNull { it?.takeIf(String::isNotEmpty) }
+        return nonEmptyParts.drop(1).joinToString(
+            separator = "",
+            prefix = nonEmptyParts.firstOrNull().orEmpty(),
+            transform = String::capitalize
+        )
+    }
+}
\ No newline at end of file
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
index 0e420a88..194f12e 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -151,5 +151,5 @@
     val WINDOW = Version("1.0.0-alpha07")
     val WINDOW_EXTENSIONS = Version("1.0.0-alpha01")
     val WINDOW_SIDECAR = Version("0.1.0-alpha01")
-    val WORK = Version("2.6.0-alpha02")
+    val WORK = Version("2.6.0-beta01")
 }
diff --git a/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt b/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
index fa4179a..22a7375 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
@@ -133,9 +133,6 @@
             }
             isIgnoreWarnings = true
 
-            // Workaround for b/177359055 where 27.2.0-beta04 incorrectly computes severity.
-            isCheckAllWarnings = true
-
             // Write output directly to the console (and nowhere else).
             textReport = true
             htmlReport = false
@@ -166,9 +163,6 @@
             // Disable the TODO check until we have a policy that requires it.
             disable("StopShip")
 
-            // Disable a check that conflicts with our workaround for b/177359055
-            disable("LintBaseline")
-
             // Broken in 7.0.0-alpha15 due to b/180408990
             disable("RestrictedApi")
             disable("VisibleForTests")
diff --git a/buildSrc/src/main/kotlin/androidx/build/checkapi/ApiTasks.kt b/buildSrc/src/main/kotlin/androidx/build/checkapi/ApiTasks.kt
index 1c9ed42..4f521ef 100644
--- a/buildSrc/src/main/kotlin/androidx/build/checkapi/ApiTasks.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/checkapi/ApiTasks.kt
@@ -20,6 +20,7 @@
 import androidx.build.Release
 import androidx.build.RunApiTasks
 import androidx.build.Version
+import androidx.build.doclava.androidJarFile
 import androidx.build.isWriteVersionedApiFilesEnabled
 import androidx.build.java.JavaCompileInputs
 import androidx.build.metalava.MetalavaTasks
@@ -161,7 +162,6 @@
                 } ?: return@afterEvaluate
 
                 javaInputs = JavaCompileInputs.fromLibraryVariant(
-                    config.library,
                     variant,
                     project
                 )
@@ -220,9 +220,9 @@
         }
     )
 
-    return JavaCompileInputs.fromSourcesAndDeps(
+    return JavaCompileInputs(
         sourcePaths = mainSourcePaths + kotlinSourcePaths,
         dependencyClasspath = dependencyClasspath,
-        project = this
+        androidJarFile(project)
     )
 }
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
index 279ab0b..2ef858a 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
@@ -100,7 +100,7 @@
 const val REACTIVE_STREAMS = "org.reactivestreams:reactive-streams:1.0.0"
 const val RX_JAVA = "io.reactivex.rxjava2:rxjava:2.2.9"
 const val RX_JAVA3 = "io.reactivex.rxjava3:rxjava:3.0.0"
-val SKIKO_VERSION = System.getenv("SKIKO_VERSION") ?: "0.2.30"
+val SKIKO_VERSION = System.getenv("SKIKO_VERSION") ?: "0.2.33"
 val SKIKO = "org.jetbrains.skiko:skiko-jvm:$SKIKO_VERSION"
 val SKIKO_LINUX_X64 = "org.jetbrains.skiko:skiko-jvm-runtime-linux-x64:$SKIKO_VERSION"
 val SKIKO_MACOS_X64 = "org.jetbrains.skiko:skiko-jvm-runtime-macos-x64:$SKIKO_VERSION"
diff --git a/buildSrc/src/main/kotlin/androidx/build/java/JavaCompileInputs.kt b/buildSrc/src/main/kotlin/androidx/build/java/JavaCompileInputs.kt
index eab0fbc..98740fa 100644
--- a/buildSrc/src/main/kotlin/androidx/build/java/JavaCompileInputs.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/java/JavaCompileInputs.kt
@@ -18,13 +18,11 @@
 
 import androidx.build.doclava.androidJarFile
 import androidx.build.multiplatformExtension
-import com.android.build.gradle.LibraryExtension
 import com.android.build.gradle.api.BaseVariant
 import com.android.build.gradle.api.SourceKind
 import org.gradle.api.Project
 import org.gradle.api.file.FileCollection
 import org.gradle.api.tasks.SourceSet
-import java.io.File
 
 // JavaCompileInputs contains the information required to compile Java/Kotlin code
 // This can be helpful for creating Metalava and Dokka tasks with the same settings
@@ -36,12 +34,11 @@
     val dependencyClasspath: FileCollection,
 
     // Android's boot classpath.
-    val bootClasspath: Collection<File>
+    val bootClasspath: FileCollection
 ) {
     companion object {
         // Constructs a JavaCompileInputs from a library and its variant
         fun fromLibraryVariant(
-            library: LibraryExtension,
             variant: BaseVariant,
             project: Project
         ): JavaCompileInputs {
@@ -54,7 +51,7 @@
             return JavaCompileInputs(
                 sourceCollection,
                 dependencyClasspath,
-                library.bootClasspath
+                androidJarFile(project)
             )
         }
 
@@ -66,16 +63,7 @@
                 })
             )
             val dependencyClasspath = sourceSet.compileClasspath
-            return fromSourcesAndDeps(sourcePaths, dependencyClasspath, project)
-        }
-
-        fun fromSourcesAndDeps(
-            sourcePaths: FileCollection,
-            dependencyClasspath: FileCollection,
-            project: Project
-        ): JavaCompileInputs {
-            val bootClasspath: Collection<File> = androidJarFile(project).files
-            return JavaCompileInputs(sourcePaths, dependencyClasspath, bootClasspath)
+            return JavaCompileInputs(sourcePaths, dependencyClasspath, androidJarFile(project))
         }
 
         private fun getSourceCollection(variant: BaseVariant, project: Project): FileCollection {
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
index 1224dea..c376ead 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/CheckApiCompatibilityTask.kt
@@ -71,7 +71,7 @@
 
     @TaskAction
     fun exec() {
-        check(bootClasspath.isNotEmpty()) { "Android boot classpath not set." }
+        check(bootClasspath.files.isNotEmpty()) { "Android boot classpath not set." }
 
         val apiLocation = api.get()
         val referenceApiLocation = referenceApi.get()
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiStubClassesTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiStubClassesTask.kt
index c73f597..7980ce6 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiStubClassesTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiStubClassesTask.kt
@@ -37,7 +37,7 @@
         runWithArgs(
             listOf(
                 "--classpath",
-                (bootClasspath + dependencyClasspath.files).joinToString(File.pathSeparator),
+                (bootClasspath.files + dependencyClasspath.files).joinToString(File.pathSeparator),
 
                 "--source-path",
                 sourcePaths.filter { it.exists() }.joinToString(File.pathSeparator),
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiTask.kt
index 3694442..5291379 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/GenerateApiTask.kt
@@ -60,7 +60,7 @@
     abstract val apiLocation: Property<ApiLocation>
 
     @OutputFiles
-    fun getTaskOutputs(): List<File>? {
+    fun getTaskOutputs(): List<File> {
         val prop = apiLocation.get()
         return listOfNotNull(
             prop.publicApiFile,
@@ -72,13 +72,13 @@
 
     @TaskAction
     fun exec() {
-        check(bootClasspath.isNotEmpty()) { "Android boot classpath not set." }
+        check(bootClasspath.files.isNotEmpty()) { "Android boot classpath not set." }
         check(sourcePaths.files.isNotEmpty()) { "Source paths not set." }
 
-        val inputs = JavaCompileInputs.fromSourcesAndDeps(
+        val inputs = JavaCompileInputs(
             sourcePaths,
             dependencyClasspath,
-            project
+            bootClasspath
         )
         generateApi(
             metalavaClasspath,
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
index 078160f..5e2508a 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
@@ -214,7 +214,7 @@
 // Gets arguments for generating the specified api file
 private fun generateApi(
     metalavaClasspath: FileCollection,
-    bootClasspath: Collection<File>,
+    bootClasspath: FileCollection,
     dependencyClasspath: FileCollection,
     sourcePaths: Collection<File>,
     outputLocation: ApiLocation,
@@ -232,7 +232,7 @@
 
 // Generates the specified api file
 fun getGenerateApiArgs(
-    bootClasspath: Collection<File>,
+    bootClasspath: FileCollection,
     dependencyClasspath: FileCollection,
     sourcePaths: Collection<File>,
     outputLocation: ApiLocation?,
@@ -243,7 +243,7 @@
     // generate public API txt
     val args = mutableListOf(
         "--classpath",
-        (bootClasspath + dependencyClasspath.files).joinToString(File.pathSeparator),
+        (bootClasspath.files + dependencyClasspath.files).joinToString(File.pathSeparator),
 
         "--source-path",
         sourcePaths.filter { it.exists() }.joinToString(File.pathSeparator),
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTask.kt
index f4d797b..1e867ee 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTask.kt
@@ -28,7 +28,6 @@
 import org.gradle.api.tasks.PathSensitive
 import org.gradle.api.tasks.PathSensitivity
 import org.gradle.workers.WorkerExecutor
-import java.io.File
 import javax.inject.Inject
 
 /** Base class for invoking Metalava. */
@@ -40,9 +39,9 @@
     @get:Classpath
     abstract val metalavaClasspath: ConfigurableFileCollection
 
-    /** Android's boot classpath. Obtained from [BaseExtension.getBootClasspath]. */
+    /** Android's boot classpath */
     @get:Classpath
-    lateinit var bootClasspath: Collection<File>
+    lateinit var bootClasspath: FileCollection
 
     /** Dependencies of [sourcePaths]. */
     @get:Classpath
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/RegenerateOldApisTask.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/RegenerateOldApisTask.kt
index 57d735e..63bd573 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/RegenerateOldApisTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/RegenerateOldApisTask.kt
@@ -20,6 +20,7 @@
 import androidx.build.checkapi.getApiFileVersion
 import androidx.build.checkapi.getVersionedApiLocation
 import androidx.build.checkapi.isValidArtifactVersion
+import androidx.build.doclava.androidJarFile
 import androidx.build.getCheckoutRoot
 import androidx.build.java.JavaCompileInputs
 import org.gradle.api.DefaultTask
@@ -102,7 +103,7 @@
         val jars = getJars(runnerProject, mavenId)
         val sources = getSources(runnerProject, mavenId + ":sources")
 
-        return JavaCompileInputs.fromSourcesAndDeps(sources, jars, runnerProject)
+        return JavaCompileInputs(sources, jars, androidJarFile(project))
     }
 
     fun getJars(runnerProject: Project, mavenId: String): FileCollection {
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateBaselineTasks.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateBaselineTasks.kt
index 127a325..9fa99e3 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateBaselineTasks.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/UpdateBaselineTasks.kt
@@ -52,7 +52,7 @@
 
     @TaskAction
     fun updateBaseline() {
-        check(bootClasspath.isNotEmpty()) { "Android boot classpath not set." }
+        check(bootClasspath.files.isNotEmpty()) { "Android boot classpath not set." }
         val baselineFile = baselines.get().apiLintFile
         val checkArgs = getGenerateApiArgs(
             bootClasspath, dependencyClasspath,
@@ -106,7 +106,7 @@
 
     @TaskAction
     fun exec() {
-        check(bootClasspath.isNotEmpty()) { "Android boot classpath not set." }
+        check(bootClasspath.files.isNotEmpty()) { "Android boot classpath not set." }
 
         updateBaseline(
             api.get().publicApiFile,
@@ -161,13 +161,13 @@
 }
 
 private fun getCommonBaselineUpdateArgs(
-    bootClasspath: Collection<File>,
+    bootClasspath: FileCollection,
     dependencyClasspath: FileCollection,
     baselineFile: File
 ): MutableList<String> {
     val args = mutableListOf(
         "--classpath",
-        (bootClasspath + dependencyClasspath.files).joinToString(File.pathSeparator)
+        (bootClasspath.files + dependencyClasspath.files).joinToString(File.pathSeparator)
     )
     args += getCommonBaselineUpdateArgs(baselineFile)
     return args
diff --git a/camera/camera-camera2-pipe-integration/build.gradle b/camera/camera-camera2-pipe-integration/build.gradle
index e14d471..d7ee6fb 100644
--- a/camera/camera-camera2-pipe-integration/build.gradle
+++ b/camera/camera-camera2-pipe-integration/build.gradle
@@ -38,7 +38,7 @@
 )
 
 dependencies {
-    implementation("androidx.core:core:1.1.0")
+    implementation("androidx.core:core:1.3.2")
     implementation("androidx.concurrent:concurrent-listenablefuture-callback:1.0.0-beta01")
     bundleInside(project(path: ":camera:camera-camera2-pipe", configuration: "exportRelease"))
 
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/MeteringRepeating.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/MeteringRepeating.kt
index d038a85..2007786 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/MeteringRepeating.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/MeteringRepeating.kt
@@ -72,6 +72,13 @@
         deferrableSurface = null
     }
 
+    /** Sets up the use case's session configuration, mainly its [DeferrableSurface]. */
+    fun setupSession() {
+        // The suggested resolution passed to `updateSuggestedResolution` doesn't matter since
+        // this use case uses the min preview size.
+        updateSuggestedResolution(DEFAULT_PREVIEW_SIZE)
+    }
+
     private fun createPipeline(): SessionConfig.Builder {
         val surfaceTexture = SurfaceTexture(0).apply {
             setDefaultBufferSize(meteringSurfaceSize.width, meteringSurfaceSize.height)
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
index 8a78385..7f210f9 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
@@ -21,6 +21,7 @@
 import androidx.camera.camera2.pipe.integration.config.CameraScope
 import androidx.camera.camera2.pipe.integration.config.UseCaseCameraComponent
 import androidx.camera.camera2.pipe.integration.config.UseCaseCameraConfig
+import androidx.camera.core.ImageCapture
 import androidx.camera.core.UseCase
 import javax.inject.Inject
 
@@ -32,10 +33,12 @@
     private val cameraConfig: CameraConfig,
     private val builder: UseCaseCameraComponent.Builder,
     @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") // Java version required for Dagger
-    private val controls: java.util.Set<UseCaseCameraControl>
+    private val controls: java.util.Set<UseCaseCameraControl>,
+    cameraProperties: CameraProperties,
 ) {
     private val attachedUseCases = mutableListOf<UseCase>()
     private val enabledUseCases = mutableSetOf<UseCase>()
+    private val meteringRepeating by lazy { MeteringRepeating.Builder(cameraProperties).build() }
 
     @Volatile
     private var _activeComponent: UseCaseCameraComponent? = null
@@ -109,8 +112,10 @@
     override fun toString(): String = "UseCaseManager<${cameraConfig.cameraId}>"
 
     private fun invalidate() {
-        camera?.let {
-            it.activeUseCases = enabledUseCases.toSet()
+        when {
+            shouldAddRepeatingUseCase() -> addRepeatingUseCase()
+            shouldRemoveRepeatingUseCase() -> removeRepeatingUseCase()
+            else -> camera?.activeUseCases = enabledUseCases.toSet()
         }
     }
 
@@ -139,4 +144,36 @@
 
         invalidate()
     }
+
+    private fun shouldAddRepeatingUseCase(): Boolean {
+        return enabledUseCases.only { it is ImageCapture }
+    }
+
+    private fun addRepeatingUseCase() {
+        meteringRepeating.setupSession()
+        attach(listOf(meteringRepeating))
+        enable(meteringRepeating)
+    }
+
+    private fun shouldRemoveRepeatingUseCase(): Boolean {
+        val onlyMeteringRepeatingEnabled = enabledUseCases.only { it is MeteringRepeating }
+        val meteringRepeatingAndNonImageCaptureEnabled =
+            enabledUseCases.any { it is MeteringRepeating } &&
+                enabledUseCases.any { it !is MeteringRepeating && it !is ImageCapture }
+        return onlyMeteringRepeatingEnabled || meteringRepeatingAndNonImageCaptureEnabled
+    }
+
+    private fun removeRepeatingUseCase() {
+        disable(meteringRepeating)
+        detach(listOf(meteringRepeating))
+        meteringRepeating.onDetached()
+    }
+
+    /**
+     * Returns true when the collection only has elements (1 or more) that verify the predicate,
+     * false otherwise.
+     */
+    private fun <T> Collection<T>.only(predicate: (T) -> Boolean): Boolean {
+        return isNotEmpty() && all(predicate)
+    }
 }
\ No newline at end of file
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
new file mode 100644
index 0000000..ef234d33
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.pipe.integration.impl
+
+import android.os.Build
+import androidx.camera.camera2.pipe.CameraId
+import androidx.camera.camera2.pipe.integration.adapter.RobolectricCameraPipeTestRunner
+import androidx.camera.camera2.pipe.integration.config.CameraConfig
+import androidx.camera.camera2.pipe.integration.testing.FakeCameraProperties
+import androidx.camera.camera2.pipe.integration.testing.FakeUseCaseCameraComponentBuilder
+import androidx.camera.core.ImageCapture
+import androidx.camera.core.Preview
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.annotation.Config
+import java.util.HashSet
+
+@RunWith(RobolectricCameraPipeTestRunner::class)
+@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+class UseCaseManagerTest {
+
+    @Test
+    fun enabledUseCasesEmpty_whenUseCaseAttachedOnly() {
+        // Arrange
+        val useCaseManager = createUseCaseManager()
+        val useCase = Preview.Builder().build()
+
+        // Act
+        useCaseManager.attach(listOf(useCase))
+
+        // Assert
+        val enabledUseCases = useCaseManager.camera?.activeUseCases
+        assertThat(enabledUseCases).isEmpty()
+    }
+
+    @Test
+    fun enabledUseCasesNotEmpty_whenUseCaseEnabled() {
+        // Arrange
+        val useCaseManager = createUseCaseManager()
+        val useCase = Preview.Builder().build()
+        useCaseManager.attach(listOf(useCase))
+
+        // Act
+        useCaseManager.enable(useCase)
+
+        // Assert
+        val enabledUseCases = useCaseManager.camera?.activeUseCases
+        assertThat(enabledUseCases).containsExactly(useCase)
+    }
+
+    @Test
+    fun meteringRepeatingNotEnabled_whenPreviewEnabled() {
+        // Arrange
+        val useCaseManager = createUseCaseManager()
+        val preview = Preview.Builder().build()
+        val imageCapture = ImageCapture.Builder().build()
+        useCaseManager.attach(listOf(preview, imageCapture))
+
+        // Act
+        useCaseManager.enable(preview)
+        useCaseManager.enable(imageCapture)
+
+        // Assert
+        val enabledUseCases = useCaseManager.camera?.activeUseCases
+        assertThat(enabledUseCases).containsExactly(preview, imageCapture)
+    }
+
+    @Test
+    fun meteringRepeatingEnabled_whenOnlyImageCaptureEnabled() {
+        // Arrange
+        val useCaseManager = createUseCaseManager()
+        val imageCapture = ImageCapture.Builder().build()
+        useCaseManager.attach(listOf(imageCapture))
+
+        // Act
+        useCaseManager.enable(imageCapture)
+
+        // Assert
+        val enabledUseCaseClasses = useCaseManager.camera?.activeUseCases?.map { it::class.java }
+        assertThat(enabledUseCaseClasses).containsExactly(
+            ImageCapture::class.java,
+            MeteringRepeating::class.java
+        )
+    }
+
+    @Test
+    fun meteringRepeatingDisabled_whenPreviewBecomesEnabled() {
+        // Arrange
+        val useCaseManager = createUseCaseManager()
+        val imageCapture = ImageCapture.Builder().build()
+        useCaseManager.attach(listOf(imageCapture))
+        useCaseManager.enable(imageCapture)
+
+        // Act
+        val preview = Preview.Builder().build()
+        useCaseManager.attach(listOf(preview))
+        useCaseManager.enable(preview)
+
+        // Assert
+        val activeUseCases = useCaseManager.camera?.activeUseCases
+        assertThat(activeUseCases).containsExactly(preview, imageCapture)
+    }
+
+    @Test
+    fun meteringRepeatingEnabled_afterAllUseCasesButImageCaptureDisabled() {
+        // Arrange
+        val useCaseManager = createUseCaseManager()
+        val preview = Preview.Builder().build()
+        val imageCapture = ImageCapture.Builder().build()
+        useCaseManager.attach(listOf(preview, imageCapture))
+        useCaseManager.enable(preview)
+        useCaseManager.enable(imageCapture)
+
+        // Act
+        useCaseManager.disable(preview)
+
+        // Assert
+        val enabledUseCaseClasses = useCaseManager.camera?.activeUseCases?.map { it::class.java }
+        assertThat(enabledUseCaseClasses).containsExactly(
+            ImageCapture::class.java,
+            MeteringRepeating::class.java
+        )
+    }
+
+    @Test
+    fun meteringRepeatingDisabled_whenAllUseCasesDisabled() {
+        // Arrange
+        val useCaseManager = createUseCaseManager()
+        val imageCapture = ImageCapture.Builder().build()
+        useCaseManager.attach(listOf(imageCapture))
+        useCaseManager.enable(imageCapture)
+
+        // Act
+        useCaseManager.disable(imageCapture)
+
+        // Assert
+        val enabledUseCases = useCaseManager.camera?.activeUseCases
+        assertThat(enabledUseCases).isEmpty()
+    }
+
+    @Suppress("UNCHECKED_CAST", "PLATFORM_CLASS_MAPPED_TO_KOTLIN")
+    private fun createUseCaseManager() = UseCaseManager(
+        cameraConfig = CameraConfig(CameraId("0")),
+        builder = FakeUseCaseCameraComponentBuilder(),
+        controls = HashSet<UseCaseCameraControl>() as java.util.Set<UseCaseCameraControl>,
+        cameraProperties = FakeCameraProperties()
+    )
+}
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeCameraProperties.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeCameraProperties.kt
new file mode 100644
index 0000000..3a459e0
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeCameraProperties.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.pipe.integration.testing
+
+import androidx.camera.camera2.pipe.CameraId
+import androidx.camera.camera2.pipe.CameraMetadata
+import androidx.camera.camera2.pipe.integration.impl.CameraProperties
+import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
+
+class FakeCameraProperties(
+    override val metadata: CameraMetadata = FakeCameraMetadata(),
+    override val cameraId: CameraId = metadata.camera,
+) : CameraProperties
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeUseCaseCamera.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeUseCaseCamera.kt
new file mode 100644
index 0000000..9b3adc9
--- /dev/null
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/testing/FakeUseCaseCamera.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.camera.camera2.pipe.integration.testing
+
+import android.hardware.camera2.CaptureRequest
+import android.hardware.camera2.params.MeteringRectangle
+import androidx.camera.camera2.pipe.Result3A
+import androidx.camera.camera2.pipe.integration.config.UseCaseCameraComponent
+import androidx.camera.camera2.pipe.integration.config.UseCaseCameraConfig
+import androidx.camera.camera2.pipe.integration.impl.UseCaseCamera
+import androidx.camera.core.UseCase
+import androidx.camera.core.impl.CaptureConfig
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.Deferred
+
+class FakeUseCaseCameraComponentBuilder : UseCaseCameraComponent.Builder {
+    private var config: UseCaseCameraConfig = UseCaseCameraConfig(emptyList())
+
+    override fun config(config: UseCaseCameraConfig): UseCaseCameraComponent.Builder {
+        this.config = config
+        return this
+    }
+
+    override fun build(): UseCaseCameraComponent {
+        return FakeUseCaseCameraComponent(config.provideUseCaseList())
+    }
+}
+
+class FakeUseCaseCameraComponent(useCases: List<UseCase>) : UseCaseCameraComponent {
+    private val fakeUseCaseCamera = FakeUseCaseCamera(useCases.toSet())
+
+    override fun getUseCaseCamera(): UseCaseCamera {
+        return fakeUseCaseCamera
+    }
+}
+
+// TODO: Further implement the methods in this class as needed
+class FakeUseCaseCamera(override var activeUseCases: Set<UseCase> = emptySet()) : UseCaseCamera {
+
+    override fun <T> setParameter(key: CaptureRequest.Key<T>, value: T) {
+    }
+
+    override fun <T> setParameterAsync(key: CaptureRequest.Key<T>, value: T): Deferred<Unit> {
+        return CompletableDeferred<Unit>().apply { complete(Unit) }
+    }
+
+    override fun <T> setParameters(values: Map<CaptureRequest.Key<*>, Any>) {
+    }
+
+    override fun <T> setParametersAsync(values: Map<CaptureRequest.Key<*>, Any>): Deferred<Unit> {
+        return CompletableDeferred<Unit>().apply { complete(Unit) }
+    }
+
+    override suspend fun setTorchAsync(enabled: Boolean): Deferred<Result3A> {
+        return CompletableDeferred<Result3A>().apply {
+            complete(Result3A(status = Result3A.Status.OK))
+        }
+    }
+
+    override suspend fun startFocusAndMeteringAsync(
+        aeRegions: List<MeteringRectangle>,
+        afRegions: List<MeteringRectangle>,
+        awbRegions: List<MeteringRectangle>
+    ): Deferred<Result3A> {
+        return CompletableDeferred<Result3A>().apply {
+            complete(Result3A(status = Result3A.Status.OK))
+        }
+    }
+
+    override fun capture(captureSequence: List<CaptureConfig>) {
+    }
+
+    override fun close() {
+    }
+}
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
index cc4004b..1f2babb 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
@@ -836,6 +836,8 @@
 
     @Test
     fun defaultAspectRatioWillBeSet_whenTargetResolutionIsNotSet() {
+        skipTestOnCameraPipeConfig()
+
         val useCase = ImageCapture.Builder().build()
         camera = CameraUtil.createCameraAndAttachUseCase(context, BACK_SELECTOR, useCase)
 
@@ -845,6 +847,8 @@
 
     @Test
     fun defaultAspectRatioWontBeSet_whenTargetResolutionIsSet() {
+        skipTestOnCameraPipeConfig()
+
         val useCase = ImageCapture.Builder()
             .setTargetResolution(DEFAULT_RESOLUTION)
             .build()
@@ -875,6 +879,8 @@
 
     @Test
     fun targetResolutionIsUpdatedAfterTargetRotationIsUpdated() {
+        skipTestOnCameraPipeConfig()
+
         val imageCapture = ImageCapture.Builder()
             .setTargetResolution(DEFAULT_RESOLUTION)
             .setTargetRotation(Surface.ROTATION_0)
@@ -1039,6 +1045,8 @@
 
     @Test
     fun useCaseConfigCanBeReset_afterUnbind() = runBlocking {
+        skipTestOnCameraPipeConfig()
+
         val useCase = defaultBuilder.build()
         val initialConfig = useCase.currentConfig
         camera = CameraUtil.createCameraAndAttachUseCase(context, BACK_SELECTOR, useCase)
@@ -1053,6 +1061,8 @@
 
     @Test
     fun targetRotationIsRetained_whenUseCaseIsReused() = runBlocking {
+        skipTestOnCameraPipeConfig()
+
         val useCase = defaultBuilder.build()
         camera = CameraUtil.createCameraAndAttachUseCase(context, BACK_SELECTOR, useCase)
 
@@ -1206,6 +1216,8 @@
 
     @Test
     fun returnCorrectTargetRotation_afterUseCaseIsAttached() {
+        skipTestOnCameraPipeConfig()
+
         val imageCapture = ImageCapture.Builder()
             .setTargetRotation(Surface.ROTATION_180)
             .build()
@@ -1221,6 +1233,8 @@
 
     @Test
     fun returnCorrectFlashMode_afterUseCaseIsAttached() {
+        skipTestOnCameraPipeConfig()
+
         val imageCapture = ImageCapture.Builder()
             .setFlashMode(ImageCapture.FLASH_MODE_ON)
             .build()
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/UseCaseCombinationTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/UseCaseCombinationTest.kt
index 9cdff8a..2ff1686 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/UseCaseCombinationTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/UseCaseCombinationTest.kt
@@ -31,6 +31,7 @@
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.withContext
 import org.junit.After
+import org.junit.Assume
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -75,6 +76,8 @@
     /** Test Combination: Preview + ImageCapture */
     @Test
     fun previewCombinesImageCapture() = runBlocking {
+        skipTestOnCameraPipeConfig()
+
         val preview = initPreview()
         val imageCapture = initImageCapture()
 
@@ -105,6 +108,8 @@
     /** Test Combination: Preview + ImageAnalysis + ImageCapture  */
     @Test
     fun previewCombinesImageAnalysisAndImageCapture() = runBlocking {
+        skipTestOnCameraPipeConfig()
+
         val preview = initPreview()
         val imageAnalysis = initImageAnalysis()
         val imageCapture = initImageCapture()
@@ -134,4 +139,13 @@
     private fun initImageCapture(): ImageCapture {
         return ImageCapture.Builder().build()
     }
+
+    // TODO(b/187015621): Remove when DeferrableSurface reference count support is added to
+    //  Camera-pipe-integration
+    private fun skipTestOnCameraPipeConfig() {
+        Assume.assumeFalse(
+            "DeferrableSurface ref count isn't supported on Camera-pipe-integration (b/187015621)",
+            implName == CameraPipeConfig::class.simpleName
+        )
+    }
 }
diff --git a/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java b/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java
index d84d77d..95d5f5b 100644
--- a/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java
+++ b/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java
@@ -119,27 +119,10 @@
         }
     }
 
-    /**
-     * Sets up the appropriate UseCases.
-     */
-    private void bindUseCases() {
-        ImageCapture.Builder imageCaptureBuilder = new ImageCapture.Builder().setTargetName(
-                "ImageCapture");
-        mImageCapture = imageCaptureBuilder.build();
-
-        Preview.Builder previewBuilder = new Preview.Builder().setTargetName("Preview");
-
-        mPreview = previewBuilder.build();
-        mPreview.setSurfaceProvider(mPreviewView.getSurfaceProvider());
-
-        mCamera = mCameraProvider.bindToLifecycle(this, mCurrentCameraSelector,
-                mImageCapture, mPreview);
-    }
-
     void setupButtons() {
         Button btnToggleMode = findViewById(R.id.PhotoToggle);
         Button btnSwitchCamera = findViewById(R.id.Switch);
-        btnToggleMode.setOnClickListener(view -> enableNextExtension());
+        btnToggleMode.setOnClickListener(view -> bindUseCasesWithNextExtension());
         btnSwitchCamera.setOnClickListener(view -> switchCameras());
     }
 
@@ -147,8 +130,7 @@
         mCameraProvider.unbindAll();
         mCurrentCameraSelector = (mCurrentCameraSelector == CameraSelector.DEFAULT_BACK_CAMERA)
                 ? CameraSelector.DEFAULT_FRONT_CAMERA : CameraSelector.DEFAULT_BACK_CAMERA;
-        bindUseCases();
-        enableExtension(mCurrentImageCaptureType);
+        bindUseCasesWithExtension(mCurrentImageCaptureType);
     }
 
     @Extensions.ExtensionMode
@@ -172,30 +154,37 @@
         }
     }
 
-    void enableNextExtension() {
+    void bindUseCasesWithNextExtension() {
         do {
             mCurrentImageCaptureType = mCurrentImageCaptureType.getNextType();
-        } while (!enableExtension(mCurrentImageCaptureType));
+        } while (!bindUseCasesWithExtension(mCurrentImageCaptureType));
     }
 
     // TODO(b/162875208) Suppress until new extensions API made public
     @SuppressLint("RestrictedAPI")
-    boolean enableExtension(ImageCaptureType imageCaptureType) {
+    boolean bindUseCasesWithExtension(ImageCaptureType imageCaptureType) {
         // Check that extension can be enabled and if so enable it
         @Extensions.ExtensionMode
         int extensionMode = extensionModeFrom(imageCaptureType);
-
         if (!mExtensions.isExtensionAvailable(mCameraProvider, mCurrentCameraSelector,
                 extensionMode)) {
             return false;
         }
 
+        ImageCapture.Builder imageCaptureBuilder = new ImageCapture.Builder().setTargetName(
+                "ImageCapture");
+        mImageCapture = imageCaptureBuilder.build();
+
+        Preview.Builder previewBuilder = new Preview.Builder().setTargetName("Preview");
+
+        mPreview = previewBuilder.build();
+        mPreview.setSurfaceProvider(mPreviewView.getSurfaceProvider());
+
         CameraSelector cameraSelector = mExtensions.getExtensionCameraSelector(
                 mCurrentCameraSelector, extensionMode);
 
         mCameraProvider.unbindAll();
-
-        mCameraProvider.bindToLifecycle(this, cameraSelector, mImageCapture, mPreview);
+        mCamera = mCameraProvider.bindToLifecycle(this, cameraSelector, mImageCapture, mPreview);
 
         // Update the UI and save location for ImageCapture
         Button toggleButton = findViewById(R.id.PhotoToggle);
@@ -269,13 +258,6 @@
         return true;
     }
 
-    /** Creates all the use cases. */
-    void createUseCases() {
-        ExtensionsManager.setExtensionsErrorListener((errorCode) ->
-                Log.d(TAG, "Extensions error in error code: " + errorCode));
-        bindUseCases();
-    }
-
     @SuppressWarnings("UnstableApiUsage")
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -339,8 +321,9 @@
                             case NONE:
                                 mExtensions = ExtensionsManager.getExtensions(
                                         getApplicationContext());
-                                createUseCases();
-                                enableNextExtension();
+                                ExtensionsManager.setExtensionsErrorListener((errorCode) ->
+                                        Log.d(TAG, "Extensions error in error code: " + errorCode));
+                                bindUseCasesWithNextExtension();
                                 setupButtons();
                                 break;
                             case LIBRARY_UNAVAILABLE_ERROR_LOADING:
@@ -407,9 +390,8 @@
                                 motionEvent.getX(), motionEvent.getY());
 
                 mCamera.getCameraControl().startFocusAndMetering(
-                        new FocusMeteringAction.Builder(point).build())
-                        .addListener(() -> {},
-                                ContextCompat.getMainExecutor(CameraExtensionsActivity.this));
+                        new FocusMeteringAction.Builder(point).build()).addListener(() -> {},
+                        ContextCompat.getMainExecutor(CameraExtensionsActivity.this));
             }
             return true;
         });
diff --git a/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/app/MainActivity.java b/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/app/MainActivity.java
index 9acd598..50f48ba2 100644
--- a/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/app/MainActivity.java
+++ b/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/app/MainActivity.java
@@ -30,7 +30,7 @@
 
 import androidx.activity.ComponentActivity;
 import androidx.annotation.Nullable;
-import androidx.car.app.connection.ConnectionToCar;
+import androidx.car.app.connection.CarConnection;
 import androidx.car.app.sample.navigation.common.R;
 import androidx.car.app.sample.navigation.common.nav.NavigationService;
 
@@ -82,7 +82,7 @@
         Button stopNavButton = findViewById(R.id.stop_nav);
         stopNavButton.setOnClickListener(this::stopNavigation);
 
-        new ConnectionToCar(this).getType().observe(this,
+        new CarConnection(this).getType().observe(this,
                 this::onConnectionStateUpdate);
     }
 
@@ -112,7 +112,7 @@
     }
 
     private void onConnectionStateUpdate(Integer connectionState) {
-        String message = connectionState > ConnectionToCar.NOT_CONNECTED
+        String message = connectionState > CarConnection.CONNECTION_TYPE_NOT_CONNECTED
                 ? "Connected to a car head unit"
                 : "Not Connected to a car head unit";
         Toast.makeText(this, message, Toast.LENGTH_LONG).show();
diff --git a/car/app/app-samples/showcase/common/src/main/AndroidManifest.xml b/car/app/app-samples/showcase/common/src/main/AndroidManifest.xml
index 4e1a805..330eeab 100644
--- a/car/app/app-samples/showcase/common/src/main/AndroidManifest.xml
+++ b/car/app/app-samples/showcase/common/src/main/AndroidManifest.xml
@@ -14,4 +14,10 @@
  See the License for the specific language governing permissions and
  limitations under the License.
 -->
-<manifest package="androidx.car.app.sample.showcase.common" />
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="androidx.car.app.sample.showcase.common">
+    <application>
+        <activity android:name=".templates.SignInWithGoogleActivity" />
+    </application>
+</manifest>
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInTemplateDemoScreen.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInTemplateDemoScreen.java
index 3f0c42f..365b683 100644
--- a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInTemplateDemoScreen.java
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInTemplateDemoScreen.java
@@ -17,7 +17,6 @@
 package androidx.car.app.sample.showcase.common.templates;
 
 import static androidx.car.app.CarToast.LENGTH_LONG;
-import static androidx.car.app.CarToast.LENGTH_SHORT;
 
 import android.graphics.Color;
 
@@ -62,7 +61,7 @@
     private String mErrorMessage;
 
     private final CharSequence mAdditionalText = Utils.clickable("Please review our terms of "
-            + "service", 18, 16,
+                    + "service", 18, 16,
             () -> getScreenManager().push(new LongMessageTemplateDemoScreen(getCarContext())));
 
     private final Action mProviderSignInAction = new Action.Builder()
@@ -227,12 +226,7 @@
                                 .setTint(noTint)
                                 .build())
                         .setOnClickListener(ParkedOnlyOnClickListener.create(
-                                () -> CarToast.makeText(
-                                        getCarContext(),
-                                        "Sign-in with Google starts here",
-                                        LENGTH_SHORT)
-                                        .show()))
-                        .build()
+                                this::performSignInWithGoogleFlow)).build()
         ).build();
 
         return new SignInTemplate.Builder(providerSignInMethod)
@@ -243,6 +237,31 @@
                 .build();
     }
 
+    private void performSignInWithGoogleFlow() {
+        // This is here for demonstration purposes, if the APK is not signed with a signature
+        // that has been registered for sign in with Google flow, the sign in will fail at runtime.
+
+//        Bundle extras = new Bundle(1);
+//        extras.putBinder(BINDER_KEY, new SignInWithGoogleActivity.OnSignInComplete() {
+//            @Override
+//            public void onSignInComplete(@Nullable GoogleSignInAccount account) {
+//                if (account == null) {
+//                    CarToast.makeText(getCarContext(), "Error signing in", LENGTH_LONG).show();
+//                    return;
+//                }
+//
+//                // Use the account
+//                CarToast.makeText(getCarContext(),
+//                        account.getGivenName() + " signed in", LENGTH_LONG).show();
+//            }
+//        });
+//        getCarContext().startActivity(
+//                new Intent()
+//                        .setClass(getCarContext(), SignInWithGoogleActivity.class)
+//                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+//                        .putExtras(extras));
+    }
+
     private MessageTemplate getSignInCompletedMessageTemplate() {
         return new MessageTemplate.Builder("You are signed in!")
                 .setTitle("Sign in completed")
@@ -256,4 +275,5 @@
                         .build())
                 .build();
     }
+
 }
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInWithGoogleActivity.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInWithGoogleActivity.java
new file mode 100644
index 0000000..d7bf59f
--- /dev/null
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInWithGoogleActivity.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.car.app.sample.showcase.common.templates;
+
+import android.os.Bundle;
+
+import androidx.activity.ComponentActivity;
+import androidx.annotation.Nullable;
+
+/**
+ * An activity for use by the car app library to perform actions such as requesting permissions.
+ */
+public class SignInWithGoogleActivity extends ComponentActivity {
+    static final String BINDER_KEY = "binder";
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+//        OnSignInComplete signInCompleteCallback =
+//                (OnSignInComplete) getIntent().getExtras().getBinder(BINDER_KEY);
+//
+//        ActivityResultLauncher<Intent> activityResultLauncher =
+//                registerForActivityResult(
+//                        new ActivityResultContracts.StartActivityForResult(),
+//                        result -> {
+//                            GoogleSignInAccount account =
+//                                    GoogleSignIn.getSignedInAccountFromIntent(
+//                                            result.getData()).getResult();
+//                            signInCompleteCallback.onSignInComplete(account);
+//                            finish();
+//                        });
+//
+//        GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
+//        if (account != null) {
+//            signInCompleteCallback.onSignInComplete(account);
+//            finish();
+//        }
+//
+//        GoogleSignInOptions gso =
+//                new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
+//                        .requestEmail()
+//                        .requestProfile()
+//                        .build();
+//        GoogleSignInClient signInClient = GoogleSignIn.getClient(this, gso);
+//        activityResultLauncher.launch(signInClient.getSignInIntent());
+    }
+
+
+//    /**
+//     * Binder callback to provide to the sign in activity.
+//     */
+//    abstract static class OnSignInComplete extends Binder implements IBinder {
+//        /**
+//         * Notifies that sign in flow completed.
+//         *
+//         * @param account the account signed in or {@code null} if there were issues signing in.
+//         */
+//        public abstract void onSignInComplete(@Nullable GoogleSignInAccount account);
+//    }
+}
diff --git a/car/app/app/api/current.txt b/car/app/app/api/current.txt
index 8d47bcd..777910c 100644
--- a/car/app/app/api/current.txt
+++ b/car/app/app/api/current.txt
@@ -179,14 +179,24 @@
 
 package androidx.car.app.connection {
 
-  public final class ConnectionToCar {
-    ctor public ConnectionToCar(android.content.Context);
+  public final class CarConnection {
+    ctor public CarConnection(android.content.Context);
     method public androidx.lifecycle.LiveData<java.lang.Integer!> getType();
     field public static final String ACTION_CAR_CONNECTION_UPDATED = "androidx.car.app.connection.action.CAR_CONNECTION_UPDATED";
     field public static final String CAR_CONNECTION_STATE = "CarConnectionState";
-    field public static final int NATIVE = 1; // 0x1
-    field public static final int NOT_CONNECTED = 0; // 0x0
-    field public static final int PROJECTION = 2; // 0x2
+    field public static final int CONNECTION_TYPE_NATIVE = 1; // 0x1
+    field public static final int CONNECTION_TYPE_NOT_CONNECTED = 0; // 0x0
+    field public static final int CONNECTION_TYPE_PROJECTION = 2; // 0x2
+  }
+
+  @Deprecated public final class ConnectionToCar {
+    ctor @Deprecated public ConnectionToCar(android.content.Context);
+    method @Deprecated public androidx.lifecycle.LiveData<java.lang.Integer!> getType();
+    field @Deprecated public static final String ACTION_CAR_CONNECTION_UPDATED = "androidx.car.app.connection.action.CAR_CONNECTION_UPDATED";
+    field @Deprecated public static final String CAR_CONNECTION_STATE = "CarConnectionState";
+    field @Deprecated public static final int NATIVE = 1; // 0x1
+    field @Deprecated public static final int NOT_CONNECTED = 0; // 0x0
+    field @Deprecated public static final int PROJECTION = 2; // 0x2
   }
 
 }
@@ -1050,6 +1060,7 @@
   }
 
   public static final class Step.Builder {
+    ctor public Step.Builder();
     ctor public Step.Builder(CharSequence);
     ctor public Step.Builder(androidx.car.app.model.CarText);
     method public androidx.car.app.navigation.model.Step.Builder addLane(androidx.car.app.navigation.model.Lane);
diff --git a/car/app/app/api/public_plus_experimental_current.txt b/car/app/app/api/public_plus_experimental_current.txt
index 0fafb1f..29159e0 100644
--- a/car/app/app/api/public_plus_experimental_current.txt
+++ b/car/app/app/api/public_plus_experimental_current.txt
@@ -182,14 +182,24 @@
 
 package androidx.car.app.connection {
 
-  public final class ConnectionToCar {
-    ctor public ConnectionToCar(android.content.Context);
+  public final class CarConnection {
+    ctor public CarConnection(android.content.Context);
     method public androidx.lifecycle.LiveData<java.lang.Integer!> getType();
     field public static final String ACTION_CAR_CONNECTION_UPDATED = "androidx.car.app.connection.action.CAR_CONNECTION_UPDATED";
     field public static final String CAR_CONNECTION_STATE = "CarConnectionState";
-    field public static final int NATIVE = 1; // 0x1
-    field public static final int NOT_CONNECTED = 0; // 0x0
-    field public static final int PROJECTION = 2; // 0x2
+    field public static final int CONNECTION_TYPE_NATIVE = 1; // 0x1
+    field public static final int CONNECTION_TYPE_NOT_CONNECTED = 0; // 0x0
+    field public static final int CONNECTION_TYPE_PROJECTION = 2; // 0x2
+  }
+
+  @Deprecated public final class ConnectionToCar {
+    ctor @Deprecated public ConnectionToCar(android.content.Context);
+    method @Deprecated public androidx.lifecycle.LiveData<java.lang.Integer!> getType();
+    field @Deprecated public static final String ACTION_CAR_CONNECTION_UPDATED = "androidx.car.app.connection.action.CAR_CONNECTION_UPDATED";
+    field @Deprecated public static final String CAR_CONNECTION_STATE = "CarConnectionState";
+    field @Deprecated public static final int NATIVE = 1; // 0x1
+    field @Deprecated public static final int NOT_CONNECTED = 0; // 0x0
+    field @Deprecated public static final int PROJECTION = 2; // 0x2
   }
 
 }
@@ -1053,6 +1063,7 @@
   }
 
   public static final class Step.Builder {
+    ctor public Step.Builder();
     ctor public Step.Builder(CharSequence);
     ctor public Step.Builder(androidx.car.app.model.CarText);
     method public androidx.car.app.navigation.model.Step.Builder addLane(androidx.car.app.navigation.model.Lane);
diff --git a/car/app/app/api/restricted_current.txt b/car/app/app/api/restricted_current.txt
index 8d47bcd..777910c 100644
--- a/car/app/app/api/restricted_current.txt
+++ b/car/app/app/api/restricted_current.txt
@@ -179,14 +179,24 @@
 
 package androidx.car.app.connection {
 
-  public final class ConnectionToCar {
-    ctor public ConnectionToCar(android.content.Context);
+  public final class CarConnection {
+    ctor public CarConnection(android.content.Context);
     method public androidx.lifecycle.LiveData<java.lang.Integer!> getType();
     field public static final String ACTION_CAR_CONNECTION_UPDATED = "androidx.car.app.connection.action.CAR_CONNECTION_UPDATED";
     field public static final String CAR_CONNECTION_STATE = "CarConnectionState";
-    field public static final int NATIVE = 1; // 0x1
-    field public static final int NOT_CONNECTED = 0; // 0x0
-    field public static final int PROJECTION = 2; // 0x2
+    field public static final int CONNECTION_TYPE_NATIVE = 1; // 0x1
+    field public static final int CONNECTION_TYPE_NOT_CONNECTED = 0; // 0x0
+    field public static final int CONNECTION_TYPE_PROJECTION = 2; // 0x2
+  }
+
+  @Deprecated public final class ConnectionToCar {
+    ctor @Deprecated public ConnectionToCar(android.content.Context);
+    method @Deprecated public androidx.lifecycle.LiveData<java.lang.Integer!> getType();
+    field @Deprecated public static final String ACTION_CAR_CONNECTION_UPDATED = "androidx.car.app.connection.action.CAR_CONNECTION_UPDATED";
+    field @Deprecated public static final String CAR_CONNECTION_STATE = "CarConnectionState";
+    field @Deprecated public static final int NATIVE = 1; // 0x1
+    field @Deprecated public static final int NOT_CONNECTED = 0; // 0x0
+    field @Deprecated public static final int PROJECTION = 2; // 0x2
   }
 
 }
@@ -1050,6 +1060,7 @@
   }
 
   public static final class Step.Builder {
+    ctor public Step.Builder();
     ctor public Step.Builder(CharSequence);
     ctor public Step.Builder(androidx.car.app.model.CarText);
     method public androidx.car.app.navigation.model.Step.Builder addLane(androidx.car.app.navigation.model.Lane);
diff --git a/car/app/app/src/main/java/androidx/car/app/connection/AutomotiveConnectionToCarTypeLiveData.java b/car/app/app/src/main/java/androidx/car/app/connection/AutomotiveCarConnectionTypeLiveData.java
similarity index 79%
rename from car/app/app/src/main/java/androidx/car/app/connection/AutomotiveConnectionToCarTypeLiveData.java
rename to car/app/app/src/main/java/androidx/car/app/connection/AutomotiveCarConnectionTypeLiveData.java
index f8857be..b35606b 100644
--- a/car/app/app/src/main/java/androidx/car/app/connection/AutomotiveConnectionToCarTypeLiveData.java
+++ b/car/app/app/src/main/java/androidx/car/app/connection/AutomotiveCarConnectionTypeLiveData.java
@@ -16,15 +16,15 @@
 
 package androidx.car.app.connection;
 
-import androidx.car.app.connection.ConnectionToCar.ConnectionType;
+import androidx.car.app.connection.CarConnection.ConnectionType;
 import androidx.lifecycle.LiveData;
 
 /**
  * A {@link LiveData} that always returns that it is connected natively to a car head unit.
  */
-final class AutomotiveConnectionToCarTypeLiveData extends LiveData<@ConnectionType Integer> {
+final class AutomotiveCarConnectionTypeLiveData extends LiveData<@ConnectionType Integer> {
     @Override
     protected void onActive() {
-        setValue(ConnectionToCar.NATIVE);
+        setValue(CarConnection.CONNECTION_TYPE_NATIVE);
     }
 }
diff --git a/car/app/app/src/main/java/androidx/car/app/connection/CarConnection.java b/car/app/app/src/main/java/androidx/car/app/connection/CarConnection.java
new file mode 100644
index 0000000..79d81bd
--- /dev/null
+++ b/car/app/app/src/main/java/androidx/car/app/connection/CarConnection.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.car.app.connection;
+
+import static androidx.annotation.RestrictTo.Scope.LIBRARY;
+import static androidx.car.app.utils.CommonUtils.isAutomotiveOS;
+
+import static java.util.Objects.requireNonNull;
+
+import android.content.Context;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.lifecycle.LiveData;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A class that allows retrieval of information about connection to a car head unit.
+ */
+public final class CarConnection {
+    /**
+     * Defines current car connection state.
+     *
+     * <p>This is used for communication with the car host's content provider on queries for
+     * connection type.
+     */
+    public static final String CAR_CONNECTION_STATE = "CarConnectionState";
+
+    /**
+     * Broadcast action that notifies that the car connection has changed and needs to be updated.
+     */
+    public static final String ACTION_CAR_CONNECTION_UPDATED =
+            "androidx.car.app.connection.action.CAR_CONNECTION_UPDATED";
+
+    /**
+     * Represents the types of connections that exist to a car head unit.
+     *
+     * @hide
+     */
+    @IntDef({CONNECTION_TYPE_NOT_CONNECTED, CONNECTION_TYPE_NATIVE, CONNECTION_TYPE_PROJECTION})
+    @Retention(RetentionPolicy.SOURCE)
+    @Target({ElementType.TYPE_USE})
+    @RestrictTo(LIBRARY)
+    public @interface ConnectionType {
+    }
+
+    /**
+     * Not connected to any car head unit.z
+     */
+    public static final int CONNECTION_TYPE_NOT_CONNECTED = 0;
+
+    /**
+     * Natively running on a head unit (Android Automotive OS).
+     */
+    public static final int CONNECTION_TYPE_NATIVE = 1;
+
+    /**
+     * Connected to a car head unit by projecting to it.
+     */
+    public static final int CONNECTION_TYPE_PROJECTION = 2;
+
+    private final LiveData<Integer> mConnectionTypeLiveData;
+
+    /**
+     * Constructs a {@link CarConnection} that can be used to get connection information.
+     *
+     * @throws NullPointerException if {@code context} is {@code null}
+     */
+    public CarConnection(@NonNull Context context) {
+        requireNonNull(context);
+        mConnectionTypeLiveData = isAutomotiveOS(context)
+                ? new AutomotiveCarConnectionTypeLiveData()
+                : new CarConnectionTypeLiveData(context);
+    }
+
+    /**
+     * Returns a {@link LiveData} that can be observed to get current connection type.
+     *
+     * <p>The recommended pattern is to observe the {@link LiveData} with the activity's
+     * lifecycle in order to get updates on the state change throughout the activity's lifetime.
+     *
+     * <p>Connection types are:
+     * <ol>
+     *     <li>{@link #CONNECTION_TYPE_NOT_CONNECTED}
+     *     <li>{@link #CONNECTION_TYPE_NATIVE}
+     *     <li>{@link #CONNECTION_TYPE_PROJECTION}
+     * </ol>
+     */
+    @NonNull
+    public LiveData<@ConnectionType Integer> getType() {
+        return mConnectionTypeLiveData;
+    }
+}
diff --git a/car/app/app/src/main/java/androidx/car/app/connection/ConnectionToCarTypeLiveData.java b/car/app/app/src/main/java/androidx/car/app/connection/CarConnectionTypeLiveData.java
similarity index 84%
rename from car/app/app/src/main/java/androidx/car/app/connection/ConnectionToCarTypeLiveData.java
rename to car/app/app/src/main/java/androidx/car/app/connection/CarConnectionTypeLiveData.java
index 77d714a..79f30f9 100644
--- a/car/app/app/src/main/java/androidx/car/app/connection/ConnectionToCarTypeLiveData.java
+++ b/car/app/app/src/main/java/androidx/car/app/connection/CarConnectionTypeLiveData.java
@@ -16,8 +16,8 @@
 
 package androidx.car.app.connection;
 
-import static androidx.car.app.connection.ConnectionToCar.ACTION_CAR_CONNECTION_UPDATED;
-import static androidx.car.app.connection.ConnectionToCar.CAR_CONNECTION_STATE;
+import static androidx.car.app.connection.CarConnection.ACTION_CAR_CONNECTION_UPDATED;
+import static androidx.car.app.connection.CarConnection.CAR_CONNECTION_STATE;
 import static androidx.car.app.utils.LogTags.TAG_CONNECTION_TO_CAR;
 
 import android.content.AsyncQueryHandler;
@@ -31,14 +31,14 @@
 import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
-import androidx.car.app.connection.ConnectionToCar.ConnectionType;
+import androidx.car.app.connection.CarConnection.ConnectionType;
 import androidx.lifecycle.LiveData;
 
 /**
  * A {@link LiveData} that will query once while being observed and only again if it gets updates
  * via a broadcast.
  */
-final class ConnectionToCarTypeLiveData extends LiveData<@ConnectionType Integer> {
+final class CarConnectionTypeLiveData extends LiveData<@ConnectionType Integer> {
     @VisibleForTesting
     static final String CAR_CONNECTION_AUTHORITY = "androidx.car.app.connection";
 
@@ -50,7 +50,7 @@
     private final AsyncQueryHandler mQueryHandler;
     private final CarConnectionBroadcastReceiver mBroadcastReceiver;
 
-    ConnectionToCarTypeLiveData(Context context) {
+    CarConnectionTypeLiveData(Context context) {
         mContext = context;
 
         mQueryHandler = new CarConnectionQueryHandler(
@@ -88,7 +88,7 @@
             if (response == null) {
                 Log.w(TAG_CONNECTION_TO_CAR, "Null response from content provider when checking "
                         + "connection to the car, treating as disconnected");
-                postValue(ConnectionToCar.NOT_CONNECTED);
+                postValue(CarConnection.CONNECTION_TYPE_NOT_CONNECTED);
                 return;
             }
 
@@ -96,14 +96,14 @@
             if (carConnectionTypeColumn < 0) {
                 Log.e(TAG_CONNECTION_TO_CAR, "Connection to car response is missing the "
                         + "connection type, treating as disconnected");
-                postValue(ConnectionToCar.NOT_CONNECTED);
+                postValue(CarConnection.CONNECTION_TYPE_NOT_CONNECTED);
                 return;
             }
 
             if (!response.moveToNext()) {
-                Log.e(TAG_CONNECTION_TO_CAR,  "Connection to car response is empty, treating as "
+                Log.e(TAG_CONNECTION_TO_CAR, "Connection to car response is empty, treating as "
                         + "disconnected");
-                postValue(ConnectionToCar.NOT_CONNECTED);
+                postValue(CarConnection.CONNECTION_TYPE_NOT_CONNECTED);
                 return;
             }
 
diff --git a/car/app/app/src/main/java/androidx/car/app/connection/ConnectionToCar.java b/car/app/app/src/main/java/androidx/car/app/connection/ConnectionToCar.java
index 1397c0a..4caabbe 100644
--- a/car/app/app/src/main/java/androidx/car/app/connection/ConnectionToCar.java
+++ b/car/app/app/src/main/java/androidx/car/app/connection/ConnectionToCar.java
@@ -33,14 +33,19 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+// TODO(b/169537526): Remove this class
 /**
  * A class that allows retrieval of information about connection to a car head unit.
+ *
+ * @deprecated use {@link CarConnection} instead.
  */
+@Deprecated
 public final class ConnectionToCar {
     /**
      * Defines current car connection state.
      *
-     * <p>This is used for communication with the car host.
+     * <p>This is used for communication with the car host's content provider on queries for
+     * connection type.
      */
     public static final String CAR_CONNECTION_STATE = "CarConnectionState";
 
@@ -87,8 +92,8 @@
     public ConnectionToCar(@NonNull Context context) {
         requireNonNull(context);
         mConnectionTypeLiveData = isAutomotiveOS(context)
-                ? new AutomotiveConnectionToCarTypeLiveData()
-                : new ConnectionToCarTypeLiveData(context);
+                ? new AutomotiveCarConnectionTypeLiveData()
+                : new CarConnectionTypeLiveData(context);
     }
 
     /**
diff --git a/car/app/app/src/main/java/androidx/car/app/navigation/model/Step.java b/car/app/app/src/main/java/androidx/car/app/navigation/model/Step.java
index 5604161..5af30b8 100644
--- a/car/app/app/src/main/java/androidx/car/app/navigation/model/Step.java
+++ b/car/app/app/src/main/java/androidx/car/app/navigation/model/Step.java
@@ -173,15 +173,21 @@
         private Maneuver mManeuver;
         @Nullable
         private CarIcon mLanesImage;
+        @Nullable
         private CarText mCue;
         @Nullable
         private CarText mRoad;
 
         /**
+        * Constructs a new builder of {@link Step}.
+        */
+        public Builder() {
+        }
+
+        /**
          * Constructs a new builder of {@link Step} with a cue.
          *
-         * <p>A cue must always be set when the step is created and is used as a fallback when
-         * {@link Maneuver} is not set or is unavailable.
+         * <p>A cue can be used as a fallback when {@link Maneuver} is not set or is unavailable.
          *
          * <p>Some cluster displays do not support UTF-8 encoded characters, in which case
          * unsupported characters will not be displayed properly.
@@ -267,8 +273,7 @@
         /**
          * Sets a text description of this maneuver.
          *
-         * <p>Must always be set when the step is created and is used as a fallback when {@link
-         * Maneuver} is not set or is unavailable.
+         * <p>A cue can be used as a fallback when {@link Maneuver} is not set or is unavailable.
          *
          * <p>For example "Turn left", "Make a U-Turn", "Sharp Right", or "Take the exit using
          * the left lane"
diff --git a/car/app/app/src/test/java/androidx/car/app/connection/AutomotiveConnectionToCarTypeLiveDataTest.java b/car/app/app/src/test/java/androidx/car/app/connection/AutomotiveCarConnectionTypeLiveDataTest.java
similarity index 81%
rename from car/app/app/src/test/java/androidx/car/app/connection/AutomotiveConnectionToCarTypeLiveDataTest.java
rename to car/app/app/src/test/java/androidx/car/app/connection/AutomotiveCarConnectionTypeLiveDataTest.java
index 83a95bb..aeb08a8 100644
--- a/car/app/app/src/test/java/androidx/car/app/connection/AutomotiveConnectionToCarTypeLiveDataTest.java
+++ b/car/app/app/src/test/java/androidx/car/app/connection/AutomotiveCarConnectionTypeLiveDataTest.java
@@ -28,10 +28,10 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.internal.DoNotInstrument;
 
-/** Tests for {@link AutomotiveConnectionToCarTypeLiveData}. */
+/** Tests for {@link AutomotiveCarConnectionTypeLiveData}. */
 @RunWith(RobolectricTestRunner.class)
 @DoNotInstrument
-public class AutomotiveConnectionToCarTypeLiveDataTest {
+public class AutomotiveCarConnectionTypeLiveDataTest {
     @Mock private Observer<Integer> mMockObserver;
 
     @Before
@@ -41,8 +41,8 @@
 
     @Test
     public void observe_returnsNative() {
-        new AutomotiveConnectionToCarTypeLiveData().observeForever(mMockObserver);
+        new AutomotiveCarConnectionTypeLiveData().observeForever(mMockObserver);
 
-        verify(mMockObserver).onChanged(ConnectionToCar.NATIVE);
+        verify(mMockObserver).onChanged(CarConnection.CONNECTION_TYPE_NATIVE);
     }
 }
diff --git a/car/app/app/src/test/java/androidx/car/app/connection/ConnectionToCarTest.java b/car/app/app/src/test/java/androidx/car/app/connection/CarConnectionTest.java
similarity index 80%
rename from car/app/app/src/test/java/androidx/car/app/connection/ConnectionToCarTest.java
rename to car/app/app/src/test/java/androidx/car/app/connection/CarConnectionTest.java
index 18c6222..e7f4a7b 100644
--- a/car/app/app/src/test/java/androidx/car/app/connection/ConnectionToCarTest.java
+++ b/car/app/app/src/test/java/androidx/car/app/connection/CarConnectionTest.java
@@ -31,23 +31,23 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.internal.DoNotInstrument;
 
-/** Tests for {@link ConnectionToCar}. */
+/** Tests for {@link CarConnection}. */
 @RunWith(RobolectricTestRunner.class)
 @DoNotInstrument
-public class ConnectionToCarTest {
+public class CarConnectionTest {
     private final Context mContext = ApplicationProvider.getApplicationContext();
 
     @Test
     public void getType_projection() {
-        assertThat(new ConnectionToCar(mContext).getType()).isInstanceOf(
-                ConnectionToCarTypeLiveData.class);
+        assertThat(new CarConnection(mContext).getType()).isInstanceOf(
+                CarConnectionTypeLiveData.class);
     }
 
     @Test
     public void getType_automotive() {
         shadowOf(mContext.getPackageManager()).setSystemFeature(FEATURE_AUTOMOTIVE, true);
 
-        assertThat(new ConnectionToCar(mContext).getType()).isInstanceOf(
-                AutomotiveConnectionToCarTypeLiveData.class);
+        assertThat(new CarConnection(mContext).getType()).isInstanceOf(
+                AutomotiveCarConnectionTypeLiveData.class);
     }
 }
diff --git a/car/app/app/src/test/java/androidx/car/app/connection/ConnectionToCarTypeLiveDataTest.java b/car/app/app/src/test/java/androidx/car/app/connection/CarConnectionTypeLiveDataTest.java
similarity index 73%
rename from car/app/app/src/test/java/androidx/car/app/connection/ConnectionToCarTypeLiveDataTest.java
rename to car/app/app/src/test/java/androidx/car/app/connection/CarConnectionTypeLiveDataTest.java
index 976b8ee..ae02a8e 100644
--- a/car/app/app/src/test/java/androidx/car/app/connection/ConnectionToCarTypeLiveDataTest.java
+++ b/car/app/app/src/test/java/androidx/car/app/connection/CarConnectionTypeLiveDataTest.java
@@ -49,16 +49,16 @@
 import org.robolectric.shadows.ShadowApplication;
 import org.robolectric.shadows.ShadowLooper;
 
-/** Tests for {@link ConnectionToCarTypeLiveData}. */
+/** Tests for {@link CarConnectionTypeLiveData}. */
 @RunWith(RobolectricTestRunner.class)
 @DoNotInstrument
-public class ConnectionToCarTypeLiveDataTest {
+public class CarConnectionTypeLiveDataTest {
     @Mock
     private Observer<Integer> mMockObserver;
 
     private final Application mApplication = ApplicationProvider.getApplicationContext();
     private final Context mContext = ApplicationProvider.getApplicationContext();
-    private ConnectionToCarTypeLiveData mConnectionToCarTypeLiveData;
+    private CarConnectionTypeLiveData mCarConnectionTypeLiveData;
     private TestContentProvider mContentProvider;
 
     @Before
@@ -66,76 +66,76 @@
         MockitoAnnotations.initMocks(this);
 
         ProviderInfo info = new ProviderInfo();
-        info.authority = ConnectionToCarTypeLiveData.CAR_CONNECTION_AUTHORITY;
+        info.authority = CarConnectionTypeLiveData.CAR_CONNECTION_AUTHORITY;
         mContentProvider =
                 Robolectric.buildContentProvider(TestContentProvider.class).create(info).get();
 
         // Starts with 1 broadcast receiver (for CarPendingIntent)
         assertThat(shadowOf(mApplication).getRegisteredReceivers()).hasSize(1);
 
-        mConnectionToCarTypeLiveData = new ConnectionToCarTypeLiveData(mContext);
+        mCarConnectionTypeLiveData = new CarConnectionTypeLiveData(mContext);
     }
 
     @Test
     public void observe_registersBroadcastReceiver() {
         assertThat(shadowOf(mApplication).getRegisteredReceivers()).hasSize(1);
 
-        mConnectionToCarTypeLiveData.observeForever(mMockObserver);
+        mCarConnectionTypeLiveData.observeForever(mMockObserver);
 
         assertThat(shadowOf(mApplication).getRegisteredReceivers()).hasSize(2);
     }
 
     @Test
     public void getInstance_queriesContentProvider() {
-        mConnectionToCarTypeLiveData.observeForever(mMockObserver);
+        mCarConnectionTypeLiveData.observeForever(mMockObserver);
         assertThat(mContentProvider.mDidQueryContentProvider).isTrue();
     }
 
     @Test
     public void contentProviderQuery_wasProjecting() {
         mContentProvider.mIsProjecting = true;
-        mConnectionToCarTypeLiveData = new ConnectionToCarTypeLiveData(mContext);
+        mCarConnectionTypeLiveData = new CarConnectionTypeLiveData(mContext);
 
-        mConnectionToCarTypeLiveData.observeForever(mMockObserver);
+        mCarConnectionTypeLiveData.observeForever(mMockObserver);
         ShadowLooper.runUiThreadTasks();
-        verify(mMockObserver).onChanged(ConnectionToCar.PROJECTION);
+        verify(mMockObserver).onChanged(CarConnection.CONNECTION_TYPE_PROJECTION);
     }
 
     @Test
     public void contentProviderQuery_nullReturn() {
         mContentProvider.mReturnNull = true;
-        mConnectionToCarTypeLiveData = new ConnectionToCarTypeLiveData(mContext);
+        mCarConnectionTypeLiveData = new CarConnectionTypeLiveData(mContext);
 
-        mConnectionToCarTypeLiveData.observeForever(mMockObserver);
+        mCarConnectionTypeLiveData.observeForever(mMockObserver);
         ShadowLooper.runUiThreadTasks();
-        verify(mMockObserver).onChanged(ConnectionToCar.NOT_CONNECTED);
+        verify(mMockObserver).onChanged(CarConnection.CONNECTION_TYPE_NOT_CONNECTED);
     }
 
     @Test
     public void contentProviderQuery_noColumn() {
         mContentProvider.mReturnNoColumn = true;
-        mConnectionToCarTypeLiveData = new ConnectionToCarTypeLiveData(mContext);
+        mCarConnectionTypeLiveData = new CarConnectionTypeLiveData(mContext);
 
-        mConnectionToCarTypeLiveData.observeForever(mMockObserver);
+        mCarConnectionTypeLiveData.observeForever(mMockObserver);
         ShadowLooper.runUiThreadTasks();
-        verify(mMockObserver).onChanged(ConnectionToCar.NOT_CONNECTED);
+        verify(mMockObserver).onChanged(CarConnection.CONNECTION_TYPE_NOT_CONNECTED);
     }
 
     @Test
     public void contentProviderQuery_noRow() {
         mContentProvider.mReturnNoRow = true;
-        mConnectionToCarTypeLiveData = new ConnectionToCarTypeLiveData(mContext);
+        mCarConnectionTypeLiveData = new CarConnectionTypeLiveData(mContext);
 
-        mConnectionToCarTypeLiveData.observeForever(mMockObserver);
+        mCarConnectionTypeLiveData.observeForever(mMockObserver);
         ShadowLooper.runUiThreadTasks();
-        verify(mMockObserver).onChanged(ConnectionToCar.NOT_CONNECTED);
+        verify(mMockObserver).onChanged(CarConnection.CONNECTION_TYPE_NOT_CONNECTED);
     }
 
     @Test
     public void broadcastReceived_queriesAndSetsValue() {
         InOrder mocks = inOrder(mMockObserver);
 
-        mConnectionToCarTypeLiveData.observeForever(mMockObserver);
+        mCarConnectionTypeLiveData.observeForever(mMockObserver);
         ShadowLooper.runUiThreadTasks();
 
         ShadowApplication.Wrapper receiverWrapper = shadowOf(
@@ -143,11 +143,11 @@
 
         mContentProvider.mIsProjecting = true;
         receiverWrapper.broadcastReceiver.onReceive(mContext,
-                new Intent(ConnectionToCar.ACTION_CAR_CONNECTION_UPDATED));
+                new Intent(CarConnection.ACTION_CAR_CONNECTION_UPDATED));
         ShadowLooper.runUiThreadTasks();
 
-        mocks.verify(mMockObserver).onChanged(ConnectionToCar.NOT_CONNECTED);
-        mocks.verify(mMockObserver).onChanged(ConnectionToCar.PROJECTION);
+        mocks.verify(mMockObserver).onChanged(CarConnection.CONNECTION_TYPE_NOT_CONNECTED);
+        mocks.verify(mMockObserver).onChanged(CarConnection.CONNECTION_TYPE_PROJECTION);
         mocks.verifyNoMoreInteractions();
     }
 
@@ -155,11 +155,11 @@
     public void stopObserving_removedBroadcastReceiver() {
         assertThat(shadowOf(mApplication).getRegisteredReceivers()).hasSize(1);
 
-        mConnectionToCarTypeLiveData.observeForever(mMockObserver);
+        mCarConnectionTypeLiveData.observeForever(mMockObserver);
 
         assertThat(shadowOf(mApplication).getRegisteredReceivers()).hasSize(2);
 
-        mConnectionToCarTypeLiveData.removeObserver(mMockObserver);
+        mCarConnectionTypeLiveData.removeObserver(mMockObserver);
 
         assertThat(shadowOf(mApplication).getRegisteredReceivers()).hasSize(1);
     }
@@ -182,7 +182,7 @@
                 @Nullable String selection, @Nullable String[] selectionArgs,
                 @Nullable String sortOrder) {
             mDidQueryContentProvider = true;
-            assertThat(projection).asList().containsExactly(ConnectionToCar.CAR_CONNECTION_STATE);
+            assertThat(projection).asList().containsExactly(CarConnection.CAR_CONNECTION_STATE);
 
             if (mReturnNull) {
                 return null;
@@ -199,9 +199,9 @@
             if (mReturnNoColumn) {
                 return cursor;
             }
-            rowBuilder.add(ConnectionToCar.CAR_CONNECTION_STATE,
-                    mIsProjecting ? ConnectionToCar.PROJECTION :
-                            ConnectionToCar.NOT_CONNECTED);
+            rowBuilder.add(CarConnection.CAR_CONNECTION_STATE,
+                    mIsProjecting ? CarConnection.CONNECTION_TYPE_PROJECTION :
+                            CarConnection.CONNECTION_TYPE_NOT_CONNECTED);
 
             return cursor;
         }
diff --git a/car/app/app/src/test/java/androidx/car/app/navigation/model/StepTest.java b/car/app/app/src/test/java/androidx/car/app/navigation/model/StepTest.java
index 1a46ce9..ea2a1d5 100644
--- a/car/app/app/src/test/java/androidx/car/app/navigation/model/StepTest.java
+++ b/car/app/app/src/test/java/androidx/car/app/navigation/model/StepTest.java
@@ -77,6 +77,43 @@
     }
 
     @Test
+    public void createInstance_noCue() {
+        Lane lane = new Lane.Builder().addDirection(
+                LaneDirection.create(SHAPE_SHARP_LEFT, true)).build();
+
+        Step step =
+                new Step.Builder()
+                    .addLane(lane)
+                    .build();
+
+        assertThat(step.getCue()).isNull();
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void createInstance_cueIsNullInBuilder() {
+        Lane lane = new Lane.Builder().addDirection(
+                LaneDirection.create(SHAPE_SHARP_LEFT, true)).build();
+        CharSequence charSequence = null;
+
+        Step step =
+                new Step.Builder(charSequence)
+                    .addLane(lane)
+                    .build();
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void createInstance_cueIsNullInSetter() {
+        Lane lane = new Lane.Builder().addDirection(
+                LaneDirection.create(SHAPE_SHARP_LEFT, true)).build();
+
+        Step step =
+                new Step.Builder()
+                    .setCue(null)
+                    .addLane(lane)
+                    .build();
+    }
+
+    @Test
     public void createInstance_lanesImage_no_lanes_throws() {
         String cue = "Left at State street.";
 
diff --git a/compose/animation/animation-core-lint/build.gradle b/compose/animation/animation-core-lint/build.gradle
index 9cee8fb..92c1abb 100644
--- a/compose/animation/animation-core-lint/build.gradle
+++ b/compose/animation/animation-core-lint/build.gradle
@@ -28,13 +28,7 @@
 BundleInsideHelper.forInsideLintJar(project)
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly LINT_API_LATEST
-    } else {
-        compileOnly LINT_API_MIN
-    }
+    compileOnly LINT_API_MIN
     compileOnly KOTLIN_STDLIB
     bundleInside(project(":compose:lint:common"))
 
diff --git a/compose/animation/animation-lint/build.gradle b/compose/animation/animation-lint/build.gradle
index 36f50b5..441f4b7 100644
--- a/compose/animation/animation-lint/build.gradle
+++ b/compose/animation/animation-lint/build.gradle
@@ -28,13 +28,7 @@
 BundleInsideHelper.forInsideLintJar(project)
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly LINT_API_LATEST
-    } else {
-        compileOnly LINT_API_MIN
-    }
+    compileOnly LINT_API_MIN
     compileOnly KOTLIN_STDLIB
     bundleInside(project(":compose:lint:common"))
 
diff --git a/compose/desktop/desktop/build.gradle b/compose/desktop/desktop/build.gradle
index ce53db3..a3ca2ad 100644
--- a/compose/desktop/desktop/build.gradle
+++ b/compose/desktop/desktop/build.gradle
@@ -19,6 +19,7 @@
 import androidx.build.LibraryVersions
 import androidx.build.RunApiTasks
 import androidx.build.SupportConfigKt
+import androidx.build.ComposeJvmTarget
 
 import static androidx.build.AndroidXPlugin.BUILD_ON_SERVER_TASK
 import static androidx.build.dependencies.DependenciesKt.*
@@ -34,9 +35,9 @@
 }
 
 kotlin {
-    jvm() {
-        withJava()
-    }
+    // Replace with jvm() { withJava() }
+    // Once the build switches to Kotlin 1.5
+    ComposeJvmTarget.withJava(jvm())
 
     sourceSets {
         commonMain.dependencies {
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionDelegateTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionDelegateTest.kt
index 474d1215..bf21e40 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionDelegateTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/selection/TextFieldSelectionDelegateTest.kt
@@ -344,6 +344,32 @@
         assertThat(range.end).isEqualTo(endOffset)
     }
 
+    @Test
+    fun getTextFieldSelection_empty_string() {
+        val text = ""
+        val fontSize = 20.sp
+
+        val textLayoutResult = simpleTextLayout(
+            text = text,
+            fontSize = fontSize,
+            density = defaultDensity
+        )
+
+        // Act.
+        val range = getTextFieldSelection(
+            textLayoutResult = textLayoutResult,
+            rawStartOffset = 0,
+            rawEndOffset = 0,
+            previousSelection = null,
+            isStartHandle = true,
+            adjustment = SelectionAdjustment.WORD
+        )
+
+        // Assert.
+        assertThat(range.start).isEqualTo(0)
+        assertThat(range.end).isEqualTo(0)
+    }
+
     @OptIn(InternalFoundationTextApi::class)
     private fun simpleTextLayout(
         text: String = "",
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/TextSelectionDelegate.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/TextSelectionDelegate.kt
index fcd0212..63aaf64 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/TextSelectionDelegate.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/selection/TextSelectionDelegate.kt
@@ -101,7 +101,8 @@
     previousHandlesCrossed: Boolean,
     adjustment: SelectionAdjustment
 ): TextRange {
-    if (adjustment == SelectionAdjustment.NONE) {
+    val textLength = textLayoutResult.layoutInput.text.text.length
+    if (adjustment == SelectionAdjustment.NONE || textLength == 0) {
         return textRange
     }
 
@@ -124,7 +125,7 @@
         textLayoutResult.layoutInput.text.text::getParagraphBoundary
     }
 
-    val maxOffset = textLayoutResult.layoutInput.text.text.length - 1
+    val maxOffset = textLength - 1
     val startBoundary = boundaryFun(textRange.start.coerceIn(0, maxOffset))
     val endBoundary = boundaryFun(textRange.end.coerceIn(0, maxOffset))
 
diff --git a/compose/material/material-lint/build.gradle b/compose/material/material-lint/build.gradle
index 0ba4d6d..e413333 100644
--- a/compose/material/material-lint/build.gradle
+++ b/compose/material/material-lint/build.gradle
@@ -28,13 +28,7 @@
 BundleInsideHelper.forInsideLintJar(project)
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly LINT_API_LATEST
-    } else {
-        compileOnly LINT_API_MIN
-    }
+    compileOnly LINT_API_MIN
     compileOnly KOTLIN_STDLIB
     bundleInside(project(":compose:lint:common"))
 
diff --git a/compose/material/material-ripple/src/androidMain/kotlin/androidx/compose/material/ripple/Ripple.android.kt b/compose/material/material-ripple/src/androidMain/kotlin/androidx/compose/material/ripple/Ripple.android.kt
index d0e9e60..326c385 100644
--- a/compose/material/material-ripple/src/androidMain/kotlin/androidx/compose/material/ripple/Ripple.android.kt
+++ b/compose/material/material-ripple/src/androidMain/kotlin/androidx/compose/material/ripple/Ripple.android.kt
@@ -66,8 +66,10 @@
         color: State<Color>,
         rippleAlpha: State<RippleAlpha>
     ): RippleIndicationInstance {
+        val view = findNearestViewGroup()
         // Fallback to drawing inside Compose if needed, using the common implementation
-        if (!LocalRippleNativeRendering.current) {
+        // TODO(b/188112048): Remove isInEditMode once RenderThread support is fixed in Layoutlib.
+        if (!LocalRippleNativeRendering.current || view.isInEditMode) {
             return remember(interactionSource, this) {
                 CommonRippleIndicationInstance(bounded, radius, color, rippleAlpha)
             }
@@ -75,8 +77,6 @@
 
         // Create or get the RippleContainer attached to the nearest root Compose view
 
-        val view = findNearestViewGroup()
-
         var rippleContainer: RippleContainer? = null
 
         for (index in 0 until view.childCount) {
diff --git a/compose/runtime/runtime-lint/build.gradle b/compose/runtime/runtime-lint/build.gradle
index e2db424..30b5400 100644
--- a/compose/runtime/runtime-lint/build.gradle
+++ b/compose/runtime/runtime-lint/build.gradle
@@ -28,13 +28,7 @@
 BundleInsideHelper.forInsideLintJar(project)
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly(LINT_API_LATEST)
-    } else {
-        compileOnly(LINT_API_MIN)
-    }
+    compileOnly(LINT_API_MIN)
     compileOnly(KOTLIN_STDLIB)
     bundleInside(project(":compose:lint:common"))
 
diff --git a/compose/runtime/runtime-saveable-lint/build.gradle b/compose/runtime/runtime-saveable-lint/build.gradle
index a1a65a0..dca4aab 100644
--- a/compose/runtime/runtime-saveable-lint/build.gradle
+++ b/compose/runtime/runtime-saveable-lint/build.gradle
@@ -28,13 +28,7 @@
 BundleInsideHelper.forInsideLintJar(project)
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly(LINT_API_LATEST)
-    } else {
-        compileOnly(LINT_API_MIN)
-    }
+    compileOnly(LINT_API_MIN)
     compileOnly(KOTLIN_STDLIB)
     bundleInside(project(":compose:lint:common"))
 
diff --git a/compose/ui/ui-graphics-lint/build.gradle b/compose/ui/ui-graphics-lint/build.gradle
index 09e0ee9..8d06b87 100644
--- a/compose/ui/ui-graphics-lint/build.gradle
+++ b/compose/ui/ui-graphics-lint/build.gradle
@@ -28,13 +28,7 @@
 BundleInsideHelper.forInsideLintJar(project)
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly(LINT_API_LATEST)
-    } else {
-        compileOnly(LINT_API_MIN)
-    }
+    compileOnly(LINT_API_MIN)
     compileOnly(KOTLIN_STDLIB)
 
     bundleInside(project(":compose:lint:common"))
diff --git a/compose/ui/ui-lint/build.gradle b/compose/ui/ui-lint/build.gradle
index fe21cd0..ed38111 100644
--- a/compose/ui/ui-lint/build.gradle
+++ b/compose/ui/ui-lint/build.gradle
@@ -28,13 +28,7 @@
 BundleInsideHelper.forInsideLintJar(project)
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly(LINT_API_LATEST)
-    } else {
-        compileOnly(LINT_API_MIN)
-    }
+    compileOnly(LINT_API_MIN)
     compileOnly(KOTLIN_STDLIB)
 
     bundleInside(project(":compose:lint:common"))
diff --git a/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/android/ComposeRootRegistry.android.kt b/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/android/ComposeRootRegistry.android.kt
index 975fb6f..f60a598 100644
--- a/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/android/ComposeRootRegistry.android.kt
+++ b/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/android/ComposeRootRegistry.android.kt
@@ -191,7 +191,9 @@
         override fun onViewAttachedToWindow(view: View) {
             // Only add lifecycle observer. If the root is resumed,
             // the lifecycle observer will get notified.
-            val lifecycle = checkNotNull(ViewTreeLifecycleOwner.get(view)?.lifecycle)
+            // TODO: This can be missing if the ComposeView is in a ViewOverlay.
+            // If so, we do nothing and bail.
+            val lifecycle = ViewTreeLifecycleOwner.get(view)?.lifecycle ?: return
             lifecycle.addObserver(this)
             // Setup a lambda to remove the observer when we're detached from the window. When
             // that happens, we won't have access to the lifecycle anymore.
diff --git a/compose/ui/ui/api/1.0.0-beta08.txt b/compose/ui/ui/api/1.0.0-beta08.txt
index 1b73557..3c64838 100644
--- a/compose/ui/ui/api/1.0.0-beta08.txt
+++ b/compose/ui/ui/api/1.0.0-beta08.txt
@@ -1924,9 +1924,6 @@
     property protected boolean shouldCreateCompositionOnAttachedToWindow;
   }
 
-  public final class ComposeView_androidKt {
-  }
-
   public final class CompositionLocalsKt {
     method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.platform.AccessibilityManager> getLocalAccessibilityManager();
     method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.platform.ClipboardManager> getLocalClipboardManager();
diff --git a/compose/ui/ui/api/current.ignore b/compose/ui/ui/api/current.ignore
index 8c133d6..b392991 100644
--- a/compose/ui/ui/api/current.ignore
+++ b/compose/ui/ui/api/current.ignore
@@ -21,6 +21,8 @@
 
 RemovedClass: androidx.compose.ui.focus.FocusStateKt:
     Removed class androidx.compose.ui.focus.FocusStateKt
+RemovedClass: androidx.compose.ui.platform.ComposeView_androidKt:
+    Removed class androidx.compose.ui.platform.ComposeView_androidKt
 
 
 RemovedField: androidx.compose.ui.focus.FocusState#Active:
diff --git a/compose/ui/ui/api/current.txt b/compose/ui/ui/api/current.txt
index 1b73557..3c64838 100644
--- a/compose/ui/ui/api/current.txt
+++ b/compose/ui/ui/api/current.txt
@@ -1924,9 +1924,6 @@
     property protected boolean shouldCreateCompositionOnAttachedToWindow;
   }
 
-  public final class ComposeView_androidKt {
-  }
-
   public final class CompositionLocalsKt {
     method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.platform.AccessibilityManager> getLocalAccessibilityManager();
     method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.platform.ClipboardManager> getLocalClipboardManager();
diff --git a/compose/ui/ui/api/public_plus_experimental_1.0.0-beta08.txt b/compose/ui/ui/api/public_plus_experimental_1.0.0-beta08.txt
index 286637c..6f6667c 100644
--- a/compose/ui/ui/api/public_plus_experimental_1.0.0-beta08.txt
+++ b/compose/ui/ui/api/public_plus_experimental_1.0.0-beta08.txt
@@ -2037,9 +2037,6 @@
     property protected boolean shouldCreateCompositionOnAttachedToWindow;
   }
 
-  public final class ComposeView_androidKt {
-  }
-
   public final class CompositionLocalsKt {
     method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.platform.AccessibilityManager> getLocalAccessibilityManager();
     method @androidx.compose.ui.ExperimentalComposeUiApi public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.autofill.Autofill> getLocalAutofill();
diff --git a/compose/ui/ui/api/public_plus_experimental_current.txt b/compose/ui/ui/api/public_plus_experimental_current.txt
index 286637c..6f6667c 100644
--- a/compose/ui/ui/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui/api/public_plus_experimental_current.txt
@@ -2037,9 +2037,6 @@
     property protected boolean shouldCreateCompositionOnAttachedToWindow;
   }
 
-  public final class ComposeView_androidKt {
-  }
-
   public final class CompositionLocalsKt {
     method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.platform.AccessibilityManager> getLocalAccessibilityManager();
     method @androidx.compose.ui.ExperimentalComposeUiApi public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.autofill.Autofill> getLocalAutofill();
diff --git a/compose/ui/ui/api/restricted_1.0.0-beta08.txt b/compose/ui/ui/api/restricted_1.0.0-beta08.txt
index 386faca..196241f 100644
--- a/compose/ui/ui/api/restricted_1.0.0-beta08.txt
+++ b/compose/ui/ui/api/restricted_1.0.0-beta08.txt
@@ -1954,9 +1954,6 @@
     property protected boolean shouldCreateCompositionOnAttachedToWindow;
   }
 
-  public final class ComposeView_androidKt {
-  }
-
   public final class CompositionLocalsKt {
     method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.platform.AccessibilityManager> getLocalAccessibilityManager();
     method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.platform.ClipboardManager> getLocalClipboardManager();
diff --git a/compose/ui/ui/api/restricted_current.ignore b/compose/ui/ui/api/restricted_current.ignore
index 8c133d6..b392991 100644
--- a/compose/ui/ui/api/restricted_current.ignore
+++ b/compose/ui/ui/api/restricted_current.ignore
@@ -21,6 +21,8 @@
 
 RemovedClass: androidx.compose.ui.focus.FocusStateKt:
     Removed class androidx.compose.ui.focus.FocusStateKt
+RemovedClass: androidx.compose.ui.platform.ComposeView_androidKt:
+    Removed class androidx.compose.ui.platform.ComposeView_androidKt
 
 
 RemovedField: androidx.compose.ui.focus.FocusState#Active:
diff --git a/compose/ui/ui/api/restricted_current.txt b/compose/ui/ui/api/restricted_current.txt
index 386faca..196241f 100644
--- a/compose/ui/ui/api/restricted_current.txt
+++ b/compose/ui/ui/api/restricted_current.txt
@@ -1954,9 +1954,6 @@
     property protected boolean shouldCreateCompositionOnAttachedToWindow;
   }
 
-  public final class ComposeView_androidKt {
-  }
-
   public final class CompositionLocalsKt {
     method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.platform.AccessibilityManager> getLocalAccessibilityManager();
     method public static androidx.compose.runtime.ProvidableCompositionLocal<androidx.compose.ui.platform.ClipboardManager> getLocalClipboardManager();
diff --git a/compose/ui/ui/src/androidAndroidTest/AndroidManifest.xml b/compose/ui/ui/src/androidAndroidTest/AndroidManifest.xml
index b6b7f01..5a120c7 100644
--- a/compose/ui/ui/src/androidAndroidTest/AndroidManifest.xml
+++ b/compose/ui/ui/src/androidAndroidTest/AndroidManifest.xml
@@ -25,6 +25,7 @@
             android:name="androidx.compose.ui.input.pointer.AndroidPointerInputTestActivity" />
         <activity android:name="androidx.appcompat.app.AppCompatActivity"
             android:theme="@style/Theme.AppCompat"/>
+        <activity android:name="androidx.activity.ComponentActivity" />
         <activity android:name="androidx.fragment.app.FragmentActivity"/>
         <activity android:name="androidx.compose.ui.window.ActivityWithFlagSecure"/>
         <activity android:name="androidx.compose.ui.RecyclerViewActivity" />
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
index 81fa463..de0a2d9 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
@@ -1305,12 +1305,13 @@
             ++alignmentLinesCalculations
             0
         }
+        var linePosition by mutableStateOf(10)
         activityTestRule.runOnUiThreadIR {
             activity.setContent {
                 val innerChild = @Composable {
                     offset.value // Artificial remeasure.
                     Layout(content = {}) { _, _ ->
-                        layout(0, 0, mapOf(TestLine to 10)) { }
+                        layout(0, 0, mapOf(TestLine to linePosition)) { }
                     }
                 }
                 val child = @Composable {
@@ -1340,12 +1341,12 @@
         assertEquals(1, alignmentLinesCalculations)
 
         layoutLatch = CountDownLatch(1)
-        activityTestRule.runOnUiThreadIR { offset.value = 20 }
+        activityTestRule.runOnUiThreadIR { offset.value = 20; linePosition = 20 }
         assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
         assertEquals(1, alignmentLinesCalculations)
 
         layoutLatch = CountDownLatch(1)
-        activityTestRule.runOnUiThreadIR { offset.value = 10 }
+        activityTestRule.runOnUiThreadIR { offset.value = 10; linePosition = 30 }
         assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
         assertEquals(2, alignmentLinesCalculations)
     }
@@ -1473,26 +1474,44 @@
             }
         }
         assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
-        // Two layouts as the alignment line was only queried after the child was placed.
-        assertEquals(2, childLayouts)
+        assertEquals(1, childLayouts)
     }
 
     @Test
     fun testAlignmentLines_whenQueriedAfterPlacing_haveCorrectNumberOfLayouts() {
-        val TestLine = VerticalAlignmentLine(::min)
-        var layoutLatch = CountDownLatch(1)
         var childLayouts = 0
+        var childAlignmentLinesCalculations = 0
+        val TestLine = VerticalAlignmentLine { v1, _ ->
+            ++childAlignmentLinesCalculations
+            v1
+        }
         val offset = mutableStateOf(10)
+        var linePositionState by mutableStateOf(10)
+        var linePosition = 10
+        fun changeLinePosition() {
+            linePosition = 30 - linePosition
+            linePositionState = 30 - linePositionState
+        }
+        var layoutLatch = CountDownLatch(1)
         activityTestRule.runOnUiThreadIR {
             activity.setContent {
-                val child = @Composable {
+                val childChild = @Composable {
                     Layout(content = {}) { _, constraints ->
                         layout(
                             constraints.minWidth,
                             constraints.minHeight,
-                            mapOf(TestLine to 10)
+                            mapOf(TestLine to linePositionState)
                         ) {
                             offset.value // To ensure relayout.
+                        }
+                    }
+                }
+                val child = @Composable {
+                    Layout(content = { childChild(); childChild() }) { measurables, constraints ->
+                        val placeables = measurables.map { it.measure(constraints) }
+                        layout(constraints.minWidth, constraints.minHeight) {
+                            offset.value // To ensure relayout.
+                            placeables.forEach { it.place(0, 0) }
                             ++childLayouts
                         }
                     }
@@ -1503,9 +1522,9 @@
                     }) { measurables, constraints ->
                         val placeable = measurables[0].measure(constraints)
                         layout(placeable.width, placeable.height) {
-                            if (offset.value > 15) assertEquals(10, placeable[TestLine])
+                            if (offset.value > 15) assertEquals(linePosition, placeable[TestLine])
                             placeable.place(0, 0)
-                            if (offset.value > 5) assertEquals(10, placeable[TestLine])
+                            if (offset.value > 5) assertEquals(linePosition, placeable[TestLine])
                         }
                     }
                 }
@@ -1522,37 +1541,42 @@
             }
         }
         assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
-        // Two layouts as the alignment line was only queried after the child was placed.
-        assertEquals(2, childLayouts)
-
-        layoutLatch = CountDownLatch(1)
-        activityTestRule.runOnUiThreadIR { offset.value = 12 }
-        assertTrue(layoutLatch.await(5, TimeUnit.SECONDS))
-        // Just one more layout as the alignment lines were speculatively calculated this time.
-        assertEquals(3, childLayouts)
-
-        layoutLatch = CountDownLatch(1)
-        activityTestRule.runOnUiThreadIR { offset.value = 17 }
-        assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
-        // One layout as the alignment lines are queried before.
-        assertEquals(4, childLayouts)
-
-        layoutLatch = CountDownLatch(1)
-        activityTestRule.runOnUiThreadIR { offset.value = 12 }
-        assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
-        // One layout as the alignment lines are still calculated speculatively.
-        assertEquals(5, childLayouts)
+        assertEquals(2, childLayouts + childAlignmentLinesCalculations)
 
         layoutLatch = CountDownLatch(1)
         activityTestRule.runOnUiThreadIR { offset.value = 1 }
         assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
-        assertEquals(6, childLayouts)
+        assertEquals(3, childLayouts + childAlignmentLinesCalculations)
+
         layoutLatch = CountDownLatch(1)
-        activityTestRule.runOnUiThreadIR { offset.value = 10 }
+        activityTestRule.runOnUiThreadIR { offset.value = 10; changeLinePosition() }
         assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
-        // Two layouts again, since alignment lines were not queried during last layout,
-        // so we did not calculate them speculatively anymore.
-        assertEquals(8, childLayouts)
+        assertEquals(5, childLayouts + childAlignmentLinesCalculations)
+
+        layoutLatch = CountDownLatch(1)
+        activityTestRule.runOnUiThreadIR { offset.value = 12; changeLinePosition() }
+        assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
+        assertEquals(7, childLayouts + childAlignmentLinesCalculations)
+
+        layoutLatch = CountDownLatch(1)
+        activityTestRule.runOnUiThreadIR { offset.value = 17; changeLinePosition() }
+        assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
+        assertEquals(9, childLayouts + childAlignmentLinesCalculations)
+
+        layoutLatch = CountDownLatch(1)
+        activityTestRule.runOnUiThreadIR { offset.value = 12; changeLinePosition() }
+        assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
+        assertEquals(11, childLayouts + childAlignmentLinesCalculations)
+
+        layoutLatch = CountDownLatch(1)
+        activityTestRule.runOnUiThreadIR { offset.value = 1; changeLinePosition() }
+        assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
+        assertEquals(13, childLayouts + childAlignmentLinesCalculations)
+
+        layoutLatch = CountDownLatch(1)
+        activityTestRule.runOnUiThreadIR { offset.value = 10; changeLinePosition() }
+        assertTrue(layoutLatch.await(1, TimeUnit.SECONDS))
+        assertEquals(15, childLayouts + childAlignmentLinesCalculations)
     }
 
     @Test
@@ -1632,7 +1656,7 @@
         testHorizontalLine: HorizontalAlignmentLine,
         assertLines: Modifier.(Int, Int) -> Modifier
     ) {
-        val layoutLatch = CountDownLatch(7)
+        val layoutLatch = CountDownLatch(1)
         activityTestRule.runOnUiThreadIR {
             activity.setContent {
                 val layout = @Composable { modifier: Modifier ->
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/EditorInfoTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/EditorInfoTest.kt
new file mode 100644
index 0000000..5894e49
--- /dev/null
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/EditorInfoTest.kt
@@ -0,0 +1,523 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.input
+
+import android.text.InputType
+import android.view.inputmethod.EditorInfo
+import androidx.compose.ui.text.TextRange
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.ImeOptions
+import androidx.compose.ui.text.input.KeyboardCapitalization
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.text.input.TextFieldValue
+import androidx.compose.ui.text.input.update
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class EditorInfoTest {
+
+    @Test
+    fun test_fill_editor_info_text() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Text,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_ascii() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_number() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Number,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_NUMBER and info.inputType) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_phone() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Phone,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_PHONE and info.inputType) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_uri() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Uri,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_VARIATION_URI and info.inputType) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_email() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Email,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS and info.inputType) != 0)
+            .isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_password() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Password,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_VARIATION_PASSWORD and info.inputType) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_number_password() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.NumberPassword,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_NUMBER and info.inputType) != 0).isTrue()
+        assertThat((InputType.TYPE_NUMBER_VARIATION_PASSWORD and info.inputType) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_UNSPECIFIED
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_none() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.None
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_NONE
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_go() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Go
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_GO
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_next() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Next
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_NEXT
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_previous() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Previous
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_PREVIOUS
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_search() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Search,
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_SEARCH
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_send() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Send
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_SEND
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_action_done() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
+        assertThat(
+            (EditorInfo.IME_MASK_ACTION and info.imeOptions)
+                == EditorInfo.IME_ACTION_DONE
+        ).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_multi_line() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                singleLine = false,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_MULTI_LINE and info.inputType) == 0).isFalse()
+        assertThat((EditorInfo.IME_FLAG_NO_ENTER_ACTION and info.imeOptions) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_multi_line_with_default_action() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                singleLine = false,
+                keyboardType = KeyboardType.Text,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_MULTI_LINE and info.inputType) == 0).isFalse()
+        assertThat((EditorInfo.IME_FLAG_NO_ENTER_ACTION and info.imeOptions) == 0).isFalse()
+    }
+
+    @Test
+    fun test_fill_editor_info_single_line() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                singleLine = true,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_MULTI_LINE and info.inputType) == 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_NO_ENTER_ACTION and info.imeOptions) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_single_line_changes_ime_from_unspecified_to_done() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                singleLine = true,
+                keyboardType = KeyboardType.Text,
+                imeAction = ImeAction.Default
+            )
+        )
+
+        assertThat((EditorInfo.IME_ACTION_DONE and info.imeOptions) == 0).isFalse()
+        assertThat((EditorInfo.IME_ACTION_UNSPECIFIED and info.imeOptions) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_multi_line_not_set_when_input_type_is_not_text() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                singleLine = false,
+                keyboardType = KeyboardType.Number,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_MULTI_LINE and info.inputType) == 0).isTrue()
+        assertThat((EditorInfo.IME_FLAG_NO_ENTER_ACTION and info.imeOptions) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_capitalization_none() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                capitalization = KeyboardCapitalization.None,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_capitalization_characters() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                capitalization = KeyboardCapitalization.Characters,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isFalse()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_capitalization_words() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                capitalization = KeyboardCapitalization.Words,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isFalse()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_capitalization_sentences() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                capitalization = KeyboardCapitalization.Sentences,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done,
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isFalse()
+    }
+
+    @Test
+    fun test_fill_editor_info_capitalization_not_added_when_input_type_is_not_text() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                capitalization = KeyboardCapitalization.Sentences,
+                keyboardType = KeyboardType.Number,
+                imeAction = ImeAction.Done,
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isTrue()
+        assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isTrue()
+    }
+
+    @Test
+    fun test_fill_editor_info_auto_correct_on() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                autoCorrect = true,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_AUTO_CORRECT and info.inputType) == 0).isFalse()
+    }
+
+    @Test
+    fun test_fill_editor_info_auto_correct_off() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                autoCorrect = false,
+                keyboardType = KeyboardType.Ascii,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_AUTO_CORRECT and info.inputType) == 0).isTrue()
+    }
+
+    @Test
+    fun autocorrect_not_added_when_input_type_is_not_text() {
+        val info = EditorInfo()
+        info.update(
+            ImeOptions(
+                autoCorrect = true,
+                keyboardType = KeyboardType.Number,
+                imeAction = ImeAction.Done
+            )
+        )
+
+        assertThat((InputType.TYPE_TEXT_FLAG_AUTO_CORRECT and info.inputType) == 0).isTrue()
+    }
+
+    @Test
+    fun initial_default_selection_info_is_set() {
+        val info = EditorInfo()
+        info.update(ImeOptions.Default)
+
+        assertThat(info.initialSelStart).isEqualTo(0)
+        assertThat(info.initialSelEnd).isEqualTo(0)
+    }
+
+    @Test
+    fun initial_selection_info_is_set() {
+        val selection = TextRange(1, 2)
+        val info = EditorInfo()
+        info.update(ImeOptions.Default, TextFieldValue("abc", selection))
+
+        assertThat(info.initialSelStart).isEqualTo(selection.start)
+        assertThat(info.initialSelEnd).isEqualTo(selection.end)
+    }
+
+    private fun EditorInfo.update(imeOptions: ImeOptions) {
+        this.update(imeOptions, TextFieldValue())
+    }
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/TextInputServiceAndroidOnStateUpdateTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/TextInputServiceAndroidOnStateUpdateTest.kt
similarity index 74%
rename from compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/TextInputServiceAndroidOnStateUpdateTest.kt
rename to compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/TextInputServiceAndroidOnStateUpdateTest.kt
index a43182af..25ba030 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/TextInputServiceAndroidOnStateUpdateTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/TextInputServiceAndroidOnStateUpdateTest.kt
@@ -16,43 +16,42 @@
 
 package androidx.compose.ui.input
 
-import android.content.Context
 import android.view.View
 import android.view.inputmethod.EditorInfo
-import android.view.inputmethod.InputMethodManager
 import androidx.compose.ui.text.TextRange
 import androidx.compose.ui.text.input.ImeOptions
+import androidx.compose.ui.text.input.InputMethodManager
 import androidx.compose.ui.text.input.RecordingInputConnection
 import androidx.compose.ui.text.input.TextFieldValue
 import androidx.compose.ui.text.input.TextInputServiceAndroid
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
 import com.google.common.truth.Truth.assertThat
 import com.nhaarman.mockitokotlin2.any
-import com.nhaarman.mockitokotlin2.eq
 import com.nhaarman.mockitokotlin2.mock
 import com.nhaarman.mockitokotlin2.never
 import com.nhaarman.mockitokotlin2.times
 import com.nhaarman.mockitokotlin2.verify
-import com.nhaarman.mockitokotlin2.whenever
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
 
-@RunWith(JUnit4::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
 class TextInputServiceAndroidOnStateUpdateTest {
 
     private lateinit var textInputService: TextInputServiceAndroid
-    private lateinit var imm: InputMethodManager
+    private lateinit var inputMethodManager: InputMethodManager
     private lateinit var inputConnection: RecordingInputConnection
 
     @Before
     fun setup() {
-        imm = mock()
-        val view: View = mock()
-        val context: Context = mock()
-        whenever(context.getSystemService(eq(Context.INPUT_METHOD_SERVICE))).thenReturn(imm)
-        whenever(view.context).thenReturn(context)
-        textInputService = TextInputServiceAndroid(view)
+        val view = View(InstrumentationRegistry.getInstrumentation().context)
+        inputMethodManager = mock()
+        textInputService = TextInputServiceAndroid(view, mock())
+
+        textInputService = TextInputServiceAndroid(view, inputMethodManager)
         textInputService.startInput(
             value = TextFieldValue(""),
             imeOptions = ImeOptions.Default,
@@ -71,8 +70,8 @@
             newValue = newValue
         )
 
-        verify(imm, times(1)).restartInput(any())
-        verify(imm, never()).updateSelection(any(), any(), any(), any(), any())
+        verify(inputMethodManager, times(1)).restartInput(any())
+        verify(inputMethodManager, never()).updateSelection(any(), any(), any(), any(), any())
 
         assertThat(inputConnection.mTextFieldValue).isEqualTo(newValue)
         assertThat(textInputService.state).isEqualTo(newValue)
@@ -86,8 +85,8 @@
             newValue = newValue
         )
 
-        verify(imm, times(1)).restartInput(any())
-        verify(imm, never()).updateSelection(any(), any(), any(), any(), any())
+        verify(inputMethodManager, times(1)).restartInput(any())
+        verify(inputMethodManager, never()).updateSelection(any(), any(), any(), any(), any())
 
         assertThat(inputConnection.mTextFieldValue).isEqualTo(newValue)
         assertThat(textInputService.state).isEqualTo(newValue)
@@ -101,8 +100,8 @@
             newValue = newValue
         )
 
-        verify(imm, never()).restartInput(any())
-        verify(imm, times(1)).updateSelection(any(), any(), any(), any(), any())
+        verify(inputMethodManager, never()).restartInput(any())
+        verify(inputMethodManager, times(1)).updateSelection(any(), any(), any(), any(), any())
 
         assertThat(inputConnection.mTextFieldValue).isEqualTo(newValue)
         assertThat(textInputService.state).isEqualTo(newValue)
@@ -116,8 +115,8 @@
             newValue = newValue
         )
 
-        verify(imm, never()).restartInput(any())
-        verify(imm, times(1)).updateSelection(any(), any(), any(), any(), any())
+        verify(inputMethodManager, never()).restartInput(any())
+        verify(inputMethodManager, times(1)).updateSelection(any(), any(), any(), any(), any())
 
         assertThat(inputConnection.mTextFieldValue).isEqualTo(newValue)
         assertThat(textInputService.state).isEqualTo(newValue)
@@ -131,8 +130,8 @@
             newValue = value
         )
 
-        verify(imm, never()).restartInput(any())
-        verify(imm, never()).updateSelection(any(), any(), any(), any(), any())
+        verify(inputMethodManager, never()).restartInput(any())
+        verify(inputMethodManager, never()).updateSelection(any(), any(), any(), any(), any())
 
         assertThat(inputConnection.mTextFieldValue).isEqualTo(value)
         assertThat(textInputService.state).isEqualTo(value)
@@ -146,8 +145,8 @@
             newValue = value
         )
 
-        verify(imm, never()).restartInput(any())
-        verify(imm, never()).updateSelection(any(), any(), any(), any(), any())
+        verify(inputMethodManager, never()).restartInput(any())
+        verify(inputMethodManager, never()).updateSelection(any(), any(), any(), any(), any())
 
         // recreate the connection
         inputConnection = textInputService.createInputConnection(EditorInfo())
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/AlignmentLineTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/AlignmentLineTest.kt
index 81b70cd..9c76455 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/AlignmentLineTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/AlignmentLineTest.kt
@@ -18,11 +18,18 @@
 
 import androidx.activity.ComponentActivity
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.offset
 import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.layout.size
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateMapOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.test.junit4.createAndroidComposeRule
 import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.IntOffset
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import org.junit.Assert.assertEquals
@@ -126,4 +133,1166 @@
         }
         rule.waitForIdle()
     }
+
+    @Test
+    fun alignmentLinesArePropagated_whenSuppliedViaModifier() {
+        val size = 50
+        val sizeDp = with(rule.density) { size.toDp() }
+        val linePosition = 25
+        val hLine = HorizontalAlignmentLine(::min)
+        val vLine = VerticalAlignmentLine(::min)
+        rule.setContent {
+            val content = @Composable {
+                Box(Modifier.size(sizeDp)) {
+                    Box(
+                        Modifier.supplyAlignmentLines {
+                            mapOf(
+                                hLine to linePosition,
+                                vLine to linePosition
+                            )
+                        }.size(sizeDp)
+                    )
+                }
+            }
+
+            Layout(content) { measurables, constraints ->
+                val placeable = measurables.first().measure(constraints)
+                assertEquals(linePosition, placeable[hLine])
+                assertEquals(linePosition, placeable[vLine])
+                layout(0, 0) {}
+            }
+        }
+    }
+
+    @Test
+    fun alignmentLinesArePropagated_whenSuppliedViaModifier_withCorrectPosition() {
+        val size = 50
+        val sizeDp = with(rule.density) { size.toDp() }
+        val offset = 10
+        val offsetDp = with(rule.density) { offset.toDp() }
+        val linePosition = 25
+        val hLine = HorizontalAlignmentLine(::min)
+        val vLine = VerticalAlignmentLine(::min)
+        rule.setContent {
+            val content = @Composable {
+                Box(Modifier.size(sizeDp)) {
+                    Box(
+                        Modifier.offset(offsetDp, offsetDp)
+                            .supplyAlignmentLines {
+                                mapOf(
+                                    hLine to linePosition,
+                                    vLine to linePosition
+                                )
+                            }.size(sizeDp)
+                            .offset(offsetDp, offsetDp)
+                    )
+                }
+            }
+
+            Layout(content) { measurables, constraints ->
+                val placeable = measurables.first().measure(constraints)
+                assertEquals(linePosition + offset, placeable[hLine])
+                assertEquals(linePosition + offset, placeable[vLine])
+                layout(0, 0) {}
+            }
+        }
+    }
+
+    @Test
+    fun alignmentLinesChangeCausesRemeasure_whenSuppliedViaModifier() {
+        val size = 50
+        val sizeDp = with(rule.density) { size.toDp() }
+        val offset = 10
+        val linePosition = 25
+        val hLine = HorizontalAlignmentLine(::min)
+        val vLine = VerticalAlignmentLine(::min)
+        val alignmentLines = mutableStateMapOf(hLine to linePosition, vLine to linePosition)
+        var obtainedHLinePosition = -1
+        var obtainedVLinePosition = -1
+        rule.setContent {
+            val content = @Composable {
+                Box(Modifier.size(sizeDp)) {
+                    Box(Modifier.supplyAlignmentLines { alignmentLines.toMap() }.size(sizeDp))
+                }
+            }
+
+            Layout(content) { measurables, constraints ->
+                val placeable = measurables.first().measure(constraints)
+                obtainedHLinePosition = placeable[hLine]
+                obtainedVLinePosition = placeable[vLine]
+                layout(0, 0) {}
+            }
+        }
+
+        rule.runOnIdle {
+            assertEquals(linePosition, obtainedHLinePosition)
+            assertEquals(linePosition, obtainedVLinePosition)
+            alignmentLines[hLine] = linePosition + offset
+            alignmentLines[vLine] = linePosition + offset
+        }
+
+        rule.runOnIdle {
+            assertEquals(linePosition + offset, obtainedHLinePosition)
+            assertEquals(linePosition + offset, obtainedVLinePosition)
+        }
+    }
+
+    @Test
+    fun alignmentLinesChangeCausesRemeasure_whenSuppliedViaLayout() {
+        val size = 50
+        val sizeDp = with(rule.density) { size.toDp() }
+        val offset = 10
+        val linePosition = 25
+        val hLine = HorizontalAlignmentLine(::min)
+        val vLine = VerticalAlignmentLine(::min)
+        val alignmentLines = mutableStateMapOf(hLine to linePosition, vLine to linePosition)
+        var obtainedHLinePosition = -1
+        var obtainedVLinePosition = -1
+        rule.setContent {
+            val content = @Composable {
+                val innerContent = @Composable {
+                    Layout({}) { _, _ ->
+                        layout(size, size, alignmentLines) {}
+                    }
+                }
+                Layout(content = innerContent, Modifier.size(sizeDp)) { measurables, constraints ->
+                    val placeable = measurables.first().measure(constraints)
+                    layout(constraints.maxWidth, constraints.maxHeight) {
+                        placeable.place(0, 0)
+                    }
+                }
+            }
+
+            Layout(content) { measurables, constraints ->
+                val placeable = measurables.first().measure(constraints)
+                obtainedHLinePosition = placeable[hLine]
+                obtainedVLinePosition = placeable[vLine]
+                layout(0, 0) {}
+            }
+        }
+
+        rule.runOnIdle {
+            assertEquals(linePosition, obtainedHLinePosition)
+            assertEquals(linePosition, obtainedVLinePosition)
+            alignmentLines[hLine] = linePosition + offset
+            alignmentLines[vLine] = linePosition + offset
+        }
+
+        rule.runOnIdle {
+            assertEquals(linePosition + offset, obtainedHLinePosition)
+            assertEquals(linePosition + offset, obtainedVLinePosition)
+        }
+    }
+
+    @Test
+    fun scenario1() {
+        var parentMeasures = 0
+        var measures = 0
+        rule.setContent {
+            Parent(onMeasure = { ++parentMeasures }) {
+                Parent(onMeasure = { ++measures }, readDuringMeasure = true) {
+                    Parent {
+                        Provider()
+                    }
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, measures)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(2, measures)
+        }
+    }
+
+    @Test
+    fun scenario2() {
+        var parentLayouts = 0
+        var measures = 0
+        var layouts = 0
+        rule.setContent {
+            Parent(onLayout = { ++parentLayouts }) {
+                Parent(
+                    onMeasure = { ++measures },
+                    onLayout = { ++layouts },
+                    readDuringLayoutBeforePlacing = true
+                ) {
+                    Parent {
+                        Provider()
+                    }
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentLayouts)
+            assertEquals(1, measures)
+            assertEquals(1, layouts)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, parentLayouts)
+            assertEquals(1, measures)
+            assertEquals(2, layouts)
+        }
+    }
+
+    @Test
+    fun scenario3() {
+        var parentLayouts = 0
+        var measures = 0
+        var layouts = 0
+        rule.setContent {
+            Parent(onLayout = { ++parentLayouts }) {
+                Parent(
+                    onMeasure = { ++measures },
+                    onLayout = { ++layouts },
+                    readDuringLayoutAfterPlacing = true
+                ) {
+                    Parent {
+                        Provider()
+                    }
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentLayouts)
+            assertEquals(1, measures)
+            assertEquals(1, layouts)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, parentLayouts)
+            assertEquals(1, measures)
+            assertEquals(2, layouts)
+        }
+    }
+
+    @Test
+    fun scenario4() {
+        var parentMeasures = 0
+        var parentLayouts = 0
+        var measures = 0
+        var layouts = 0
+        rule.setContent {
+            Parent(
+                onMeasure = { ++parentMeasures },
+                onLayout = { ++parentLayouts },
+                readDuringMeasure = true
+            ) {
+                Parent(
+                    onMeasure = { ++measures },
+                    onLayout = { ++layouts },
+                    readDuringLayoutBeforePlacing = true
+                ) {
+                    Parent {
+                        Provider()
+                    }
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, parentLayouts)
+            assertEquals(1, measures)
+            assertEquals(1, layouts)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(2, parentMeasures)
+            assertEquals(2, parentLayouts)
+            assertEquals(1, measures)
+            assertEquals(2, layouts)
+        }
+    }
+
+    @Test
+    fun scenario5() {
+        var parentMeasures = 0
+        var parentLayouts = 0
+        var measures = 0
+        var layouts = 0
+        rule.setContent {
+            Parent(
+                onMeasure = { ++parentMeasures },
+                onLayout = { ++parentLayouts },
+                readDuringMeasure = true
+            ) {
+                Parent(
+                    onMeasure = { ++measures },
+                    onLayout = { ++layouts },
+                    readDuringLayoutAfterPlacing = true
+                ) {
+                    Parent {
+                        Provider()
+                    }
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, parentLayouts)
+            assertEquals(1, measures)
+            assertEquals(1, layouts)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(2, parentMeasures)
+            assertEquals(2, parentLayouts)
+            assertEquals(1, measures)
+            assertEquals(2, layouts)
+        }
+    }
+
+    @Test
+    fun scenario6() {
+        var parentMeasures = 0
+        var parentLayouts = 0
+        var measures = 0
+        var layouts = 0
+        rule.setContent {
+            Parent(
+                onMeasure = { ++parentMeasures },
+                onLayout = { ++parentLayouts },
+                readDuringLayoutAfterPlacing = true
+            ) {
+                Parent(
+                    onMeasure = { ++measures },
+                    onLayout = { ++layouts },
+                    readDuringMeasure = true
+                ) {
+                    Parent {
+                        Provider()
+                    }
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, parentLayouts)
+            assertEquals(1, measures)
+            assertEquals(1, layouts)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(2, parentLayouts)
+            assertEquals(2, measures)
+            assertEquals(2, layouts)
+        }
+    }
+
+    @Test
+    fun scenario7() {
+        var parentMeasures = 0
+        var measures = 0
+        var layouts = 0
+        var childMeasures = 0
+        rule.setContent {
+            Parent(onMeasure = { ++parentMeasures }) {
+                Parent(
+                    onMeasure = { ++measures },
+                    onLayout = { ++layouts },
+                    readDuringMeasure = true
+                ) {
+                    Parent(modifier = Modifier.provider(), onMeasure = { ++childMeasures }) {
+                        Parent()
+                    }
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, measures)
+            assertEquals(1, layouts)
+            assertEquals(1, childMeasures)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(2, measures)
+            assertEquals(2, layouts)
+            assertEquals(2, childMeasures)
+        }
+    }
+
+    @Test
+    fun scenario8() {
+        var parentMeasures = 0
+        var measures = 0
+        var layouts = 0
+        var childMeasures = 0
+        rule.setContent {
+            Parent(onMeasure = { ++parentMeasures }) {
+                Parent(
+                    onMeasure = { ++measures },
+                    onLayout = { ++layouts },
+                    readDuringLayoutBeforePlacing = true
+                ) {
+                    Parent(modifier = Modifier.provider(), onMeasure = { ++childMeasures }) {
+                        Parent()
+                    }
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, measures)
+            assertEquals(1, layouts)
+            assertEquals(1, childMeasures)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, measures)
+            assertEquals(2, layouts)
+            assertEquals(2, childMeasures)
+        }
+    }
+
+    @Test
+    fun scenario9() {
+        var parentMeasures = 0
+        var measures = 0
+        var layouts = 0
+        var childMeasures = 0
+        rule.setContent {
+            Parent(onMeasure = { ++parentMeasures }) {
+                Parent(
+                    onMeasure = { ++measures },
+                    onLayout = { ++layouts },
+                    readDuringLayoutAfterPlacing = true
+                ) {
+                    Parent(modifier = Modifier.provider(), onMeasure = { ++childMeasures }) {
+                        Parent()
+                    }
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, measures)
+            assertEquals(1, layouts)
+            assertEquals(1, childMeasures)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, measures)
+            assertEquals(2, layouts)
+            assertEquals(2, childMeasures)
+        }
+    }
+
+    @Test
+    fun scenario10() {
+        var parentMeasures = 0
+        var measures = 0
+        var layouts = 0
+        var childMeasures = 0
+        rule.setContent {
+            Parent(onMeasure = { ++parentMeasures }, readDuringMeasure = true) {
+                Parent(
+                    onMeasure = { ++measures },
+                    onLayout = { ++layouts },
+                    readDuringLayoutAfterPlacing = true
+                ) {
+                    Parent(modifier = Modifier.provider(), onMeasure = { ++childMeasures }) {
+                        Parent()
+                    }
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, measures)
+            assertEquals(1, layouts)
+            assertEquals(1, childMeasures)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(2, parentMeasures)
+            assertEquals(1, measures)
+            assertEquals(2, layouts)
+            assertEquals(2, childMeasures)
+        }
+    }
+
+    @Test
+    fun scenario11() {
+        var measures = 0
+        var layouts = 0
+        var childMeasures = 0
+        rule.setContent {
+            Parent {
+                Parent(
+                    onMeasure = { ++measures },
+                    onLayout = { ++layouts },
+                    readDuringLayoutAfterPlacing = true
+                ) {
+                    Parent(
+                        modifier = Modifier.reader(readDuringMeasure = true),
+                        onMeasure = { ++childMeasures }
+                    ) {
+                        Provider()
+                    }
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, measures)
+            assertEquals(1, layouts)
+            assertEquals(1, childMeasures)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, measures)
+            assertEquals(2, layouts)
+            assertEquals(2, childMeasures)
+        }
+    }
+
+    @Test
+    fun scenario12() {
+        var childMeasures = 0
+        rule.setContent {
+            Parent {
+                Provider(
+                    modifier = Modifier.reader(readDuringMeasure = true),
+                    onMeasure = { ++childMeasures }
+                )
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, childMeasures)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(2, childMeasures)
+        }
+    }
+
+    @Test
+    fun scenario13() {
+        var measures = 0
+        var childMeasures = 0
+        var childLayouts = 0
+        rule.setContent {
+            Parent(onMeasure = { ++measures }) {
+                Provider(
+                    modifier = Modifier.reader(readDuringLayoutBeforePlacing = true),
+                    onMeasure = { ++childMeasures },
+                    onLayout = { ++childLayouts }
+                )
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, measures)
+            assertEquals(1, childMeasures)
+            assertEquals(1, childLayouts)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, measures)
+            assertEquals(2, childMeasures)
+            assertEquals(2, childLayouts)
+        }
+    }
+
+    @Test
+    fun scenario14() {
+        var measures = 0
+        var childMeasures = 0
+        var childLayouts = 0
+        rule.setContent {
+            Parent(onMeasure = { ++measures }) {
+                Provider(
+                    modifier = Modifier.reader(readDuringLayoutAfterPlacing = true),
+                    onMeasure = { ++childMeasures },
+                    onLayout = { ++childLayouts }
+                )
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, measures)
+            assertEquals(1, childMeasures)
+            assertEquals(1, childLayouts)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, measures)
+            assertEquals(2, childMeasures)
+            assertEquals(2, childLayouts)
+        }
+    }
+
+    @Test
+    fun scenario15() {
+        var parentMeasures = 0
+        var measures = 0
+        var childMeasures = 0
+        rule.setContent {
+            Parent(onMeasure = { ++parentMeasures }) {
+                Parent(
+                    modifier = Modifier.reader(readDuringMeasure = true).provider(),
+                    onMeasure = { ++measures }
+                ) {
+                    Parent(onMeasure = { ++childMeasures })
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, measures)
+            assertEquals(1, childMeasures)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(2, measures)
+            assertEquals(1, childMeasures)
+        }
+    }
+
+    @Test
+    fun scenario16() {
+        var parentMeasures = 0
+        var measures = 0
+        var childMeasures = 0
+        rule.setContent {
+            Parent(onMeasure = { ++parentMeasures }, readDuringMeasure = true) {
+                Parent(
+                    modifier = Modifier.reader(readDuringMeasure = true).provider(),
+                    onMeasure = { ++measures }
+                ) {
+                    Parent(onMeasure = { ++childMeasures })
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, measures)
+            assertEquals(1, childMeasures)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(2, parentMeasures)
+            assertEquals(2, measures)
+            assertEquals(1, childMeasures)
+        }
+    }
+
+    @Test
+    fun scenario17() {
+        var parentMeasures = 0
+        var measures = 0
+        var childMeasures = 0
+        var read by mutableStateOf(true)
+        rule.setContent {
+            Parent(onMeasure = { ++parentMeasures }, readDuringMeasure = true) {
+                ChangingParent(
+                    onMeasure = { ++measures },
+                    readDuringMeasure = { read }
+                ) {
+                    Parent(onMeasure = { ++childMeasures }) {
+                        Provider()
+                    }
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, measures)
+            assertEquals(1, childMeasures)
+            changeLinePosition()
+            read = false
+        }
+
+        rule.runOnIdle {
+            assertEquals(2, parentMeasures)
+            assertEquals(2, measures)
+            assertEquals(1, childMeasures)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(3, parentMeasures)
+            assertEquals(2, measures)
+            assertEquals(1, childMeasures)
+        }
+    }
+
+    @Test
+    fun scenario18() {
+        var parentLayouts = 0
+        var parentMeasures = 0
+        var measures = 0
+        var childMeasures = 0
+        var read by mutableStateOf(true)
+        rule.setContent {
+            Parent(
+                onMeasure = { ++parentMeasures },
+                onLayout = { ++parentLayouts },
+                readDuringLayoutAfterPlacing = true
+            ) {
+                ChangingParent(
+                    onMeasure = { ++measures },
+                    readDuringMeasure = { read }
+                ) {
+                    Parent(onMeasure = { ++childMeasures }) {
+                        Provider()
+                    }
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(1, parentLayouts)
+            assertEquals(1, measures)
+            assertEquals(1, childMeasures)
+            changeLinePosition()
+            read = false
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(2, parentLayouts)
+            assertEquals(2, measures)
+            assertEquals(1, childMeasures)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, parentMeasures)
+            assertEquals(3, parentLayouts)
+            assertEquals(2, measures)
+            assertEquals(1, childMeasures)
+        }
+    }
+
+    @Test
+    fun scenario19() {
+        var offset by mutableStateOf(IntOffset.Zero)
+        rule.setContent {
+            Parent(readDuringLayoutBeforePlacing = true) {
+                Provider(modifier = Modifier.offset { offset })
+            }
+        }
+        rule.runOnIdle {
+            offset = IntOffset(10, 10)
+            linePosition += 10
+        }
+
+        rule.waitForIdle()
+    }
+
+    @Test
+    fun scenario20() {
+        var parentLayouts = 0
+        var offset by mutableStateOf(IntOffset.Zero)
+        rule.setContent {
+            Parent(readDuringLayoutBeforePlacing = true, onLayout = { ++parentLayouts }) {
+                Parent {
+                    Provider(modifier = Modifier.offset { offset })
+                }
+            }
+        }
+        rule.runOnIdle {
+            offset = IntOffset(10, 10)
+            linePosition += 10
+        }
+
+        rule.runOnIdle {
+            assertEquals(2, parentLayouts)
+        }
+
+        rule.waitForIdle()
+    }
+
+    @Test
+    fun scenario21() {
+        var parentMeasures = 0
+        var read by mutableStateOf(false)
+        rule.setContent {
+            ChangingParent(
+                readDuringMeasure = { read },
+                onMeasure = { ++parentMeasures }
+            ) {
+                Parent {
+                    Provider()
+                }
+            }
+        }
+        rule.runOnIdle {
+            read = true
+        }
+
+        rule.runOnIdle {
+            assertEquals(2, parentMeasures)
+        }
+    }
+
+    @Test
+    fun scenario22() {
+        var parentLayouts = 0
+        var read by mutableStateOf(false)
+        rule.setContent {
+            ChangingParent(
+                readDuringLayoutBeforePlacing = { read },
+                onLayout = { ++parentLayouts }
+            ) {
+                Parent {
+                    Provider()
+                }
+            }
+        }
+        rule.runOnIdle {
+            read = true
+        }
+
+        rule.runOnIdle {
+            assertEquals(2, parentLayouts)
+        }
+    }
+
+    @Test
+    fun scenario23() {
+        var obtainedPosition = 0
+        var changingState by mutableStateOf(false)
+        rule.setContent {
+            Layout(
+                content = {
+                    Parent {
+                        Provider()
+                    }
+                }
+            ) { measurables, constraints ->
+                val placeable = measurables.first().measure(constraints)
+                layout(constraints.maxWidth, constraints.maxHeight) {
+                    if (changingState) require(true)
+                    obtainedPosition = placeable[TestLine]
+                    placeable.place(0, 0)
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(linePosition, obtainedPosition)
+            changeLinePosition()
+            changingState = true
+        }
+
+        rule.runOnIdle {
+            assertEquals(linePosition, obtainedPosition)
+        }
+    }
+
+    @Test
+    fun scenario24() {
+        var obtainedPosition = 0
+        var changingState by mutableStateOf(false)
+        rule.setContent {
+            Layout(
+                content = {
+                    Parent {
+                        Provider()
+                    }
+                }
+            ) { measurables, constraints ->
+                val placeable = measurables.first().measure(constraints)
+                layout(constraints.maxWidth, constraints.maxHeight) {
+                    if (changingState) require(true)
+                    placeable.place(0, 0)
+                    obtainedPosition = placeable[TestLine]
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(linePosition, obtainedPosition)
+            changeLinePosition()
+            changingState = true
+        }
+
+        rule.runOnIdle {
+            assertEquals(linePosition, obtainedPosition)
+        }
+    }
+
+    @Test
+    fun scenario25() {
+        var obtainedPosition = 0
+        rule.setContent {
+            Parent(modifier = Modifier.onGloballyPositioned { obtainedPosition = it[TestLine] }) {
+                Parent {
+                    Provider()
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(linePosition, obtainedPosition)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(linePosition, obtainedPosition)
+        }
+    }
+
+    @Test
+    fun scenario26() {
+        var measures = 0
+        var layouts = 0
+        rule.setContent {
+            Parent(
+                modifier = Modifier.reader(
+                    readDuringMeasure = true,
+                    readDuringLayoutBeforePlacing = true,
+                    onMeasure = { ++measures },
+                    onLayout = { ++layouts }
+                )
+            ) {
+                Parent {
+                    Provider()
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, measures)
+            assertEquals(1, layouts)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(2, measures)
+            assertEquals(2, layouts)
+        }
+    }
+
+    @Test
+    fun scenario27() {
+        var measures = 0
+        var layouts = 0
+        rule.setContent {
+            Parent(
+                modifier = Modifier.reader(
+                    readDuringLayoutBeforePlacing = true,
+                    onMeasure = { ++measures },
+                    onLayout = { ++layouts }
+                )
+            ) {
+                Parent {
+                    Provider()
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, measures)
+            assertEquals(1, layouts)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, measures)
+            assertEquals(2, layouts)
+        }
+    }
+
+    @Test
+    fun scenario28() {
+        var measures = 0
+        var layouts = 0
+        rule.setContent {
+            Parent(
+                modifier = Modifier.reader(
+                    readDuringLayoutAfterPlacing = true,
+                    onMeasure = { ++measures },
+                    onLayout = { ++layouts }
+                )
+            ) {
+                Parent {
+                    Provider()
+                }
+            }
+        }
+        rule.runOnIdle {
+            assertEquals(1, measures)
+            assertEquals(1, layouts)
+            changeLinePosition()
+        }
+
+        rule.runOnIdle {
+            assertEquals(1, measures)
+            assertEquals(2, layouts)
+        }
+    }
+
+    private var linePosition = 10
+    private var linePositionState by mutableStateOf(10)
+    private fun changeLinePosition() {
+        linePosition += 10
+        linePositionState += 10
+    }
+    private val TestLine = HorizontalAlignmentLine(::min)
+
+    @Composable
+    private fun Parent(
+        modifier: Modifier = Modifier,
+        onMeasure: () -> Unit = {},
+        onLayout: () -> Unit = {},
+        readDuringMeasure: Boolean = false,
+        readDuringLayoutBeforePlacing: Boolean = false,
+        readDuringLayoutAfterPlacing: Boolean = false,
+        content: @Composable () -> Unit = {}
+    ) {
+        ChangingParent(
+            modifier,
+            onMeasure,
+            onLayout,
+            { readDuringMeasure },
+            { readDuringLayoutBeforePlacing },
+            { readDuringLayoutAfterPlacing },
+            content
+        )
+    }
+
+    @Composable
+    private fun ChangingParent(
+        modifier: Modifier = Modifier,
+        onMeasure: () -> Unit = {},
+        onLayout: () -> Unit = {},
+        readDuringMeasure: () -> Boolean = { false },
+        readDuringLayoutBeforePlacing: () -> Boolean = { false },
+        readDuringLayoutAfterPlacing: () -> Boolean = { false },
+        content: @Composable () -> Unit = {}
+    ) {
+        Layout(content, modifier) { measurables, constraints ->
+            onMeasure()
+            val placeables = measurables.map {
+                it.measure(constraints).also {
+                    if (readDuringMeasure()) assertEquals(linePosition, it[TestLine])
+                }
+            }
+            layout(constraints.maxWidth, constraints.maxHeight) {
+                onLayout()
+                placeables.forEach { placeable ->
+                    if (readDuringLayoutBeforePlacing()) {
+                        // placeable[TestLine]
+                        assertEquals(linePosition, placeable[TestLine])
+                    }
+                    placeable.place(0, 0)
+                    if (readDuringLayoutAfterPlacing()) {
+                        // placeable[TestLine]
+                        assertEquals(linePosition, placeable[TestLine])
+                    }
+                }
+            }
+        }
+    }
+
+    @Composable
+    private fun Provider(
+        modifier: Modifier = Modifier,
+        onMeasure: () -> Unit = {},
+        onLayout: () -> Unit = {},
+        content: @Composable () -> Unit = {}
+    ) {
+        Layout(content, modifier) { _, constraints ->
+            onMeasure()
+            layout(
+                constraints.maxWidth,
+                constraints.maxHeight,
+                mapOf(TestLine to linePositionState)
+            ) {
+                onLayout()
+            }
+        }
+    }
+
+    private fun Modifier.reader(
+        onMeasure: () -> Unit = {},
+        onLayout: () -> Unit = {},
+        readDuringMeasure: Boolean = false,
+        readDuringLayoutBeforePlacing: Boolean = false,
+        readDuringLayoutAfterPlacing: Boolean = false
+    ) = this.then(
+        ReaderModifier(
+            onMeasure,
+            onLayout,
+            readDuringMeasure,
+            readDuringLayoutBeforePlacing,
+            readDuringLayoutAfterPlacing
+        )
+    )
+    private inner class ReaderModifier(
+        val onMeasure: () -> Unit,
+        val onLayout: () -> Unit,
+        val readDuringMeasure: Boolean,
+        val readDuringLayoutBeforePlacing: Boolean,
+        val readDuringLayoutAfterPlacing: Boolean
+    ) : LayoutModifier {
+        override fun MeasureScope.measure(
+            measurable: Measurable,
+            constraints: Constraints
+        ): MeasureResult {
+            onMeasure()
+            val placeable = measurable.measure(constraints)
+            if (readDuringMeasure) assertEquals(linePosition, placeable[TestLine])
+            return layout(constraints.maxWidth, constraints.maxHeight) {
+                onLayout()
+                if (readDuringLayoutBeforePlacing) assertEquals(linePosition, placeable[TestLine])
+                placeable.place(0, 0)
+                if (readDuringLayoutAfterPlacing) assertEquals(linePosition, placeable[TestLine])
+            }
+        }
+    }
+
+    private fun Modifier.provider() = this.then(ProviderModifier())
+    private inner class ProviderModifier : LayoutModifier {
+        override fun MeasureScope.measure(
+            measurable: Measurable,
+            constraints: Constraints
+        ): MeasureResult {
+            val placeable = measurable.measure(constraints)
+            return layout(
+                constraints.maxWidth,
+                constraints.maxHeight,
+                mapOf(TestLine to linePositionState)
+            ) {
+                placeable.place(0, 0)
+            }
+        }
+
+        override fun hashCode(): Int {
+            return 0
+        }
+
+        override fun equals(other: Any?): Boolean {
+            return other is ProviderModifier
+        }
+    }
+
+    private fun Modifier.supplyAlignmentLines(alignmentLines: () -> Map<AlignmentLine, Int>) =
+        layout { measurable, constraints ->
+            val placeable = measurable.measure(constraints)
+            layout(placeable.width, placeable.height, alignmentLines()) {
+                placeable.place(0, 0)
+            }
+        }
 }
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/OnGloballyPositionedTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/OnGloballyPositionedTest.kt
index d7ae773..c66b1c7 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/OnGloballyPositionedTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/OnGloballyPositionedTest.kt
@@ -621,16 +621,24 @@
     @Test
     fun testAlignmentLinesArePresent() {
         val latch = CountDownLatch(1)
-        val line = VerticalAlignmentLine(::min)
+        val line1 = VerticalAlignmentLine(::min)
+        val line2 = HorizontalAlignmentLine(::min)
         val lineValue = 10
         rule.setContent {
             val onPositioned = Modifier.onGloballyPositioned { coordinates: LayoutCoordinates ->
-                assertEquals(1, coordinates.providedAlignmentLines.size)
-                assertEquals(lineValue, coordinates[line])
+                assertEquals(2, coordinates.providedAlignmentLines.size)
+                assertEquals(lineValue, coordinates[line1])
+                assertEquals(lineValue, coordinates[line2])
                 latch.countDown()
             }
-            Layout(modifier = onPositioned, content = { }) { _, _ ->
-                layout(0, 0, mapOf(line to lineValue)) { }
+            val lineProvider = Modifier.layout { measurable, constraints ->
+                val placeable = measurable.measure(constraints)
+                layout(0, 0, mapOf(line2 to lineValue)) {
+                    placeable.place(0, 0)
+                }
+            }
+            Layout(modifier = onPositioned.then(lineProvider), content = { }) { _, _ ->
+                layout(0, 0, mapOf(line1 to lineValue)) { }
             }
         }
         assertTrue(latch.await(1, TimeUnit.SECONDS))
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/platform/ComposeViewOverlayTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/platform/ComposeViewOverlayTest.kt
new file mode 100644
index 0000000..142aa4d
--- /dev/null
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/platform/ComposeViewOverlayTest.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.platform
+
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import android.widget.LinearLayout
+import androidx.activity.ComponentActivity
+import androidx.compose.foundation.text.BasicText
+import androidx.compose.runtime.Recomposer
+import androidx.compose.runtime.SideEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshots.Snapshot
+import androidx.compose.ui.InternalComposeUiApi
+import androidx.lifecycle.LifecycleOwner
+import androidx.test.ext.junit.rules.activityScenarioRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.runBlocking
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class ComposeViewOverlayTest {
+    /**
+     * Note: this test does not use the compose rule to ensure default behavior
+     * of window-scoped Recomposer installation.
+     */
+    @get:Rule
+    val rule = activityScenarioRule<ComponentActivity>()
+
+    /**
+     * Moving a ComposeView to an [android.view.ViewOverlay] means it won't have a correct parent
+     * chain. This happens when user code performs view transitions on the rest of the view
+     * hierarchy. Test that ComposeView still works when moved back and forth as long as it was
+     * originally attached to the target window "for real."
+     */
+    @OptIn(InternalComposeUiApi::class)
+    @Test
+    fun testComposeViewMovedToOverlay() {
+        var factoryCallCount = 0
+        lateinit var createdRecomposer: Recomposer
+        WindowRecomposerPolicy.withFactory(
+            { view ->
+                factoryCallCount++
+                WindowRecomposerFactory.LifecycleAware.createRecomposer(view).also {
+                    createdRecomposer = it
+                }
+            }
+        ) {
+            val expectedText = "Hello, world"
+            lateinit var composeView: ComposeView
+            lateinit var contentAView: ViewGroup
+            lateinit var contentBView: ViewGroup
+            var localLifecycleOwner by mutableStateOf<LifecycleOwner?>(null)
+            var publishedStage by mutableStateOf(0)
+            var consumedStage by mutableStateOf(-1)
+            var compositionCount = 0
+            rule.scenario.onActivity { activity ->
+                composeView = ComposeView(activity).apply {
+                    setContent {
+                        BasicText(expectedText)
+                        localLifecycleOwner = LocalLifecycleOwner.current
+                        consumedStage = publishedStage
+                        SideEffect {
+                            compositionCount++
+                        }
+                    }
+                }
+                contentAView = FrameLayout(activity).apply {
+                    addView(composeView)
+                }
+                contentBView = FrameLayout(activity)
+                val views = LinearLayout(activity).apply {
+                    addView(
+                        contentAView,
+                        LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1f)
+                    )
+                    addView(
+                        contentBView,
+                        LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1f)
+                    )
+                }
+                activity.setContentView(views)
+            }
+
+            createdRecomposer.waitForIdle()
+
+            assertNotNull("expected non-null LocalLifecycleOwner", localLifecycleOwner)
+            assertEquals("unexpected recomposition result", publishedStage, consumedStage)
+            assertTrue("composed at least once", compositionCount > 0)
+            val compositionCountAtFirstIdle: Int = compositionCount
+            rule.scenario.onActivity {
+                contentAView.removeView(composeView)
+                contentBView.overlay.add(composeView)
+                publishedStage++
+                // Send apply notifications right away so that we know it happened
+                // before this onActivity block returns back to the test thread.
+                // Otherwise the waitForIdleRecomposers below can run before the publishedStage
+                // change is picked up by the recomposer.
+                Snapshot.sendApplyNotifications()
+            }
+
+            createdRecomposer.waitForIdle()
+
+            assertNotNull("overlay expected non-null LocalLifecycleOwner", localLifecycleOwner)
+            assertEquals("unexpected recomposition overlay result", publishedStage, consumedStage)
+            assertTrue(
+                "recomposed at least once since idle",
+                compositionCount > compositionCountAtFirstIdle
+            )
+        }
+        assertEquals("Created recomposer count", 1, factoryCallCount)
+    }
+
+    private fun Recomposer.waitForIdle() = runBlocking {
+        state.filter { it == Recomposer.State.Idle }.first()
+    }
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ComposeView.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ComposeView.android.kt
index 7d990253..69f0564 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ComposeView.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ComposeView.android.kt
@@ -17,6 +17,7 @@
 package androidx.compose.ui.platform
 
 import android.content.Context
+import android.os.IBinder
 import android.util.AttributeSet
 import android.view.View
 import android.view.ViewGroup
@@ -29,14 +30,6 @@
 import androidx.compose.ui.node.Owner
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.ViewTreeLifecycleOwner
-import androidx.savedstate.ViewTreeSavedStateRegistryOwner
-
-private const val MissingViewTreeDependenciesMessage =
-    "If you are adding this ComposeView to an AppCompatActivity, make sure you " +
-        "are using AppCompat version 1.3+. If you are adding this ComposeView to a " +
-        "Fragment, make sure you are using Fragment version 1.3+. For other cases, manually " +
-        "set owners on this view by using `ViewTreeLifecycleOwner.set()` and " +
-        "`ViewTreeSavedStateRegistryOwner.set()`."
 
 /**
  * Base class for custom [android.view.View]s implemented using Jetpack Compose UI.
@@ -63,12 +56,44 @@
         clipToPadding = false
     }
 
+    /**
+     * The first time we successfully locate this we'll save it here.
+     * If this View moves to the [android.view.ViewOverlay] we won't be able
+     * to find view tree dependencies; this happens when using transition APIs
+     * to animate views out in particular.
+     */
+    private var cachedViewTreeCompositionContext: CompositionContext? = null
+
+    /**
+     * The [getWindowToken] of the window this view was last attached to.
+     * If we become attached to a new window we clear [cachedViewTreeCompositionContext]
+     * so that we might appeal to the (possibly lazily created) [windowRecomposer]
+     * if [findViewTreeCompositionContext] can't locate one instead of using the previous
+     * [cachedViewTreeCompositionContext].
+     */
+    private var previousAttachedWindowToken: IBinder? = null
+        set(value) {
+            if (field !== value) {
+                field = value
+                cachedViewTreeCompositionContext = null
+            }
+        }
+
     private var composition: Composition? = null
 
+    /**
+     * The explicitly set [CompositionContext] to use as the parent of compositions created
+     * for this view. Set by [setParentCompositionContext].
+     *
+     * If set to a non-null value [cachedViewTreeCompositionContext] will be cleared.
+     */
     private var parentContext: CompositionContext? = null
         set(value) {
             if (field !== value) {
                 field = value
+                if (value != null) {
+                    cachedViewTreeCompositionContext = null
+                }
                 val old = composition
                 if (old !== null) {
                     old.dispose()
@@ -175,30 +200,31 @@
         }
     }
 
-    private fun checkViewTreeOwners() {
-        checkNotNull(ViewTreeLifecycleOwner.get(this)) {
-            "ViewTreeLifecycleOwner not set for this ComposeView. " +
-                MissingViewTreeDependenciesMessage
-        }
-        checkNotNull(ViewTreeSavedStateRegistryOwner.get(this)) {
-            "ViewTreeSavedStateRegistryOwner not set for this ComposeView. " +
-                MissingViewTreeDependenciesMessage
-        }
-        // Not checking for ViewTreeViewModelStoreOwner as we don't need it inside Compose,
-        // but we provide it in ComponentActivity.setContent for convenience.
-    }
+    /**
+     * Determine the correct [CompositionContext] to use as the parent of this view's
+     * composition. This can result in caching a looked-up [CompositionContext] for use
+     * later. See [cachedViewTreeCompositionContext] for more details.
+     *
+     * If [cachedViewTreeCompositionContext] is available but [findViewTreeCompositionContext]
+     * cannot find a parent context, we will use the cached context if present before appealing
+     * to the [windowRecomposer], as [windowRecomposer] can lazily create a recomposer.
+     * If we're reattached to the same window and [findViewTreeCompositionContext] can't find the
+     * context that [windowRecomposer] would install, we might be in the [getOverlay] of some
+     * part of the view hierarchy to animate the disappearance of this and other views. We still
+     * need to be able to compose/recompose in this state without creating a brand new recomposer
+     * to do it, as well as still locate any view tree dependencies.
+     */
+    private fun resolveParentCompositionContext() = parentContext
+        ?: findViewTreeCompositionContext()?.also { cachedViewTreeCompositionContext = it }
+        ?: cachedViewTreeCompositionContext
+        ?: windowRecomposer.also { cachedViewTreeCompositionContext = it }
 
     @Suppress("DEPRECATION") // Still using ViewGroup.setContent for now
     private fun ensureCompositionCreated() {
         if (composition == null) {
-            if (isAttachedToWindow) {
-                checkViewTreeOwners()
-            }
             try {
                 creatingComposition = true
-                composition = setContent(
-                    parentContext ?: findViewTreeCompositionContext() ?: windowRecomposer
-                ) {
+                composition = setContent(resolveParentCompositionContext()) {
                     Content()
                 }
             } finally {
@@ -227,9 +253,7 @@
     override fun onAttachedToWindow() {
         super.onAttachedToWindow()
 
-        if (composition != null) {
-            checkViewTreeOwners()
-        }
+        previousAttachedWindowToken = windowToken
 
         if (shouldCreateCompositionOnAttachedToWindow) {
             ensureCompositionCreated()
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/InputMethodManager.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/InputMethodManager.kt
new file mode 100644
index 0000000..39071a16
--- /dev/null
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/InputMethodManager.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.text.input
+
+import android.content.Context
+import android.os.IBinder
+import android.view.View
+import android.view.inputmethod.ExtractedText
+
+internal interface InputMethodManager {
+    fun restartInput(view: View)
+
+    fun showSoftInput(view: View)
+
+    fun hideSoftInputFromWindow(windowToken: IBinder?)
+
+    fun updateExtractedText(
+        view: View,
+        token: Int,
+        extractedText: ExtractedText
+    )
+
+    fun updateSelection(
+        view: View,
+        selectionStart: Int,
+        selectionEnd: Int,
+        compositionStart: Int,
+        compositionEnd: Int
+    )
+}
+
+/**
+ * Wrapper class to prevent depending on getSystemService and final InputMethodManager.
+ * Let's us test TextInputServiceAndroid class.
+ */
+internal class InputMethodManagerImpl(context: Context) : InputMethodManager {
+
+    private val imm by lazy(LazyThreadSafetyMode.NONE) {
+        context.getSystemService(Context.INPUT_METHOD_SERVICE)
+            as android.view.inputmethod.InputMethodManager
+    }
+
+    override fun restartInput(view: View) {
+        imm.restartInput(view)
+    }
+
+    override fun showSoftInput(view: View) {
+        imm.showSoftInput(view, 0)
+    }
+
+    override fun hideSoftInputFromWindow(windowToken: IBinder?) {
+        imm.hideSoftInputFromWindow(windowToken, 0)
+    }
+
+    override fun updateExtractedText(
+        view: View,
+        token: Int,
+        extractedText: ExtractedText
+    ) {
+        imm.updateExtractedText(view, token, extractedText)
+    }
+
+    override fun updateSelection(
+        view: View,
+        selectionStart: Int,
+        selectionEnd: Int,
+        compositionStart: Int,
+        compositionEnd: Int
+    ) {
+        imm.updateSelection(view, selectionStart, selectionEnd, compositionStart, compositionEnd)
+    }
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/RecordingInputConnection.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/RecordingInputConnection.android.kt
index 6ff574f..ceedc8c 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/RecordingInputConnection.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/RecordingInputConnection.android.kt
@@ -29,7 +29,6 @@
 import android.view.inputmethod.ExtractedTextRequest
 import android.view.inputmethod.InputConnection
 import android.view.inputmethod.InputContentInfo
-import android.view.inputmethod.InputMethodManager
 import androidx.annotation.VisibleForTesting
 
 internal const val DEBUG = false
@@ -94,7 +93,11 @@
      * This function may emits updateSelection and updateExtractedText to notify IMEs that the text
      * contents has changed if needed.
      */
-    fun updateInputState(state: TextFieldValue, imm: InputMethodManager, view: View) {
+    fun updateInputState(
+        state: TextFieldValue,
+        inputMethodManager: InputMethodManager,
+        view: View
+    ) {
         if (!isActive) return
 
         if (DEBUG) { logDebug("RecordingInputConnection.updateInputState: $state") }
@@ -102,7 +105,11 @@
         mTextFieldValue = state
 
         if (extractedTextMonitorMode) {
-            imm.updateExtractedText(view, currentExtractedTextRequestToken, state.toExtractedText())
+            inputMethodManager.updateExtractedText(
+                view,
+                currentExtractedTextRequestToken,
+                state.toExtractedText()
+            )
         }
 
         // updateSelection API requires -1 if there is no composition
@@ -115,7 +122,7 @@
                     "composition = ($compositionStart, $compositionEnd))"
             )
         }
-        imm.updateSelection(
+        inputMethodManager.updateSelection(
             view, state.selection.min, state.selection.max, compositionStart, compositionEnd
         )
     }
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.android.kt
index 0ecb4fe..e008960 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.android.kt
@@ -16,9 +16,6 @@
 
 package androidx.compose.ui.text.input
 
-import android.annotation.SuppressLint
-import android.content.Context
-import android.os.Build
 import android.text.InputType
 import android.util.Log
 import android.view.KeyEvent
@@ -27,9 +24,9 @@
 import android.view.inputmethod.BaseInputConnection
 import android.view.inputmethod.EditorInfo
 import android.view.inputmethod.InputConnection
-import android.view.inputmethod.InputMethodManager
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.text.TextRange
+import androidx.core.view.inputmethod.EditorInfoCompat
 import kotlinx.coroutines.channels.Channel
 import kotlin.math.roundToInt
 
@@ -38,7 +35,10 @@
 /**
  * Provide Android specific input service with the Operating System.
  */
-internal class TextInputServiceAndroid(val view: View) : PlatformTextInputService {
+internal class TextInputServiceAndroid(
+    val view: View,
+    private val inputMethodManager: InputMethodManager
+) : PlatformTextInputService {
     /** True if the currently editable composable has connected */
     private var editorHasFocus = false
 
@@ -55,21 +55,11 @@
     private var imeOptions = ImeOptions.Default
     private var ic: RecordingInputConnection? = null
     // used for sendKeyEvent delegation
-    private var baseInputConnection: BaseInputConnection = BaseInputConnection(view, false)
-    private var focusedRect: android.graphics.Rect? = null
+    private val baseInputConnection by lazy(LazyThreadSafetyMode.NONE) {
+        BaseInputConnection(view, false)
+    }
 
-    private var _imm: InputMethodManager? = null
-    /**
-     * The editable buffer used for BaseInputConnection.
-     */
-    private val imm: InputMethodManager
-        get() {
-            if (_imm == null) {
-                _imm = view.context.getSystemService(Context.INPUT_METHOD_SERVICE) as
-                    InputMethodManager
-            }
-            return _imm!!
-        }
+    private var focusedRect: android.graphics.Rect? = null
 
     /**
      * A channel that is used to send ShowKeyboard/HideKeyboard commands. Send 'true' for
@@ -83,6 +73,8 @@
         focusedRect?.let { view.requestRectangleOnScreen(it) }
     }
 
+    internal constructor(view: View) : this(view, InputMethodManagerImpl(view.context))
+
     init {
         if (DEBUG) { Log.d(TAG, "$DEBUG_CLASS.create") }
 
@@ -104,7 +96,8 @@
         if (!editorHasFocus) {
             return null
         }
-        fillEditorInfo(outAttrs)
+
+        outAttrs.update(imeOptions, state)
 
         return RecordingInputConnection(
             initState = state,
@@ -167,7 +160,7 @@
 
     private fun restartInput() {
         if (DEBUG) Log.d(TAG, "$DEBUG_CLASS.restartInput")
-        imm.restartInput(view)
+        inputMethodManager.restartInput(view)
     }
 
     override fun showSoftwareKeyboard() {
@@ -189,10 +182,10 @@
             // to make sure that we use the most recent value.
             if (showKeyboardChannel.poll() ?: showKeyboard) {
                 if (DEBUG) { Log.d(TAG, "$DEBUG_CLASS.keyboardVisibilityEventLoop.showSoftInput") }
-                imm.showSoftInput(view, 0)
+                inputMethodManager.showSoftInput(view)
             } else {
                 if (DEBUG) { Log.d(TAG, "$DEBUG_CLASS.keyboardVisibilityEventLoop.hideSoftInput") }
-                imm.hideSoftInputFromWindow(view.windowToken, 0)
+                inputMethodManager.hideSoftInputFromWindow(view.windowToken)
             }
         }
     }
@@ -224,7 +217,7 @@
         if (restartInput) {
             restartInput()
         } else {
-            ic?.updateInputState(this.state, imm, view)
+            ic?.updateInputState(this.state, inputMethodManager, view)
         }
     }
 
@@ -246,97 +239,94 @@
             view.requestRectangleOnScreen(focusedRect)
         }
     }
+}
 
-    /**
-     * Fills necessary info of EditorInfo.
-     */
-    private fun fillEditorInfo(outInfo: EditorInfo) {
-        outInfo.imeOptions = when (imeOptions.imeAction) {
-            ImeAction.Default -> {
-                if (imeOptions.singleLine) {
-                    // this is the last resort to enable single line
-                    // Android IME still show return key even if multi line is not send
-                    // TextView.java#onCreateInputConnection
-                    EditorInfo.IME_ACTION_DONE
-                } else {
-                    EditorInfo.IME_ACTION_UNSPECIFIED
-                }
-            }
-            ImeAction.None -> EditorInfo.IME_ACTION_NONE
-            ImeAction.Go -> EditorInfo.IME_ACTION_GO
-            ImeAction.Next -> EditorInfo.IME_ACTION_NEXT
-            ImeAction.Previous -> EditorInfo.IME_ACTION_PREVIOUS
-            ImeAction.Search -> EditorInfo.IME_ACTION_SEARCH
-            ImeAction.Send -> EditorInfo.IME_ACTION_SEND
-            ImeAction.Done -> EditorInfo.IME_ACTION_DONE
-            else -> error("invalid ImeAction")
-        }
-        when (imeOptions.keyboardType) {
-            KeyboardType.Text -> outInfo.inputType = InputType.TYPE_CLASS_TEXT
-            KeyboardType.Ascii -> {
-                outInfo.inputType = InputType.TYPE_CLASS_TEXT
-                outInfo.imeOptions = outInfo.imeOptions or EditorInfo.IME_FLAG_FORCE_ASCII
-            }
-            KeyboardType.Number -> outInfo.inputType = InputType.TYPE_CLASS_NUMBER
-            KeyboardType.Phone -> outInfo.inputType = InputType.TYPE_CLASS_PHONE
-            KeyboardType.Uri ->
-                outInfo.inputType = InputType.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_VARIATION_URI
-            KeyboardType.Email ->
-                outInfo.inputType =
-                    InputType.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
-            KeyboardType.Password -> {
-                outInfo.inputType =
-                    InputType.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_VARIATION_PASSWORD
-            }
-            KeyboardType.NumberPassword -> {
-                outInfo.inputType =
-                    InputType.TYPE_CLASS_NUMBER or EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD
-            }
-            else -> error("Invalid Keyboard Type")
-        }
-
-        if (!imeOptions.singleLine) {
-            if (hasFlag(outInfo.inputType, InputType.TYPE_CLASS_TEXT)) {
-                // TextView.java#setInputTypeSingleLine
-                outInfo.inputType = outInfo.inputType or InputType.TYPE_TEXT_FLAG_MULTI_LINE
-
-                if (imeOptions.imeAction == ImeAction.Default) {
-                    outInfo.imeOptions = outInfo.imeOptions or EditorInfo.IME_FLAG_NO_ENTER_ACTION
-                }
+/**
+ * Fills necessary info of EditorInfo.
+ */
+internal fun EditorInfo.update(imeOptions: ImeOptions, textFieldValue: TextFieldValue) {
+    this.imeOptions = when (imeOptions.imeAction) {
+        ImeAction.Default -> {
+            if (imeOptions.singleLine) {
+                // this is the last resort to enable single line
+                // Android IME still show return key even if multi line is not send
+                // TextView.java#onCreateInputConnection
+                EditorInfo.IME_ACTION_DONE
+            } else {
+                EditorInfo.IME_ACTION_UNSPECIFIED
             }
         }
-
-        if (hasFlag(outInfo.inputType, InputType.TYPE_CLASS_TEXT)) {
-            when (imeOptions.capitalization) {
-                KeyboardCapitalization.None -> {
-                    /* do nothing */
-                }
-                KeyboardCapitalization.Characters -> {
-                    outInfo.inputType = outInfo.inputType or InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
-                }
-                KeyboardCapitalization.Words -> {
-                    outInfo.inputType = outInfo.inputType or InputType.TYPE_TEXT_FLAG_CAP_WORDS
-                }
-                KeyboardCapitalization.Sentences -> {
-                    outInfo.inputType = outInfo.inputType or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
-                }
-            }
-
-            if (imeOptions.autoCorrect) {
-                outInfo.inputType = outInfo.inputType or InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
-            }
+        ImeAction.None -> EditorInfo.IME_ACTION_NONE
+        ImeAction.Go -> EditorInfo.IME_ACTION_GO
+        ImeAction.Next -> EditorInfo.IME_ACTION_NEXT
+        ImeAction.Previous -> EditorInfo.IME_ACTION_PREVIOUS
+        ImeAction.Search -> EditorInfo.IME_ACTION_SEARCH
+        ImeAction.Send -> EditorInfo.IME_ACTION_SEND
+        ImeAction.Done -> EditorInfo.IME_ACTION_DONE
+        else -> error("invalid ImeAction")
+    }
+    when (imeOptions.keyboardType) {
+        KeyboardType.Text -> this.inputType = InputType.TYPE_CLASS_TEXT
+        KeyboardType.Ascii -> {
+            this.inputType = InputType.TYPE_CLASS_TEXT
+            this.imeOptions = this.imeOptions or EditorInfo.IME_FLAG_FORCE_ASCII
         }
-
-        outInfo.initialSelStart = state.selection.start
-        outInfo.initialSelEnd = state.selection.end
-
-        @SuppressLint("UnsafeNewApiCall")
-        if (Build.VERSION.SDK_INT >= 30) {
-            outInfo.setInitialSurroundingText(state.text)
+        KeyboardType.Number -> this.inputType = InputType.TYPE_CLASS_NUMBER
+        KeyboardType.Phone -> this.inputType = InputType.TYPE_CLASS_PHONE
+        KeyboardType.Uri ->
+            this.inputType = InputType.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_VARIATION_URI
+        KeyboardType.Email ->
+            this.inputType =
+                InputType.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
+        KeyboardType.Password -> {
+            this.inputType =
+                InputType.TYPE_CLASS_TEXT or EditorInfo.TYPE_TEXT_VARIATION_PASSWORD
         }
-
-        outInfo.imeOptions = outInfo.imeOptions or EditorInfo.IME_FLAG_NO_FULLSCREEN
+        KeyboardType.NumberPassword -> {
+            this.inputType =
+                InputType.TYPE_CLASS_NUMBER or EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD
+        }
+        else -> error("Invalid Keyboard Type")
     }
 
-    private fun hasFlag(bits: Int, flag: Int): Boolean = (bits and flag) == flag
-}
\ No newline at end of file
+    if (!imeOptions.singleLine) {
+        if (hasFlag(this.inputType, InputType.TYPE_CLASS_TEXT)) {
+            // TextView.java#setInputTypeSingleLine
+            this.inputType = this.inputType or InputType.TYPE_TEXT_FLAG_MULTI_LINE
+
+            if (imeOptions.imeAction == ImeAction.Default) {
+                this.imeOptions = this.imeOptions or EditorInfo.IME_FLAG_NO_ENTER_ACTION
+            }
+        }
+    }
+
+    if (hasFlag(this.inputType, InputType.TYPE_CLASS_TEXT)) {
+        when (imeOptions.capitalization) {
+            KeyboardCapitalization.None -> {
+                /* do nothing */
+            }
+            KeyboardCapitalization.Characters -> {
+                this.inputType = this.inputType or InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
+            }
+            KeyboardCapitalization.Words -> {
+                this.inputType = this.inputType or InputType.TYPE_TEXT_FLAG_CAP_WORDS
+            }
+            KeyboardCapitalization.Sentences -> {
+                this.inputType = this.inputType or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
+            }
+        }
+
+        if (imeOptions.autoCorrect) {
+            this.inputType = this.inputType or InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
+        }
+    }
+
+    this.initialSelStart = textFieldValue.selection.start
+    this.initialSelEnd = textFieldValue.selection.end
+
+    EditorInfoCompat.setInitialSurroundingText(this, textFieldValue.text)
+
+    this.imeOptions = this.imeOptions or EditorInfo.IME_FLAG_NO_FULLSCREEN
+}
+
+private fun hasFlag(bits: Int, flag: Int): Boolean = (bits and flag) == flag
\ No newline at end of file
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DelegatingLayoutNodeWrapper.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DelegatingLayoutNodeWrapper.kt
index 387da83..b349ac6 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DelegatingLayoutNodeWrapper.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DelegatingLayoutNodeWrapper.kt
@@ -36,9 +36,6 @@
     override var wrapped: LayoutNodeWrapper,
     open var modifier: T
 ) : LayoutNodeWrapper(wrapped.layoutNode) {
-    override val providedAlignmentLines: Set<AlignmentLine>
-        get() = wrapped.providedAlignmentLines
-
     override val measureScope: MeasureScope get() = wrapped.measureScope
 
     /**
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/InnerPlaceable.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/InnerPlaceable.kt
index a8b4970..162c404 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/InnerPlaceable.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/InnerPlaceable.kt
@@ -35,9 +35,6 @@
     layoutNode: LayoutNode
 ) : LayoutNodeWrapper(layoutNode), Density by layoutNode.measureScope {
 
-    override val providedAlignmentLines: Set<AlignmentLine>
-        get() = layoutNode.providedAlignmentLines.keys
-
     override val measureScope get() = layoutNode.measureScope
 
     override fun measure(constraints: Constraints): Placeable = performingMeasure(constraints) {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
index 394e52c..427f1fa 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
@@ -349,7 +349,7 @@
             parent.invalidateLayer()
             parent.requestRemeasure()
         }
-        alignmentLinesQueryOwner = null
+        alignmentLines.reset()
         alignmentUsageByParent = UsageByParent.NotUsed
         onDetach?.invoke(owner)
         forEachDelegate { it.detach() }
@@ -494,15 +494,9 @@
     override val height: Int get() = outerMeasurablePlaceable.height
 
     /**
-     * The alignment lines of this layout, inherited + intrinsic
+     * State corresponding to the alignment lines of this layout, inherited + intrinsic
      */
-    internal var alignmentLines: LayoutNodeAlignmentLines? = null
-        private set
-
-    /**
-     * The alignment lines provided by this layout at the last measurement
-     */
-    internal var providedAlignmentLines: Map<AlignmentLine, Int> = emptyMap()
+    internal var alignmentLines = LayoutNodeAlignmentLines(this)
 
     internal val mDrawScope: LayoutNodeDrawScope = sharedDrawScope
 
@@ -532,36 +526,6 @@
      */
     internal var measuredByParent: UsageByParent = UsageByParent.NotUsed
 
-    /**
-     * `true` while doing [calculateAlignmentLines]
-     */
-    private var isCalculatingAlignmentLines = false
-
-    /**
-     * `true` when the parent reads our alignment lines
-     */
-    private var alignmentLinesRead = false
-
-    private var alignmentLinesCalculatedDuringLastLayout = false
-
-    /**
-     * `true` when an ancestor relies on our alignment lines
-     */
-    internal val alignmentLinesRequired
-        get() = alignmentLinesQueryOwner != null && alignmentLinesQueryOwner!!.alignmentLinesRead
-
-    /**
-     * Used by the parent to identify if the child has been queried for alignment lines since
-     * last measurement.
-     */
-    private var alignmentLinesQueriedSinceLastLayout = false
-
-    /**
-     * The closest layout node above in the hierarchy which asked for alignment lines.
-     */
-    internal var alignmentLinesQueryOwner: LayoutNode? = null
-        private set
-
     internal var alignmentUsageByParent = UsageByParent.NotUsed
 
     @Deprecated("Temporary API to support ConstraintLayout prototyping.")
@@ -885,7 +849,9 @@
         layoutChildren()
     }
 
-    private fun layoutChildren() {
+    internal fun layoutChildren() {
+        alignmentLines.recalculateQueryOwner()
+
         if (layoutState == NeedsRelayout) {
             onBeforeLayoutChildren()
         }
@@ -900,16 +866,9 @@
                 _children.forEach { child ->
                     // and reset the place order for all the children before placing them
                     child.placeOrder = NotPlacedPlaceOrder
-                    if (alignmentLinesRequired && child.layoutState == Ready &&
-                        !child.alignmentLinesCalculatedDuringLastLayout
-                    ) {
-                        child.layoutState = NeedsRelayout
-                    }
-                    if (!child.alignmentLinesRequired) {
-                        child.alignmentLinesQueryOwner = alignmentLinesQueryOwner
-                    }
-                    child.alignmentLinesQueriedSinceLastLayout = false
+                    child.alignmentLines.usedDuringParentLayout = false
                 }
+
                 innerLayoutNodeWrapper.measureResult.placeChildren()
                 _children.forEach { child ->
                     // we set `placeOrder` to NotPlacedPlaceOrder for all the children, then
@@ -921,20 +880,18 @@
                         // which is not placed anymore.
                         invalidateLayer()
                     }
-                    child.alignmentLinesRead = child.alignmentLinesQueriedSinceLastLayout
+                    child.alignmentLines.previousUsedDuringParentLayout =
+                        child.alignmentLines.usedDuringParentLayout
                 }
             }
 
-            alignmentLinesCalculatedDuringLastLayout = false
-            if (alignmentLinesRequired) {
-                alignmentLinesCalculatedDuringLastLayout = true
-                val alignments = alignmentLines ?: LayoutNodeAlignmentLines(this).also {
-                    alignmentLines = it
-                }
-                alignments.recalculate()
-            }
             layoutState = Ready
         }
+
+        if (alignmentLines.usedDuringParentLayout) {
+            alignmentLines.previousUsedDuringParentLayout = true
+        }
+        if (alignmentLines.dirty && alignmentLines.required) alignmentLines.recalculate()
     }
 
     private fun markSubtreeAsPlaced() {
@@ -991,56 +948,46 @@
     }
 
     internal fun onAlignmentsChanged() {
-        val parent = parent
-        if (parent != null) {
-            if (alignmentUsageByParent == UsageByParent.InMeasureBlock &&
-                parent.layoutState != LayingOut
-            ) {
-                parent.requestRemeasure()
-            } else if (alignmentUsageByParent == UsageByParent.InLayoutBlock) {
-                parent.requestRelayout()
-            }
+        if (alignmentLines.dirty) return
+        alignmentLines.dirty = true
+
+        val parent = parent ?: return
+        if (alignmentLines.usedDuringParentMeasurement) {
+            parent.requestRemeasure()
+        } else if (alignmentLines.previousUsedDuringParentLayout) {
+            parent.requestRelayout()
         }
+        if (alignmentLines.usedByModifierMeasurement) {
+            requestRemeasure()
+        }
+        if (alignmentLines.usedByModifierLayout) {
+            parent.requestRelayout()
+        }
+        parent.onAlignmentsChanged()
     }
 
     internal fun calculateAlignmentLines(): Map<AlignmentLine, Int> {
-        isCalculatingAlignmentLines = true
-        alignmentLinesRead = true
-        alignmentLinesQueryOwner = this
-        alignmentLinesQueriedSinceLastLayout = true
-        val newUsageByParent = when (parent?.layoutState) {
-            Measuring -> UsageByParent.InMeasureBlock
-            LayingOut -> UsageByParent.InLayoutBlock
-            else -> UsageByParent.NotUsed
+        if (!outerMeasurablePlaceable.duringAlignmentLinesQuery) {
+            alignmentLinesQueriedByModifier()
         }
-        val newUsageHasLowerPriority = newUsageByParent == UsageByParent.InLayoutBlock &&
-            alignmentUsageByParent == UsageByParent.InMeasureBlock
-        if (!newUsageHasLowerPriority) {
-            alignmentUsageByParent = newUsageByParent
+        layoutChildren()
+        return alignmentLines.getLastCalculation()
+    }
+
+    private fun alignmentLinesQueriedByModifier() {
+        if (layoutState == Measuring) {
+            alignmentLines.usedByModifierMeasurement = true
+            // We quickly transition to NeedsRelayout as we need the alignment lines now.
+            // Later we will see that we also laid out as part of measurement and will skip layout.
+            if (alignmentLines.dirty) layoutState = NeedsRelayout
+        } else {
+            // Note this can also happen for onGloballyPositioned queries.
+            alignmentLines.usedByModifierLayout = true
         }
-        if (layoutState == NeedsRelayout || !alignmentLinesCalculatedDuringLastLayout) {
-            // layoutChildren() is a state transformation from NeedsRelayout to Ready.
-            // when we are already in NeedsRelayout we need to end up with Ready, but if we are
-            // currently measuring or need remeasure this extra layoutChildren is just a side effect
-            // and we will need to restore the current state.
-            val endState = if (layoutState == Measuring || layoutState == NeedsRemeasure) {
-                layoutState
-            } else {
-                Ready
-            }
-            if (!alignmentLinesCalculatedDuringLastLayout) {
-                layoutState = NeedsRelayout
-            }
-            layoutChildren()
-            layoutState = endState
-        }
-        isCalculatingAlignmentLines = false
-        return alignmentLines?.getLastCalculation() ?: emptyMap()
     }
 
     internal fun handleMeasureResult(measureResult: MeasureResult) {
         innerLayoutNodeWrapper.measureResult = measureResult
-        providedAlignmentLines = measureResult.alignmentLines
     }
 
     /**
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeAlignmentLines.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeAlignmentLines.kt
index fba763a..3e1c26c 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeAlignmentLines.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeAlignmentLines.kt
@@ -26,57 +26,154 @@
     private val layoutNode: LayoutNode
 ) {
     /**
-     * The alignment lines of this layout, inherited + intrinsic
+     * `true` when the alignment lines needs to be recalculated because they might have changed.
      */
-    private val alignmentLines: MutableMap<AlignmentLine, Int> = hashMapOf()
+    internal var dirty = true
 
-    private val previousAlignmentLines = mutableMapOf<AlignmentLine, Int>()
+    /**
+     * `true` when the alignment lines were used by the parent during measurement.
+     */
+    internal var usedDuringParentMeasurement = false
 
-    fun getLastCalculation(): Map<AlignmentLine, Int> = alignmentLines
+    /**
+     * `true` when the alignment lines have been used by the parent during the current layout (or
+     * previous layout if there is no layout in progress).
+     */
+    internal var usedDuringParentLayout = false
+    /**
+     * `true` when the alignment lines were used by the parent during the last completed layout.
+     */
+    internal var previousUsedDuringParentLayout = false
 
-    fun recalculate() {
-        previousAlignmentLines.clear()
-        previousAlignmentLines.putAll(alignmentLines)
-        alignmentLines.clear()
-        layoutNode._children.forEach { child ->
-            val childAlignments = child.alignmentLines
-            if (!child.isPlaced || childAlignments == null) return@forEach
-            childAlignments.alignmentLines.keys.forEach { childLine ->
-                val linePositionInContainer = childAlignments.getAlignmentLine(childLine)!!
-                // If the line was already provided by a previous child, merge the values.
-                alignmentLines[childLine] = if (childLine in alignmentLines) {
-                    childLine.merge(
-                        alignmentLines.getValue(childLine),
-                        linePositionInContainer
-                    )
-                } else {
-                    linePositionInContainer
-                }
+    /**
+     * `true` when the alignment lines were used by the modifier of the node during measurement.
+     */
+    internal var usedByModifierMeasurement = false
+
+    /**
+     * `true` when the alignment lines were used by the modifier of the node during measurement.
+     */
+    internal var usedByModifierLayout = false
+
+    /**
+     * `true` when the direct parent or our modifier relies on our alignment lines.
+     */
+    internal val queried get() = usedDuringParentMeasurement ||
+        previousUsedDuringParentLayout || usedByModifierMeasurement ||
+        usedByModifierLayout
+
+    /**
+     * The closest layout node ancestor who was asked for alignment lines, either by the parent or
+     * their own modifier. If the owner stops being queried for alignment lines, we have to
+     * [recalculateQueryOwner] to find the new owner if one exists.
+     */
+    private var queryOwner: LayoutNode? = null
+
+    /**
+     * Whether the alignment lines of this node are relevant (whether an ancestor depends on them).
+     */
+    internal val required: Boolean get() {
+        recalculateQueryOwner()
+        return queryOwner != null
+    }
+
+    /**
+     * Updates the alignment lines query owner according to the current values of the
+     * alignmentUsedBy* of the layout nodes in the hierarchy.
+     */
+    internal fun recalculateQueryOwner() {
+        queryOwner = if (queried) {
+            layoutNode
+        } else {
+            val parent = layoutNode.parent ?: return
+            val parentQueryOwner = parent.alignmentLines.queryOwner
+            if (parentQueryOwner != null && parentQueryOwner.alignmentLines.queried) {
+                parentQueryOwner
+            } else {
+                val owner = queryOwner
+                if (owner == null || owner.alignmentLines.queried) return
+                owner.parent?.alignmentLines?.recalculateQueryOwner()
+                owner.parent?.alignmentLines?.queryOwner
             }
         }
-        alignmentLines += layoutNode.providedAlignmentLines
-        if (previousAlignmentLines != alignmentLines) {
-            layoutNode.onAlignmentsChanged()
-        }
     }
 
     /**
-     * Returns the alignment line value for a given alignment line without affecting whether
-     * the flag for whether the alignment line was read.
+     * The alignment lines of this layout, inherited + intrinsic
      */
-    private fun getAlignmentLine(alignmentLine: AlignmentLine): Int? {
-        val linePos = alignmentLines[alignmentLine] ?: return null
-        var pos = Offset(linePos.toFloat(), linePos.toFloat())
-        var wrapper = layoutNode.innerLayoutNodeWrapper
-        while (wrapper != layoutNode.outerLayoutNodeWrapper) {
-            pos = wrapper.toParentPosition(pos)
-            wrapper = wrapper.wrappedBy!!
+    private val alignmentLines: MutableMap<AlignmentLine, Int> = hashMapOf()
+
+    fun getLastCalculation(): Map<AlignmentLine, Int> = alignmentLines
+
+    fun recalculate() {
+        alignmentLines.clear()
+        /**
+         * Returns the alignment line value for a given alignment line without affecting whether
+         * the flag for whether the alignment line was read.
+         */
+        fun addAlignmentLine(
+            alignmentLine: AlignmentLine,
+            initialPosition: Int,
+            initialWrapper: LayoutNodeWrapper
+        ) {
+            var position = Offset(initialPosition.toFloat(), initialPosition.toFloat())
+            var wrapper = initialWrapper
+            while (true) {
+                position = wrapper.toParentPosition(position)
+                wrapper = wrapper.wrappedBy!!
+                if (wrapper == layoutNode.innerLayoutNodeWrapper) break
+                if (alignmentLine in wrapper.providedAlignmentLines) {
+                    val newPosition = wrapper[alignmentLine]
+                    position = Offset(newPosition.toFloat(), newPosition.toFloat())
+                }
+            }
+            val positionInContainer = if (alignmentLine is HorizontalAlignmentLine) {
+                position.y.roundToInt()
+            } else {
+                position.x.roundToInt()
+            }
+            // If the line was already provided by a previous child, merge the values.
+            alignmentLines[alignmentLine] = if (alignmentLine in alignmentLines) {
+                alignmentLine.merge(
+                    alignmentLines.getValue(alignmentLine),
+                    positionInContainer
+                )
+            } else {
+                positionInContainer
+            }
         }
-        pos = wrapper.toParentPosition(pos)
-        return if (alignmentLine is HorizontalAlignmentLine) {
-            pos.y.roundToInt()
-        } else {
-            pos.x.roundToInt()
+        layoutNode._children.forEach { child ->
+            if (!child.isPlaced) return@forEach
+            if (child.alignmentLines.dirty) {
+                // It did not need relayout, but we still call layout to recalculate
+                // alignment lines.
+                child.layoutChildren()
+            }
+            // Add alignment lines on the child node.
+            child.alignmentLines.alignmentLines.forEach { (childLine, linePosition) ->
+                addAlignmentLine(childLine, linePosition, child.innerLayoutNodeWrapper)
+            }
+
+            // Add alignment lines on the modifier of the child.
+            var wrapper = child.innerLayoutNodeWrapper.wrappedBy!!
+            while (wrapper != layoutNode.innerLayoutNodeWrapper) {
+                wrapper.providedAlignmentLines.forEach { childLine ->
+                    addAlignmentLine(childLine, wrapper[childLine], wrapper)
+                }
+                wrapper = wrapper.wrappedBy!!
+            }
         }
+        alignmentLines += layoutNode.innerLayoutNodeWrapper.measureResult.alignmentLines
+        dirty = false
+    }
+
+    internal fun reset() {
+        dirty = true
+        usedDuringParentMeasurement = false
+        previousUsedDuringParentLayout = false
+        usedDuringParentLayout = false
+        usedByModifierMeasurement = false
+        usedByModifierLayout = false
+        queryOwner = null
     }
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeWrapper.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeWrapper.kt
index b584d63..dde4d76 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeWrapper.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeWrapper.kt
@@ -88,9 +88,40 @@
                 if (old == null || value.width != old.width || value.height != old.height) {
                     onMeasureResultChanged(value.width, value.height)
                 }
+                // We do not simply compare against old.alignmentLines in case this is a
+                // MutableStateMap and the same instance might be passed.
+                if ((!oldAlignmentLines.isNullOrEmpty() || value.alignmentLines.isNotEmpty()) &&
+                    value.alignmentLines != oldAlignmentLines
+                ) {
+                    if (wrapped?.layoutNode == layoutNode) {
+                        layoutNode.parent?.onAlignmentsChanged()
+                        // We might need to request remeasure or relayout for the parent in
+                        // case they ask for the lines so we are the query owner, without
+                        // marking dirty our alignment lines (because only the modifier's changed).
+                        if (layoutNode.alignmentLines.usedDuringParentMeasurement) {
+                            layoutNode.parent?.requestRemeasure()
+                        } else if (layoutNode.alignmentLines.usedDuringParentLayout) {
+                            layoutNode.parent?.requestRelayout()
+                        }
+                    } else {
+                        // It means we are an InnerPlaceable.
+                        layoutNode.onAlignmentsChanged()
+                    }
+                    layoutNode.alignmentLines.dirty = true
+
+                    val oldLines = oldAlignmentLines
+                        ?: (mutableMapOf<AlignmentLine, Int>().also { oldAlignmentLines = it })
+                    oldLines.clear()
+                    oldLines.putAll(value.alignmentLines)
+                }
             }
         }
 
+    private var oldAlignmentLines: MutableMap<AlignmentLine, Int>? = null
+
+    override val providedAlignmentLines: Set<AlignmentLine>
+        get() = _measureResult?.alignmentLines?.keys ?: emptySet()
+
     /**
      * Called when the width or height of [measureResult] change. The object instance pointed to
      * by [measureResult] may or may not have changed.
@@ -190,6 +221,11 @@
             } else {
                 wrappedBy?.invalidateLayer()
             }
+            if (wrapped?.layoutNode != layoutNode) {
+                layoutNode.onAlignmentsChanged()
+            } else {
+                layoutNode.parent?.onAlignmentsChanged()
+            }
             layoutNode.owner?.onLayoutChange(layoutNode)
         }
         this.zIndex = zIndex
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutTreeConsistencyChecker.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutTreeConsistencyChecker.kt
index 289268a..337e2b0 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutTreeConsistencyChecker.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutTreeConsistencyChecker.kt
@@ -68,7 +68,8 @@
                 return relayoutNodes.contains(this) ||
                     parentLayoutState == LayoutNode.LayoutState.NeedsRemeasure ||
                     parentLayoutState == LayoutNode.LayoutState.NeedsRelayout ||
-                    parentLayoutState == LayoutNode.LayoutState.Measuring
+                    parentLayoutState == LayoutNode.LayoutState.Measuring ||
+                    parentLayoutState == LayoutNode.LayoutState.LayingOut
             }
         }
         return true
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt
index 33e625a..02ec181 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt
@@ -23,7 +23,6 @@
 import androidx.compose.ui.node.LayoutNode.LayoutState.Ready
 import androidx.compose.ui.node.LayoutNode.UsageByParent.InLayoutBlock
 import androidx.compose.ui.node.LayoutNode.UsageByParent.InMeasureBlock
-import androidx.compose.ui.node.LayoutNode.UsageByParent.NotUsed
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.util.fastForEach
 
@@ -200,13 +199,9 @@
             duringMeasureLayout = true
             try {
                 relayoutNodes.popEach { layoutNode ->
-                    val alignmentLinesOwner = layoutNode.alignmentLinesQueryOwner
                     if (layoutNode.isPlaced ||
                         layoutNode.canAffectParent ||
-                        (
-                            alignmentLinesOwner != null && alignmentLinesOwner
-                                .alignmentUsageByParent != NotUsed
-                            )
+                        layoutNode.alignmentLines.required
                     ) {
                         if (layoutNode.layoutState == NeedsRemeasure) {
                             if (doRemeasure(layoutNode, rootConstraints)) {
@@ -266,5 +261,5 @@
 
     private val LayoutNode.canAffectParent
         get() = layoutState == NeedsRemeasure &&
-            (measuredByParent == InMeasureBlock || alignmentLinesQueryOwner != null)
+            (measuredByParent == InMeasureBlock || alignmentLines.required)
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OnGloballyPositionedModifierWrapper.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OnGloballyPositionedModifierWrapper.kt
index 21a928e..9e4370a 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OnGloballyPositionedModifierWrapper.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OnGloballyPositionedModifierWrapper.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.ui.node
 
+import androidx.compose.ui.layout.AlignmentLine
 import androidx.compose.ui.layout.OnGloballyPositionedModifier
 
 /**
@@ -24,4 +25,17 @@
 internal class OnGloballyPositionedModifierWrapper(
     wrapped: LayoutNodeWrapper,
     modifier: OnGloballyPositionedModifier
-) : DelegatingLayoutNodeWrapper<OnGloballyPositionedModifier>(wrapped, modifier)
+) : DelegatingLayoutNodeWrapper<OnGloballyPositionedModifier>(wrapped, modifier) {
+    override val providedAlignmentLines: Set<AlignmentLine>
+        get() {
+            val result = mutableSetOf<AlignmentLine>()
+            layoutNode
+            var wrapper = wrapped as LayoutNodeWrapper?
+            while (wrapper != null) {
+                result += wrapper.providedAlignmentLines
+                if (wrapper == layoutNode.innerLayoutNodeWrapper) break
+                wrapper = wrapper.wrapped
+            }
+            return result
+        }
+}
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OuterMeasurablePlaceable.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OuterMeasurablePlaceable.kt
index eadbc1c..6ca6b5f 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OuterMeasurablePlaceable.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OuterMeasurablePlaceable.kt
@@ -36,9 +36,10 @@
         check(measuredOnce)
         return measurementConstraints
     }
+    internal var duringAlignmentLinesQuery = false
+
     private var lastPosition: IntOffset = IntOffset.Zero
     private var lastLayerBlock: (GraphicsLayerScope.() -> Unit)? = null
-    private var lastProvidedAlignmentLines: MutableMap<AlignmentLine, Int>? = null
     private var lastZIndex: Float = 0f
 
     /**
@@ -87,6 +88,8 @@
         if (layoutNode.layoutState == LayoutState.NeedsRemeasure ||
             measurementConstraints != constraints
         ) {
+            layoutNode.alignmentLines.usedByModifierMeasurement = false
+            layoutNode._children.forEach { it.alignmentLines.usedDuringParentMeasurement = false }
             measuredOnce = true
             layoutNode.layoutState = LayoutState.Measuring
             measurementConstraints = constraints
@@ -94,8 +97,12 @@
             owner.snapshotObserver.observeMeasureSnapshotReads(layoutNode) {
                 outerWrapper.measure(constraints)
             }
-            layoutNode.layoutState = LayoutState.NeedsRelayout
-            notifyAlignmentChanges()
+            // The resulting layout state might be Ready. This can happen when the layout node's
+            // own modifier is querying an alignment line during measurement, therefore we
+            // need to also layout the layout node.
+            if (layoutNode.layoutState == LayoutState.Measuring) {
+                layoutNode.layoutState = LayoutState.NeedsRelayout
+            }
             val sizeChanged = outerWrapper.size != outerWrapperPreviousMeasuredSize ||
                 outerWrapper.width != width ||
                 outerWrapper.height != height
@@ -106,26 +113,6 @@
         return false
     }
 
-    private fun notifyAlignmentChanges() {
-        // optimized to only create a lastProvidedAlignmentLines when we do have non empty map
-        if (layoutNode.providedAlignmentLines.isNotEmpty()) {
-            val previous = lastProvidedAlignmentLines ?: mutableMapOf<AlignmentLine, Int>().also {
-                lastProvidedAlignmentLines = it
-            }
-            if (layoutNode.providedAlignmentLines != previous) {
-                previous.clear()
-                previous.putAll(layoutNode.providedAlignmentLines)
-                layoutNode.onAlignmentsChanged()
-            }
-        } else {
-            val previous = lastProvidedAlignmentLines
-            if (previous != null && previous.isNotEmpty()) {
-                previous.clear()
-                layoutNode.onAlignmentsChanged()
-            }
-        }
-    }
-
     // We are setting our measuredSize to match the coerced outerWrapper size, to prevent
     // double offseting for layout cooperation. However, this means that here we need
     // to override these getters to make the measured values correct in Measured.
@@ -133,7 +120,17 @@
     override val measuredWidth: Int get() = outerWrapper.measuredWidth
     override val measuredHeight: Int get() = outerWrapper.measuredHeight
 
-    override fun get(alignmentLine: AlignmentLine): Int = outerWrapper[alignmentLine]
+    override fun get(alignmentLine: AlignmentLine): Int {
+        if (layoutNode.parent?.layoutState == LayoutState.Measuring) {
+            layoutNode.alignmentLines.usedDuringParentMeasurement = true
+        } else if (layoutNode.parent?.layoutState == LayoutState.LayingOut) {
+            layoutNode.alignmentLines.usedDuringParentLayout = true
+        }
+        duringAlignmentLinesQuery = true
+        val result = outerWrapper[alignmentLine]
+        duringAlignmentLinesQuery = false
+        return result
+    }
 
     override fun placeAt(
         position: IntOffset,
@@ -144,6 +141,7 @@
         lastPosition = position
         lastZIndex = zIndex
         lastLayerBlock = layerBlock
+        layoutNode.alignmentLines.usedByModifierLayout = false
         with(PlacementScope) {
             if (layerBlock == null) {
                 outerWrapper.place(position, lastZIndex)
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeLayer.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeLayer.desktop.kt
index 296411b..03dbbbc 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeLayer.desktop.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeLayer.desktop.kt
@@ -54,7 +54,12 @@
     //  method?
     private val events = AWTDebounceEventQueue()
 
-    internal val wrapped = Wrapped()
+    internal val wrapped = Wrapped().apply {
+        onStateChanged(SkiaLayer.PropertyKind.ContentScale) { _ ->
+            resetDensity()
+        }
+    }
+
     internal val owners: DesktopOwners = DesktopOwners(
         coroutineScope,
         wrapped,
@@ -82,12 +87,7 @@
             initOwner()
         }
 
-        override fun contentScaleChanged() {
-            super.contentScaleChanged()
-            resetDensity()
-        }
-
-        private fun resetDensity() {
+        internal fun resetDensity() {
             this@ComposeLayer.density = detectCurrentDensity()
             owner?.density = density
         }
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposePanel.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposePanel.desktop.kt
index cfe712b..a29563d 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposePanel.desktop.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposePanel.desktop.kt
@@ -18,6 +18,7 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import org.jetbrains.skiko.ClipComponent
+import org.jetbrains.skiko.GraphicsApi
 import java.awt.Color
 import java.awt.Component
 import javax.swing.JLayeredPane
@@ -112,4 +113,12 @@
             layer!!.component.requestFocus()
         }
     }
+
+    /**
+     * Returns low-level rendering API used for rendering in this ComposeWindow. API is
+     * automatically selected based on operating system, graphical hardware and `SKIKO_RENDER_API`
+     * environment variable.
+     */
+    val renderApi: GraphicsApi
+        get() = if (layer != null) layer!!.component.renderApi else GraphicsApi.UNKNOWN
 }
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeWindow.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeWindow.desktop.kt
index 273b3b0..9b865cf 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeWindow.desktop.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/ComposeWindow.desktop.kt
@@ -20,6 +20,7 @@
 import androidx.compose.runtime.CompositionLocalProvider
 import org.jetbrains.skiko.ClipComponent
 import org.jetbrains.skiko.GraphicsApi
+import org.jetbrains.skiko.SkiaLayer
 import java.awt.Component
 import javax.swing.JFrame
 import javax.swing.JLayeredPane
@@ -98,15 +99,26 @@
     }
 
     /**
-     * Retrieve underlying platform-specific operating system handle for the window where ComposeWindow is rendered.
-     * Currently returns HWND on Windows, Drawable on X11 and 0 on macOS.
+     * Registers a task to run when the rendering API changes.
+     */
+    fun onRenderApiChanged(action: () -> Unit) {
+        layer.component.onStateChanged(SkiaLayer.PropertyKind.Renderer) {
+            action()
+        }
+    }
+
+    /**
+     * Retrieve underlying platform-specific operating system handle for the root window where
+     * ComposeWindow is rendered. Currently returns HWND on Windows, Display on X11 and NSWindow
+     * on macOS.
      */
     val windowHandle: Long
         get() = layer.component.windowHandle
 
     /**
-     * Returns low level rendering API used for rendering in this ComposeWindow. API is automatically selected based on
-     * operating system, graphical hardware and `SKIKO_RENDER_API` environment variable.
+     * Returns low-level rendering API used for rendering in this ComposeWindow. API is
+     * automatically selected based on operating system, graphical hardware and `SKIKO_RENDER_API`
+     * environment variable.
      */
     val renderApi: GraphicsApi
         get() = layer.component.renderApi
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/RecordingInputConnectionUpdateTextFieldValueTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/RecordingInputConnectionUpdateTextFieldValueTest.kt
index 2721714..bb39d23 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/RecordingInputConnectionUpdateTextFieldValueTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/RecordingInputConnectionUpdateTextFieldValueTest.kt
@@ -19,9 +19,9 @@
 import android.view.View
 import android.view.inputmethod.ExtractedText
 import android.view.inputmethod.InputConnection
-import android.view.inputmethod.InputMethodManager
 import androidx.compose.ui.text.TextRange
 import androidx.compose.ui.text.input.InputEventCallback2
+import androidx.compose.ui.text.input.InputMethodManager
 import androidx.compose.ui.text.input.RecordingInputConnection
 import androidx.compose.ui.text.input.TextFieldValue
 import com.google.common.truth.Truth.assertThat
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/TextInputServiceAndroidTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/TextInputServiceAndroidTest.kt
deleted file mode 100644
index 48050b9..0000000
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/TextInputServiceAndroidTest.kt
+++ /dev/null
@@ -1,693 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.ui.input
-
-import android.content.Context
-import android.text.InputType
-import android.view.View
-import android.view.inputmethod.EditorInfo
-import android.view.inputmethod.InputMethodManager
-import androidx.compose.ui.text.TextRange
-import androidx.compose.ui.text.input.ImeAction
-import androidx.compose.ui.text.input.ImeOptions
-import androidx.compose.ui.text.input.KeyboardCapitalization
-import androidx.compose.ui.text.input.KeyboardType
-import androidx.compose.ui.text.input.TextFieldValue
-import androidx.compose.ui.text.input.TextInputServiceAndroid
-import com.google.common.truth.Truth.assertThat
-import com.nhaarman.mockitokotlin2.eq
-import com.nhaarman.mockitokotlin2.mock
-import com.nhaarman.mockitokotlin2.whenever
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class TextInputServiceAndroidTest {
-
-    private lateinit var textInputService: TextInputServiceAndroid
-    private lateinit var imm: InputMethodManager
-
-    @Before
-    fun setup() {
-        imm = mock()
-        val view: View = mock()
-        val context: Context = mock()
-        whenever(context.getSystemService(eq(Context.INPUT_METHOD_SERVICE))).thenReturn(imm)
-        whenever(view.context).thenReturn(context)
-        textInputService = TextInputServiceAndroid(view)
-    }
-
-    @Test
-    fun test_fill_editor_info_text() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Text,
-                imeAction = ImeAction.Default
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_UNSPECIFIED
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_ascii() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Default
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
-            assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_UNSPECIFIED
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_number() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Number,
-                imeAction = ImeAction.Default
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_NUMBER and info.inputType) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_UNSPECIFIED
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_phone() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Phone,
-                imeAction = ImeAction.Default
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_PHONE and info.inputType) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_UNSPECIFIED
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_uri() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Uri,
-                imeAction = ImeAction.Default
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
-            assertThat((InputType.TYPE_TEXT_VARIATION_URI and info.inputType) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_UNSPECIFIED
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_email() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Email,
-                imeAction = ImeAction.Default
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
-            assertThat((InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS and info.inputType) != 0)
-                .isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_UNSPECIFIED
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_password() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Password,
-                imeAction = ImeAction.Default
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
-            assertThat((InputType.TYPE_TEXT_VARIATION_PASSWORD and info.inputType) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_UNSPECIFIED
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_number_password() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.NumberPassword,
-                imeAction = ImeAction.Default
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_NUMBER and info.inputType) != 0).isTrue()
-            assertThat((InputType.TYPE_NUMBER_VARIATION_PASSWORD and info.inputType) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_UNSPECIFIED
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_action_none() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.None
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
-            assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_NONE
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_action_go() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Go
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
-            assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_GO
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_action_next() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Next
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
-            assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_NEXT
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_action_previous() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Previous
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
-            assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_PREVIOUS
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_action_search() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Search,
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
-            assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_SEARCH
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_action_send() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Send
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
-            assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_SEND
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_action_done() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Done
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_CLASS_TEXT and info.inputType) != 0).isTrue()
-            assertThat((EditorInfo.IME_FLAG_FORCE_ASCII and info.imeOptions) != 0).isTrue()
-            assertThat(
-                (EditorInfo.IME_MASK_ACTION and info.imeOptions)
-                    == EditorInfo.IME_ACTION_DONE
-            ).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_multi_line() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                singleLine = false,
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Done
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_TEXT_FLAG_MULTI_LINE and info.inputType) == 0).isFalse()
-            assertThat((EditorInfo.IME_FLAG_NO_ENTER_ACTION and info.imeOptions) == 0).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_multi_line_with_default_action() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                singleLine = false,
-                keyboardType = KeyboardType.Text,
-                imeAction = ImeAction.Default
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_TEXT_FLAG_MULTI_LINE and info.inputType) == 0).isFalse()
-            assertThat((EditorInfo.IME_FLAG_NO_ENTER_ACTION and info.imeOptions) == 0).isFalse()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_single_line() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                singleLine = true,
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Done
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_TEXT_FLAG_MULTI_LINE and info.inputType) == 0).isTrue()
-            assertThat((EditorInfo.IME_FLAG_NO_ENTER_ACTION and info.imeOptions) == 0).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_single_line_changes_ime_from_unspecified_to_done() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                singleLine = true,
-                keyboardType = KeyboardType.Text,
-                imeAction = ImeAction.Default
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((EditorInfo.IME_ACTION_DONE and info.imeOptions) == 0).isFalse()
-            assertThat((EditorInfo.IME_ACTION_UNSPECIFIED and info.imeOptions) == 0).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_multi_line_not_set_when_input_type_is_not_text() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                singleLine = false,
-                keyboardType = KeyboardType.Number,
-                imeAction = ImeAction.Done
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_TEXT_FLAG_MULTI_LINE and info.inputType) == 0).isTrue()
-            assertThat((EditorInfo.IME_FLAG_NO_ENTER_ACTION and info.imeOptions) == 0).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_capitalization_none() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                capitalization = KeyboardCapitalization.None,
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Done
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isTrue()
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isTrue()
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_capitalization_characters() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                capitalization = KeyboardCapitalization.Characters,
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Done
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isFalse()
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isTrue()
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_capitalization_words() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                capitalization = KeyboardCapitalization.Words,
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Done
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isTrue()
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isFalse()
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_capitalization_sentences() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                capitalization = KeyboardCapitalization.Sentences,
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Done,
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isTrue()
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isTrue()
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isFalse()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_capitalization_not_added_when_input_type_is_not_text() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                capitalization = KeyboardCapitalization.Sentences,
-                keyboardType = KeyboardType.Number,
-                imeAction = ImeAction.Done,
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS and info.inputType) == 0).isTrue()
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_WORDS and info.inputType) == 0).isTrue()
-            assertThat((InputType.TYPE_TEXT_FLAG_CAP_SENTENCES and info.inputType) == 0).isTrue()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_auto_correct_on() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                autoCorrect = true,
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Done
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_TEXT_FLAG_AUTO_CORRECT and info.inputType) == 0).isFalse()
-        }
-    }
-
-    @Test
-    fun test_fill_editor_info_auto_correct_off() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                autoCorrect = false,
-                keyboardType = KeyboardType.Ascii,
-                imeAction = ImeAction.Done
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_TEXT_FLAG_AUTO_CORRECT and info.inputType) == 0).isTrue()
-        }
-    }
-
-    @Test
-    fun autocorrect_not_added_when_input_type_is_not_text() {
-        textInputService.startInput(
-            value = TextFieldValue(""),
-            imeOptions = ImeOptions(
-                autoCorrect = true,
-                keyboardType = KeyboardType.Number,
-                imeAction = ImeAction.Done
-            ),
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat((InputType.TYPE_TEXT_FLAG_AUTO_CORRECT and info.inputType) == 0).isTrue()
-        }
-    }
-
-    @Test
-    fun initial_default_selection_info_is_set() {
-        textInputService.startInput(
-            value = TextFieldValue(),
-            imeOptions = ImeOptions.Default,
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat(info.initialSelStart).isEqualTo(0)
-            assertThat(info.initialSelEnd).isEqualTo(0)
-        }
-    }
-
-    @Test
-    fun initial_selection_info_is_set() {
-        val selection = TextRange(1, 2)
-        textInputService.startInput(
-            value = TextFieldValue("abc", selection),
-            imeOptions = ImeOptions.Default,
-            onEditCommand = {},
-            onImeActionPerformed = {}
-        )
-
-        EditorInfo().let { info ->
-            textInputService.createInputConnection(info)
-            assertThat(info.initialSelStart).isEqualTo(selection.start)
-            assertThat(info.initialSelEnd).isEqualTo(selection.end)
-        }
-    }
-}
\ No newline at end of file
diff --git a/fragment/fragment-lint/build.gradle b/fragment/fragment-lint/build.gradle
index 446b4be..da2c726 100644
--- a/fragment/fragment-lint/build.gradle
+++ b/fragment/fragment-lint/build.gradle
@@ -25,13 +25,7 @@
 }
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly(LINT_API_LATEST)
-    } else {
-        compileOnly(LINT_API_MIN)
-    }
+    compileOnly(LINT_API_MIN)
     compileOnly(KOTLIN_STDLIB)
 
     testImplementation(KOTLIN_STDLIB)
diff --git a/fragment/fragment-testing-lint/build.gradle b/fragment/fragment-testing-lint/build.gradle
index e8edd4f..9242788 100644
--- a/fragment/fragment-testing-lint/build.gradle
+++ b/fragment/fragment-testing-lint/build.gradle
@@ -25,13 +25,7 @@
 }
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly(LINT_API_LATEST)
-    } else {
-        compileOnly(LINT_API_MIN)
-    }
+    compileOnly(LINT_API_MIN)
     compileOnly(KOTLIN_STDLIB)
 
     testImplementation(KOTLIN_STDLIB)
diff --git a/fragment/fragment/api/current.txt b/fragment/fragment/api/current.txt
index 83ddaab..0ab03c8 100644
--- a/fragment/fragment/api/current.txt
+++ b/fragment/fragment/api/current.txt
@@ -476,6 +476,7 @@
 
   public static final class FragmentStrictMode.Policy.Builder {
     ctor public FragmentStrictMode.Policy.Builder();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder allowViolation(Class<? extends androidx.fragment.app.Fragment>, Class<? extends androidx.fragment.app.strictmode.Violation>);
     method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy build();
     method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectFragmentReuse();
     method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectFragmentTagUsage();
diff --git a/fragment/fragment/api/public_plus_experimental_current.txt b/fragment/fragment/api/public_plus_experimental_current.txt
index 6cb05d1..dcbd3b6 100644
--- a/fragment/fragment/api/public_plus_experimental_current.txt
+++ b/fragment/fragment/api/public_plus_experimental_current.txt
@@ -482,6 +482,7 @@
 
   public static final class FragmentStrictMode.Policy.Builder {
     ctor public FragmentStrictMode.Policy.Builder();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder allowViolation(Class<? extends androidx.fragment.app.Fragment>, Class<? extends androidx.fragment.app.strictmode.Violation>);
     method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy build();
     method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectFragmentReuse();
     method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectFragmentTagUsage();
diff --git a/fragment/fragment/api/restricted_current.txt b/fragment/fragment/api/restricted_current.txt
index 680d7b8..9fe9aaa 100644
--- a/fragment/fragment/api/restricted_current.txt
+++ b/fragment/fragment/api/restricted_current.txt
@@ -512,6 +512,7 @@
 
   public static final class FragmentStrictMode.Policy.Builder {
     ctor public FragmentStrictMode.Policy.Builder();
+    method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder allowViolation(Class<? extends androidx.fragment.app.Fragment>, Class<? extends androidx.fragment.app.strictmode.Violation>);
     method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy build();
     method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectFragmentReuse();
     method public androidx.fragment.app.strictmode.FragmentStrictMode.Policy.Builder detectFragmentTagUsage();
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/strictmode/FragmentStrictModeTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/strictmode/FragmentStrictModeTest.kt
index 87b0c07..44e58d5 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/strictmode/FragmentStrictModeTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/strictmode/FragmentStrictModeTest.kt
@@ -36,6 +36,8 @@
 @MediumTest
 @RunWith(AndroidJUnit4::class)
 public class FragmentStrictModeTest {
+    private val fragmentClass = StrictFragment::class.java
+
     private lateinit var originalPolicy: FragmentStrictMode.Policy
 
     @Before
@@ -293,4 +295,38 @@
             assertThat(violation).isInstanceOf(WrongFragmentContainerViolation::class.java)
         }
     }
+
+    @Test
+    public fun detectAllowedViolations() {
+        val violationClass1 = RetainInstanceUsageViolation::class.java
+        val violationClass2 = SetUserVisibleHintViolation::class.java
+        val violationClassList = listOf(violationClass1, violationClass2)
+
+        var violation: Violation? = null
+        var policyBuilder = FragmentStrictMode.Policy.Builder()
+            .detectRetainInstanceUsage()
+            .detectSetUserVisibleHint()
+            .penaltyListener { violation = it }
+        for (violationClass in violationClassList) {
+            policyBuilder = policyBuilder.allowViolation(fragmentClass, violationClass)
+        }
+        FragmentStrictMode.setDefaultPolicy(policyBuilder.build())
+
+        @Suppress("DEPRECATION")
+        StrictFragment().retainInstance = true
+        assertThat(violation).isNotInstanceOf(violationClass1)
+        assertThat(violation).isNotInstanceOf(violationClass2)
+
+        violation = null
+        @Suppress("DEPRECATION")
+        StrictFragment().retainInstance
+        assertThat(violation).isNotInstanceOf(violationClass1)
+        assertThat(violation).isNotInstanceOf(violationClass2)
+
+        violation = null
+        @Suppress("DEPRECATION")
+        StrictFragment().userVisibleHint = true
+        assertThat(violation).isNotInstanceOf(violationClass1)
+        assertThat(violation).isNotInstanceOf(violationClass2)
+    }
 }
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
index 1c7ab0e..9f04df6 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
@@ -93,7 +93,10 @@
  */
 public abstract class FragmentManager implements FragmentResultOwner {
     private static boolean DEBUG = false;
-    static final String TAG = "FragmentManager";
+
+    /** @hide */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    public static final String TAG = "FragmentManager";
 
     /**
      * Control whether the framework's internal fragment manager debugging
@@ -108,7 +111,9 @@
         FragmentManager.DEBUG = enabled;
     }
 
-    static boolean isLoggingEnabled(int level) {
+    /** @hide */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    public static boolean isLoggingEnabled(int level) {
         return DEBUG || Log.isLoggable(TAG, level);
     }
 
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/FragmentStrictMode.java b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/FragmentStrictMode.java
index 65ad631..4c4368a 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/FragmentStrictMode.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/FragmentStrictMode.java
@@ -29,8 +29,9 @@
 import androidx.fragment.app.FragmentContainerView;
 import androidx.fragment.app.FragmentManager;
 
-import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -84,16 +85,30 @@
      * different penalties for different detected actions.
      */
     public static final class Policy {
-        private final Set<Flag> flags;
-        private final OnViolationListener listener;
+        private final Set<Flag> mFlags;
+        private final OnViolationListener mListener;
+        private final Map<Class<? extends Fragment>,
+                Set<Class<? extends Violation>>> mAllowedViolations;
 
         /** The default, lax policy which doesn't catch anything. */
         @NonNull
-        public static final Policy LAX = new Policy(new HashSet<Flag>(), null);
+        public static final Policy LAX = new Policy(new HashSet<>(), null, new HashMap<>());
 
-        private Policy(@NonNull Set<Flag> flags, @Nullable OnViolationListener listener) {
-            this.flags = Collections.unmodifiableSet(flags);
-            this.listener = listener;
+        private Policy(
+                @NonNull Set<Flag> flags,
+                @Nullable OnViolationListener listener,
+                @NonNull Map<Class<? extends Fragment>,
+                        Set<Class<? extends Violation>>> allowedViolations) {
+            this.mFlags = new HashSet<>(flags);
+            this.mListener = listener;
+
+            Map<Class<? extends Fragment>, Set<Class<? extends Violation>>>
+                    newAllowedViolationsMap = new HashMap<>();
+            for (Map.Entry<Class<? extends Fragment>,
+                    Set<Class<? extends Violation>>> entry : allowedViolations.entrySet()) {
+                newAllowedViolationsMap.put(entry.getKey(), new HashSet<>(entry.getValue()));
+            }
+            this.mAllowedViolations = newAllowedViolationsMap;
         }
 
         /**
@@ -105,19 +120,22 @@
          * order is insignificant: all penalties apply to all detected problems.
          */
         public static final class Builder {
-            private final Set<Flag> flags;
-            private OnViolationListener listener;
+            private final Set<Flag> mFlags;
+            private OnViolationListener mListener;
+            private final Map<Class<? extends Fragment>,
+                    Set<Class<? extends Violation>>> mAllowedViolations;
 
             /** Create a Builder that detects nothing and has no violations. */
             public Builder() {
-                flags = new HashSet<>();
+                mFlags = new HashSet<>();
+                mAllowedViolations = new HashMap<>();
             }
 
             /** Log detected violations to the system log. */
             @NonNull
             @SuppressLint("BuilderSetStyle")
             public Builder penaltyLog() {
-                flags.add(Flag.PENALTY_LOG);
+                mFlags.add(Flag.PENALTY_LOG);
                 return this;
             }
 
@@ -129,7 +147,7 @@
             @NonNull
             @SuppressLint("BuilderSetStyle")
             public Builder penaltyDeath() {
-                flags.add(Flag.PENALTY_DEATH);
+                mFlags.add(Flag.PENALTY_DEATH);
                 return this;
             }
 
@@ -140,7 +158,7 @@
             @NonNull
             @SuppressLint("BuilderSetStyle")
             public Builder penaltyListener(@NonNull OnViolationListener listener) {
-                this.listener = listener;
+                this.mListener = listener;
                 return this;
             }
 
@@ -151,7 +169,7 @@
             @NonNull
             @SuppressLint("BuilderSetStyle")
             public Builder detectFragmentReuse() {
-                flags.add(Flag.DETECT_FRAGMENT_REUSE);
+                mFlags.add(Flag.DETECT_FRAGMENT_REUSE);
                 return this;
             }
 
@@ -159,7 +177,7 @@
             @NonNull
             @SuppressLint("BuilderSetStyle")
             public Builder detectFragmentTagUsage() {
-                flags.add(Flag.DETECT_FRAGMENT_TAG_USAGE);
+                mFlags.add(Flag.DETECT_FRAGMENT_TAG_USAGE);
                 return this;
             }
 
@@ -170,7 +188,7 @@
             @NonNull
             @SuppressLint("BuilderSetStyle")
             public Builder detectRetainInstanceUsage() {
-                flags.add(Flag.DETECT_RETAIN_INSTANCE_USAGE);
+                mFlags.add(Flag.DETECT_RETAIN_INSTANCE_USAGE);
                 return this;
             }
 
@@ -178,7 +196,7 @@
             @NonNull
             @SuppressLint("BuilderSetStyle")
             public Builder detectSetUserVisibleHint() {
-                flags.add(Flag.DETECT_SET_USER_VISIBLE_HINT);
+                mFlags.add(Flag.DETECT_SET_USER_VISIBLE_HINT);
                 return this;
             }
 
@@ -189,7 +207,7 @@
             @NonNull
             @SuppressLint("BuilderSetStyle")
             public Builder detectTargetFragmentUsage() {
-                flags.add(Flag.DETECT_TARGET_FRAGMENT_USAGE);
+                mFlags.add(Flag.DETECT_TARGET_FRAGMENT_USAGE);
                 return this;
             }
 
@@ -200,7 +218,29 @@
             @NonNull
             @SuppressLint("BuilderSetStyle")
             public Builder detectWrongFragmentContainer() {
-                flags.add(Flag.DETECT_WRONG_FRAGMENT_CONTAINER);
+                mFlags.add(Flag.DETECT_WRONG_FRAGMENT_CONTAINER);
+                return this;
+            }
+
+            /**
+             * Allow the specified {@link Fragment} class to bypass penalties for the
+             * specified {@link Violation}, if detected.
+             *
+             * By default, all {@link Fragment} classes will incur penalties for any
+             * detected {@link Violation}.
+             */
+            @NonNull
+            @SuppressLint("BuilderSetStyle")
+            public Builder allowViolation(
+                    @NonNull Class<? extends Fragment> fragmentClass,
+                    @NonNull Class<? extends Violation> violationClass) {
+                Set<Class<? extends Violation>> violationsToBypass =
+                        mAllowedViolations.get(fragmentClass);
+                if (violationsToBypass == null) {
+                    violationsToBypass = new HashSet<>();
+                }
+                violationsToBypass.add(violationClass);
+                mAllowedViolations.put(fragmentClass, violationsToBypass);
                 return this;
             }
 
@@ -212,10 +252,10 @@
              */
             @NonNull
             public Policy build() {
-                if (listener == null && !flags.contains(Flag.PENALTY_DEATH)) {
+                if (mListener == null && !mFlags.contains(Flag.PENALTY_DEATH)) {
                     penaltyLog();
                 }
-                return new Policy(flags, listener);
+                return new Policy(mFlags, mListener, mAllowedViolations);
             }
         }
     }
@@ -251,56 +291,109 @@
 
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     public static void onFragmentReuse(@NonNull Fragment fragment) {
+        Violation violation = new FragmentReuseViolation();
+        logIfDebuggingEnabled(fragment.getClass().getName(), violation);
+
         Policy policy = getNearestPolicy(fragment);
-        if (policy.flags.contains(Flag.DETECT_FRAGMENT_REUSE)) {
-            handlePolicyViolation(fragment, policy, new FragmentReuseViolation());
+        if (policy.mFlags.contains(Flag.DETECT_FRAGMENT_REUSE)
+                && shouldHandlePolicyViolation(
+                fragment.getClass(), policy, violation.getClass())) {
+            handlePolicyViolation(fragment, policy, violation);
         }
     }
 
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     public static void onFragmentTagUsage(@NonNull Fragment fragment) {
+        Violation violation = new FragmentTagUsageViolation();
+        logIfDebuggingEnabled(fragment.getClass().getName(), violation);
+
         Policy policy = getNearestPolicy(fragment);
-        if (policy.flags.contains(Flag.DETECT_FRAGMENT_TAG_USAGE)) {
-            handlePolicyViolation(fragment, policy, new FragmentTagUsageViolation());
+        if (policy.mFlags.contains(Flag.DETECT_FRAGMENT_TAG_USAGE)
+                && shouldHandlePolicyViolation(
+                fragment.getClass(), policy, violation.getClass())) {
+            handlePolicyViolation(fragment, policy, violation);
         }
     }
 
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     public static void onRetainInstanceUsage(@NonNull Fragment fragment) {
+        Violation violation = new RetainInstanceUsageViolation();
+        logIfDebuggingEnabled(fragment.getClass().getName(), violation);
+
         Policy policy = getNearestPolicy(fragment);
-        if (policy.flags.contains(Flag.DETECT_RETAIN_INSTANCE_USAGE)) {
-            handlePolicyViolation(fragment, policy, new RetainInstanceUsageViolation());
+        if (policy.mFlags.contains(Flag.DETECT_RETAIN_INSTANCE_USAGE)
+                && shouldHandlePolicyViolation(
+                fragment.getClass(), policy, violation.getClass())) {
+            handlePolicyViolation(fragment, policy, violation);
         }
     }
 
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     public static void onSetUserVisibleHint(@NonNull Fragment fragment) {
+        Violation violation = new SetUserVisibleHintViolation();
+        logIfDebuggingEnabled(fragment.getClass().getName(), violation);
+
         Policy policy = getNearestPolicy(fragment);
-        if (policy.flags.contains(Flag.DETECT_SET_USER_VISIBLE_HINT)) {
-            handlePolicyViolation(fragment, policy, new SetUserVisibleHintViolation());
+        if (policy.mFlags.contains(Flag.DETECT_SET_USER_VISIBLE_HINT)
+                && shouldHandlePolicyViolation(
+                fragment.getClass(), policy, violation.getClass())) {
+            handlePolicyViolation(fragment, policy, violation);
         }
     }
 
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     public static void onTargetFragmentUsage(@NonNull Fragment fragment) {
+        Violation violation = new TargetFragmentUsageViolation();
+        logIfDebuggingEnabled(fragment.getClass().getName(), violation);
+
         Policy policy = getNearestPolicy(fragment);
-        if (policy.flags.contains(Flag.DETECT_TARGET_FRAGMENT_USAGE)) {
-            handlePolicyViolation(fragment, policy, new TargetFragmentUsageViolation());
+        if (policy.mFlags.contains(Flag.DETECT_TARGET_FRAGMENT_USAGE)
+                && shouldHandlePolicyViolation(
+                fragment.getClass(), policy, violation.getClass())) {
+            handlePolicyViolation(fragment, policy, violation);
         }
     }
 
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     public static void onWrongFragmentContainer(@NonNull Fragment fragment) {
+        Violation violation = new WrongFragmentContainerViolation();
+        logIfDebuggingEnabled(fragment.getClass().getName(), violation);
+
         Policy policy = getNearestPolicy(fragment);
-        if (policy.flags.contains(Flag.DETECT_WRONG_FRAGMENT_CONTAINER)) {
-            handlePolicyViolation(fragment, policy, new WrongFragmentContainerViolation());
+        if (policy.mFlags.contains(Flag.DETECT_WRONG_FRAGMENT_CONTAINER)
+                && shouldHandlePolicyViolation(
+                fragment.getClass(), policy, violation.getClass())) {
+            handlePolicyViolation(fragment, policy, violation);
         }
     }
 
     @VisibleForTesting
     static void onPolicyViolation(@NonNull Fragment fragment, @NonNull Violation violation) {
+        logIfDebuggingEnabled(fragment.getClass().getName(), violation);
+
         Policy policy = getNearestPolicy(fragment);
-        handlePolicyViolation(fragment, policy, violation);
+        if (shouldHandlePolicyViolation(fragment.getClass(), policy, violation.getClass())) {
+            handlePolicyViolation(fragment, policy, violation);
+        }
+    }
+
+    private static void logIfDebuggingEnabled(
+            @NonNull String fragmentName,
+            @NonNull final Violation violation
+    ) {
+        if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
+            Log.d(FragmentManager.TAG, "StrictMode violation in " + fragmentName,
+                    violation);
+        }
+    }
+
+    private static boolean shouldHandlePolicyViolation(
+            @NonNull Class<? extends Fragment> fragmentClass,
+            @NonNull final Policy policy,
+            @NonNull Class<? extends Violation> violationClass) {
+        Set<Class<? extends Violation>> violationsToBypass =
+                policy.mAllowedViolations.get(fragmentClass);
+        return violationsToBypass == null || !violationsToBypass.contains(violationClass);
     }
 
     private static void handlePolicyViolation(
@@ -310,20 +403,20 @@
     ) {
         final String fragmentName = fragment.getClass().getName();
 
-        if (policy.flags.contains(Flag.PENALTY_LOG)) {
+        if (policy.mFlags.contains(Flag.PENALTY_LOG)) {
             Log.d(TAG, "Policy violation in " + fragmentName, violation);
         }
 
-        if (policy.listener != null) {
+        if (policy.mListener != null) {
             runOnHostThread(fragment, new Runnable() {
                 @Override
                 public void run() {
-                    policy.listener.onViolation(violation);
+                    policy.mListener.onViolation(violation);
                 }
             });
         }
 
-        if (policy.flags.contains(Flag.PENALTY_DEATH)) {
+        if (policy.mFlags.contains(Flag.PENALTY_DEATH)) {
             runOnHostThread(fragment, new Runnable() {
                 @Override
                 public void run() {
diff --git a/leanback/leanback/src/androidTest/java/androidx/leanback/app/DetailsFragmentTest.java b/leanback/leanback/src/androidTest/java/androidx/leanback/app/DetailsFragmentTest.java
index 3813ac5..2c342b4 100644
--- a/leanback/leanback/src/androidTest/java/androidx/leanback/app/DetailsFragmentTest.java
+++ b/leanback/leanback/src/androidTest/java/androidx/leanback/app/DetailsFragmentTest.java
@@ -1261,16 +1261,17 @@
                         View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN),
                 1000);
 
-        View fragmentView = activity.getTestFragment().getView();
-        RowsFragment rowsSupportFragment =
-                ((DetailsFragmentEntranceTransition) activity.getTestFragment())
-                        .getRowsFragment();
+        DetailsFragmentEntranceTransition detailsFragment =
+                (DetailsFragmentEntranceTransition) activity.getTestFragment();
+        View fragmentView = detailsFragment.getView();
+        RowsFragment rowsSupportFragment = detailsFragment.getRowsFragment();
         VerticalGridView gridView = rowsSupportFragment.getVerticalGridView();
         LeakDetector leakDetector = new LeakDetector();
         leakDetector.observeObject(fragmentView);
         // Note: RowsFragment is referred by childFragmentManager of details fragment.
         leakDetector.observeObject(gridView);
         leakDetector.observeObject(gridView.getRecycledViewPool());
+        leakDetector.observeObject(detailsFragment.mDetailsBackgroundController.mCoverBitmap);
         for (int i = 0; i < gridView.getChildCount(); i++) {
             leakDetector.observeObject(gridView.getChildAt(i));
         }
@@ -1289,6 +1290,7 @@
                 return emptyFragment.isResumed();
             }
         });
+        assertTrue(detailsFragment.mBackgroundDrawable != null);
         leakDetector.assertNoLeak();
     }
 }
diff --git a/leanback/leanback/src/androidTest/java/androidx/leanback/app/DetailsSupportFragmentTest.java b/leanback/leanback/src/androidTest/java/androidx/leanback/app/DetailsSupportFragmentTest.java
index 38a1f78..0f63d6d 100644
--- a/leanback/leanback/src/androidTest/java/androidx/leanback/app/DetailsSupportFragmentTest.java
+++ b/leanback/leanback/src/androidTest/java/androidx/leanback/app/DetailsSupportFragmentTest.java
@@ -1258,16 +1258,17 @@
                         View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN),
                 1000);
 
-        View fragmentView = activity.getTestFragment().getView();
-        RowsSupportFragment rowsSupportFragment =
-                ((DetailsSupportFragmentEntranceTransition) activity.getTestFragment())
-                        .getRowsSupportFragment();
+        DetailsSupportFragmentEntranceTransition detailsFragment =
+                (DetailsSupportFragmentEntranceTransition) activity.getTestFragment();
+        View fragmentView = detailsFragment.getView();
+        RowsSupportFragment rowsSupportFragment = detailsFragment.getRowsSupportFragment();
         VerticalGridView gridView = rowsSupportFragment.getVerticalGridView();
         LeakDetector leakDetector = new LeakDetector();
         leakDetector.observeObject(fragmentView);
         // Note: RowsSupportFragment is referred by childFragmentManager of details fragment.
         leakDetector.observeObject(gridView);
         leakDetector.observeObject(gridView.getRecycledViewPool());
+        leakDetector.observeObject(detailsFragment.mDetailsBackgroundController.mCoverBitmap);
         for (int i = 0; i < gridView.getChildCount(); i++) {
             leakDetector.observeObject(gridView.getChildAt(i));
         }
@@ -1286,6 +1287,7 @@
                 return emptyFragment.isResumed();
             }
         });
+        assertTrue(detailsFragment.mBackgroundDrawable != null);
         leakDetector.assertNoLeak();
     }
 }
diff --git a/leanback/leanback/src/main/java/androidx/leanback/app/DetailsFragment.java b/leanback/leanback/src/main/java/androidx/leanback/app/DetailsFragment.java
index 1d7a26ea..9cbfbfd 100644
--- a/leanback/leanback/src/main/java/androidx/leanback/app/DetailsFragment.java
+++ b/leanback/leanback/src/main/java/androidx/leanback/app/DetailsFragment.java
@@ -528,7 +528,6 @@
         }
         mRootView = null;
         mBackgroundView = null;
-        mBackgroundDrawable = null;
         mRowsFragment = null;
         mVideoFragment = null;
         mSceneAfterEntranceTransition = null;
diff --git a/leanback/leanback/src/main/java/androidx/leanback/app/DetailsSupportFragment.java b/leanback/leanback/src/main/java/androidx/leanback/app/DetailsSupportFragment.java
index 4d56fe1..f189253 100644
--- a/leanback/leanback/src/main/java/androidx/leanback/app/DetailsSupportFragment.java
+++ b/leanback/leanback/src/main/java/androidx/leanback/app/DetailsSupportFragment.java
@@ -523,7 +523,6 @@
         }
         mRootView = null;
         mBackgroundView = null;
-        mBackgroundDrawable = null;
         mRowsSupportFragment = null;
         mVideoSupportFragment = null;
         mSceneAfterEntranceTransition = null;
diff --git a/leanback/leanback/src/main/java/androidx/leanback/app/SearchFragment.java b/leanback/leanback/src/main/java/androidx/leanback/app/SearchFragment.java
index 38bcc52..dc49c69 100644
--- a/leanback/leanback/src/main/java/androidx/leanback/app/SearchFragment.java
+++ b/leanback/leanback/src/main/java/androidx/leanback/app/SearchFragment.java
@@ -389,7 +389,7 @@
         });
 
         if (!isSpeechRecognizerAvailable()) {
-            if(mSearchBar.hasFocus()) {
+            if (mSearchBar.hasFocus()) {
                 mSearchBar.findViewById(R.id.lb_search_text_editor).requestFocus();
             }
             mSearchBar.findViewById(R.id.lb_search_bar_speech_orb).setFocusable(false);
@@ -419,8 +419,7 @@
         mIsPaused = false;
         if (mSpeechRecognitionCallback == null && null == mSpeechRecognizer
                 && mSpeechRecognizerEnabled) {
-            mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(
-                    FragmentUtil.getContext(SearchFragment.this));
+            mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(FragmentUtil.getContext(SearchFragment.this));
             mSearchBar.setSpeechRecognizer(mSpeechRecognizer);
         }
         if (mPendingStartRecognitionWhenPaused) {
@@ -783,8 +782,7 @@
     }
 
     boolean isSpeechRecognizerAvailable() {
-        return SpeechRecognizer.isRecognitionAvailable(
-                FragmentUtil.getContext(SearchFragment.this));
+        return SpeechRecognizer.isRecognitionAvailable(FragmentUtil.getContext(SearchFragment.this));
     }
 
     static class ExternalQuery {
diff --git a/lifecycle/lifecycle-compiler/build.gradle b/lifecycle/lifecycle-compiler/build.gradle
index cde5b80..f64dfa1 100644
--- a/lifecycle/lifecycle-compiler/build.gradle
+++ b/lifecycle/lifecycle-compiler/build.gradle
@@ -25,13 +25,6 @@
     id("kotlin")
 }
 
-// Temporary hack to stop AS to adding two guavas into test's classpath
-configurations.all {
-    resolutionStrategy {
-        force GUAVA
-    }
-}
-
 dependencies {
     implementation(project(":lifecycle:lifecycle-common"))
     implementation(KOTLIN_STDLIB)
diff --git a/lifecycle/lifecycle-livedata-core-ktx-lint/build.gradle b/lifecycle/lifecycle-livedata-core-ktx-lint/build.gradle
index 0dc1113..193e1c7 100644
--- a/lifecycle/lifecycle-livedata-core-ktx-lint/build.gradle
+++ b/lifecycle/lifecycle-livedata-core-ktx-lint/build.gradle
@@ -26,15 +26,8 @@
 }
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly(LINT_API_LATEST)
-        compileOnly(LINT_CORE)
-    } else {
-        compileOnly(LINT_API_MIN)
-        compileOnly("com.android.tools.lint:lint:$lintMinVersion")
-    }
+    compileOnly(LINT_API_MIN)
+    compileOnly("com.android.tools.lint:lint:$lintMinVersion")
     compileOnly(KOTLIN_STDLIB)
 
     testImplementation(KOTLIN_STDLIB)
diff --git a/lifecycle/lifecycle-runtime-ktx-lint/build.gradle b/lifecycle/lifecycle-runtime-ktx-lint/build.gradle
index c7e05bd..6a17065 100644
--- a/lifecycle/lifecycle-runtime-ktx-lint/build.gradle
+++ b/lifecycle/lifecycle-runtime-ktx-lint/build.gradle
@@ -26,13 +26,7 @@
 }
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly(LINT_API_LATEST)
-    } else {
-        compileOnly(LINT_API_MIN)
-    }
+    compileOnly(LINT_API_MIN)
     compileOnly(KOTLIN_STDLIB)
 
     testImplementation(KOTLIN_STDLIB)
diff --git a/media2/media2-widget/src/main/res/values-eu/strings.xml b/media2/media2-widget/src/main/res/values-eu/strings.xml
index 4fde31a..5999909 100644
--- a/media2/media2-widget/src/main/res/values-eu/strings.xml
+++ b/media2/media2-widget/src/main/res/values-eu/strings.xml
@@ -20,7 +20,7 @@
     <string name="MediaControlView_subtitle_off_text" msgid="3464220590351304587">"Desaktibatuta"</string>
     <string name="MediaControlView_audio_track_text" msgid="3309135445007366582">"Audio-pista"</string>
     <string name="MediaControlView_audio_track_none_text" msgid="2659752099246305694">"Bat ere ez"</string>
-    <string name="MediaControlView_playback_speed_text" msgid="1481072528142380025">"Erreprodukzioaren abiadura"</string>
+    <string name="MediaControlView_playback_speed_text" msgid="1481072528142380025">"Erreprodukzio-abiadura"</string>
     <string name="MediaControlView_playback_speed_normal" msgid="2029510260288453183">"Normala"</string>
     <string name="MediaControlView_time_placeholder" msgid="6734584158942500617">"00:00:00"</string>
     <string name="MediaControlView_subtitle_track_number_text" msgid="2241078077382492349">"<xliff:g id="TRACK_NUMBER">%1$d</xliff:g>. pista"</string>
diff --git a/recyclerview/recyclerview-lint/build.gradle b/recyclerview/recyclerview-lint/build.gradle
index 3a3b3ff..e976ce8 100644
--- a/recyclerview/recyclerview-lint/build.gradle
+++ b/recyclerview/recyclerview-lint/build.gradle
@@ -25,13 +25,7 @@
 }
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly(LINT_API_LATEST)
-    } else {
-        compileOnly(LINT_API_MIN)
-    }
+    compileOnly(LINT_API_MIN)
     compileOnly(KOTLIN_STDLIB)
 
     testImplementation(KOTLIN_STDLIB)
diff --git a/resourceinspection/resourceinspection-annotation/api/restricted_current.txt b/resourceinspection/resourceinspection-annotation/api/restricted_current.txt
index 2962da1..5be0bd5 100644
--- a/resourceinspection/resourceinspection-annotation/api/restricted_current.txt
+++ b/resourceinspection/resourceinspection-annotation/api/restricted_current.txt
@@ -1,6 +1,9 @@
 // Signature format: 4.0
 package androidx.resourceinspection.annotation {
 
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE) public @interface AppCompatShadowedAttributes {
+  }
+
   @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface Attribute {
     method public abstract androidx.resourceinspection.annotation.Attribute.IntMap[] intMapping() default {};
     method public abstract String value();
diff --git a/resourceinspection/resourceinspection-annotation/src/main/java/androidx/resourceinspection/annotation/AppCompatShadowedAttributes.java b/resourceinspection/resourceinspection-annotation/src/main/java/androidx/resourceinspection/annotation/AppCompatShadowedAttributes.java
new file mode 100644
index 0000000..2ec1183
--- /dev/null
+++ b/resourceinspection/resourceinspection-annotation/src/main/java/androidx/resourceinspection/annotation/AppCompatShadowedAttributes.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.resourceinspection.annotation;
+
+import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import androidx.annotation.RestrictTo;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a view within AppCompat that shadows platform attributes.
+ * <p>
+ * Many AppCompat views shadow a platform attribute in order to provide backwards compatibility
+ * for older API levels. This means that a developer might set
+ * {@code androidx.appcompat:backgroundTint} instead of {@code android:backgroundTint} to get a
+ * background tint with support for API < 21. On more recent versions of the platform, this has
+ * the effect of storing the resolution stack in the {@code androidx.appcompat} namespace but
+ * reading the set value from the platform inspection companion in the {@code android} namespace,
+ * causing the resolution stack to get lost in the inspector.
+ * <p>
+ * Ordinarily, this behavior could be overridden by an {@link Attribute} annotation on the getter,
+ * but it is infeasible to override a platform getter that doesn't exist on older supported API
+ * levels. It results in worse performance at load time on those devices.
+ * <p>
+ * This annotation instructs the processor to include a list of shadowed attributes with
+ * API-level appropriate accessors in the view's inspection companion. It infers the attributes
+ * to include from the interfaces on the annotated view. For example, a view that implements
+ * {@link androidx.core.view.TintableBackgroundView} will report
+ * {@code androidx.appcompat:backgroundTint} directly from the platform
+ * {@link android.view.View.getBackgroundTintList()} getter. This approach allows views within
+ * AppCompat to mix shadowed attributes and regular attribute annotations on the same view
+ * without hand-written inspection companions.
+ * <p>
+ * @hide
+ */
+@Target(TYPE)
+@Retention(SOURCE)
+@RestrictTo(LIBRARY_GROUP_PREFIX)
+public @interface AppCompatShadowedAttributes {
+}
diff --git a/resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/InspectionCompanionGeneration.kt b/resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/InspectionCompanionGeneration.kt
index a013fb7..77b6d72 100644
--- a/resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/InspectionCompanionGeneration.kt
+++ b/resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/InspectionCompanionGeneration.kt
@@ -31,7 +31,7 @@
 
 /** Generates an inspection companion from a view using JavaPoet. */
 internal fun generateInspectionCompanion(
-    view: ViewIR,
+    view: View,
     generatedAnnotation: AnnotationSpec?
 ): JavaFile {
     val typeSpec = TypeSpec.classBuilder(
@@ -73,14 +73,14 @@
 
                 for (attribute in view.attributes) {
                     when (attribute.type) {
-                        AttributeTypeIR.INT_ENUM -> addStatement(
+                        AttributeType.INT_ENUM -> addStatement(
                             "\$N = propertyMapper.mapIntEnum(\$S, \$L, \$L)",
                             attributeIdNames[attribute],
                             attribute.name,
                             attribute.attrReference,
                             intEnumLambda(attribute)
                         )
-                        AttributeTypeIR.INT_FLAG -> addStatement(
+                        AttributeType.INT_FLAG -> addStatement(
                             "\$N = propertyMapper.mapIntFlag(\$S, \$L, \$L)",
                             attributeIdNames[attribute],
                             attribute.name,
@@ -117,11 +117,11 @@
 
                 for (attribute in view.attributes) {
                     addStatement(
-                        "propertyReader.read\$L(\$N, \$N.\$L())",
+                        "propertyReader.read\$L(\$N, \$N.\$L)",
                         attribute.type.apiSuffix,
                         attributeIdNames[attribute],
                         viewParameter,
-                        attribute.getter.simpleName
+                        attribute.invocation
                     )
                 }
             }.build()
@@ -134,7 +134,7 @@
 }
 
 /** The `(Int) -> String` lambda for int enums, as an anonymous class for Java 7 compatibility. */
-private fun intEnumLambda(attribute: AttributeIR): TypeSpec {
+private fun intEnumLambda(attribute: Attribute): TypeSpec {
     return TypeSpec.anonymousClassBuilder("").apply {
         addSuperinterface(INT_FUNCTION.parameterized(STRING))
 
@@ -159,7 +159,7 @@
 }
 
 /** The `(Int) -> Set<String>` lambda for int flags, as an anonymous class. */
-private fun intFlagLambda(attribute: AttributeIR): TypeSpec {
+private fun intFlagLambda(attribute: Attribute): TypeSpec {
     val stringSet = SET.parameterized(STRING)
     val stringHashSet = HASH_SET.parameterized(STRING)
 
@@ -192,7 +192,7 @@
 }
 
 /** A [CodeBlock] of the `$namespace.R.attr.$name` attribute ID reference. */
-private val AttributeIR.attrReference: CodeBlock
+private val Attribute.attrReference: CodeBlock
     get() = CodeBlock.of("\$T.attr.\$N", ClassName.get(namespace, "R"), name)
 
 /** Kotlin wrapper for [ClassName.get] to avoid platform types. */
diff --git a/resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/LayoutInspectionStep.kt b/resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/LayoutInspectionStep.kt
index 6038e6e..a9d59b3 100644
--- a/resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/LayoutInspectionStep.kt
+++ b/resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/LayoutInspectionStep.kt
@@ -67,8 +67,8 @@
         return emptySet()
     }
 
-    /** Parse the annotated getters of a view class into a [ViewIR]. */
-    private fun parseView(type: TypeElement, getters: Iterable<ExecutableElement>): ViewIR? {
+    /** Parse the annotated getters of a view class into a [View]. */
+    private fun parseView(type: TypeElement, getters: Iterable<ExecutableElement>): View? {
         if (!type.asType().isAssignableTo("android.view.View")) {
             getters.forEach { getter ->
                 printError(
@@ -93,13 +93,13 @@
                 duplicates.forEach { attribute ->
                     val qualifiedName = attribute.qualifiedName
                     val otherGetters = duplicates
-                        .filter { it.getter != attribute.getter }
-                        .joinToString { it.getter.toString() }
+                        .filter { it.invocation != attribute.invocation }
+                        .joinToString { it.invocation }
 
                     printError(
                         "Duplicate attribute $qualifiedName is also present on $otherGetters",
-                        attribute.getter,
-                        attribute.annotation
+                        (attribute as? GetterAttribute)?.getter,
+                        (attribute as? GetterAttribute)?.annotation
                     )
                 }
             }
@@ -110,11 +110,11 @@
             return null
         }
 
-        return ViewIR(type, attributes = attributes.filterNotNull().sortedBy { it.qualifiedName })
+        return View(type, attributes = attributes.filterNotNull().sortedBy { it.qualifiedName })
     }
 
-    /** Get an [AttributeIR] from a method known to have an `Attribute` annotation. */
-    private fun parseAttribute(getter: ExecutableElement): AttributeIR? {
+    /** Get an [Attribute] from a method known to have an `Attribute` annotation. */
+    private fun parseAttribute(getter: ExecutableElement): Attribute? {
         val annotation = getter.getAnnotationMirror(ATTRIBUTE)!!
         val annotationValue = getAnnotationValue(annotation, "value")
         val value = annotationValue.value as String
@@ -139,7 +139,7 @@
             // TODO(b/180041203): Verify attribute ID or at least existence of R files
             // TODO(b/180041633): Validate consistency of int mapping
 
-            AttributeIR(getter, annotation, namespace, name, type, intMapping)
+            GetterAttribute(getter, annotation, namespace, name, type, intMapping)
         } else if (!value.contains(':')) {
             printError("Attribute name must include namespace", getter, annotation, annotationValue)
             null
@@ -150,11 +150,11 @@
     }
 
     /** Parse `Attribute.intMapping`. */
-    private fun parseIntMapping(annotation: AnnotationMirror): List<IntMapIR> {
+    private fun parseIntMapping(annotation: AnnotationMirror): List<IntMap> {
         return (getAnnotationValue(annotation, "intMapping").value as List<*>).map { entry ->
             val intMapAnnotation = (entry as AnnotationValue).value as AnnotationMirror
 
-            IntMapIR(
+            IntMap(
                 name = getAnnotationValue(intMapAnnotation, "name").value as String,
                 value = getAnnotationValue(intMapAnnotation, "value").value as Int,
                 mask = getAnnotationValue(intMapAnnotation, "mask").value as Int,
@@ -165,35 +165,35 @@
     /** Map the getter's annotations and return type to the internal attribute type. */
     private fun inferAttributeType(
         getter: ExecutableElement,
-        intMapping: List<IntMapIR>
-    ): AttributeTypeIR {
+        intMapping: List<IntMap>
+    ): AttributeType {
         return when (getter.returnType.kind) {
-            TypeKind.BOOLEAN -> AttributeTypeIR.BOOLEAN
-            TypeKind.BYTE -> AttributeTypeIR.BYTE
-            TypeKind.CHAR -> AttributeTypeIR.CHAR
-            TypeKind.DOUBLE -> AttributeTypeIR.DOUBLE
-            TypeKind.FLOAT -> AttributeTypeIR.FLOAT
-            TypeKind.SHORT -> AttributeTypeIR.SHORT
+            TypeKind.BOOLEAN -> AttributeType.BOOLEAN
+            TypeKind.BYTE -> AttributeType.BYTE
+            TypeKind.CHAR -> AttributeType.CHAR
+            TypeKind.DOUBLE -> AttributeType.DOUBLE
+            TypeKind.FLOAT -> AttributeType.FLOAT
+            TypeKind.SHORT -> AttributeType.SHORT
             TypeKind.INT -> when {
-                getter.isAnnotationPresent(COLOR_INT) -> AttributeTypeIR.COLOR
-                getter.isAnnotationPresent(GRAVITY_INT) -> AttributeTypeIR.GRAVITY
-                getter.hasResourceIdAnnotation() -> AttributeTypeIR.RESOURCE_ID
-                intMapping.any { it.mask != 0 } -> AttributeTypeIR.INT_FLAG
-                intMapping.isNotEmpty() -> AttributeTypeIR.INT_ENUM
-                else -> AttributeTypeIR.INT
+                getter.isAnnotationPresent(COLOR_INT) -> AttributeType.COLOR
+                getter.isAnnotationPresent(GRAVITY_INT) -> AttributeType.GRAVITY
+                getter.hasResourceIdAnnotation() -> AttributeType.RESOURCE_ID
+                intMapping.any { it.mask != 0 } -> AttributeType.INT_FLAG
+                intMapping.isNotEmpty() -> AttributeType.INT_ENUM
+                else -> AttributeType.INT
             }
             TypeKind.LONG ->
                 if (getter.isAnnotationPresent(COLOR_LONG)) {
-                    AttributeTypeIR.COLOR
+                    AttributeType.COLOR
                 } else {
-                    AttributeTypeIR.LONG
+                    AttributeType.LONG
                 }
             TypeKind.DECLARED, TypeKind.ARRAY ->
                 if (getter.returnType.isAssignableTo("android.graphics.Color")) {
-                    AttributeTypeIR.COLOR
+                    AttributeType.COLOR
                 } else {
                     // TODO(b/180041034): Validate object types and unbox primitives
-                    AttributeTypeIR.OBJECT
+                    AttributeType.OBJECT
                 }
             else -> throw IllegalArgumentException("Unexpected attribute type")
         }
@@ -215,7 +215,7 @@
     /** Convenience wrapper for [javax.annotation.processing.Messager.printMessage]. */
     private fun printError(
         message: String,
-        element: Element,
+        element: Element?,
         annotation: AnnotationMirror? = null,
         value: AnnotationValue? = null
     ) {
diff --git a/resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/InternalRepresentations.kt b/resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/Models.kt
similarity index 69%
rename from resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/InternalRepresentations.kt
rename to resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/Models.kt
index 8254250..ad46352 100644
--- a/resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/InternalRepresentations.kt
+++ b/resourceinspection/resourceinspection-processor/src/main/kotlin/androidx/resourceinspection/processor/Models.kt
@@ -22,34 +22,46 @@
 import javax.lang.model.element.TypeElement
 
 /** Represents a view with annotated attributes, mostly a convenience class. */
-internal data class ViewIR(
+internal data class View(
     val type: TypeElement,
-    val attributes: List<AttributeIR>
+    val attributes: List<Attribute>
 ) {
     val className: ClassName = ClassName.get(type)
 }
 
+internal interface Attribute {
+    val name: String
+    val namespace: String
+    val type: AttributeType
+    val intMapping: List<IntMap>
+    val invocation: String
+
+    val qualifiedName: String
+        get() = "$namespace:$name"
+}
+
 /** Represents an `Attribute` with its getter. */
-internal data class AttributeIR(
+internal data class GetterAttribute(
     val getter: ExecutableElement,
     val annotation: AnnotationMirror,
-    val namespace: String,
-    val name: String,
-    val type: AttributeTypeIR,
-    val intMapping: List<IntMapIR>
-) {
-    val qualifiedName: String = "$namespace:$name"
+    override val namespace: String,
+    override val name: String,
+    override val type: AttributeType,
+    override val intMapping: List<IntMap> = emptyList()
+) : Attribute {
+    override val invocation: String
+        get() = "${getter.simpleName}()"
 }
 
 /** Represents an `Attribute.IntMap` entry. */
-internal data class IntMapIR(
+internal data class IntMap(
     val name: String,
     val value: Int,
-    val mask: Int
+    val mask: Int = 0
 )
 
 /** Represents the type of the attribute, determined from context and the annotation itself. */
-internal enum class AttributeTypeIR(val apiSuffix: String) {
+internal enum class AttributeType(val apiSuffix: String) {
     BOOLEAN("Boolean"),
     BYTE("Byte"),
     CHAR("Char"),
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XElement.kt
index b06d8c9..497b194 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XElement.kt
@@ -40,6 +40,11 @@
      * message. Without this information, developer gets no clue on where the error is.
      */
     val fallbackLocationText: String
+
+    /**
+     * The documentation comment of the element, or null if there is none.
+     */
+    val docComment: String?
 }
 
 /**
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMessager.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMessager.kt
index 16f1bba..65561ab 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMessager.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XMessager.kt
@@ -37,7 +37,11 @@
         onPrintMessage(kind, msg, element)
     }
 
-    abstract fun onPrintMessage(kind: Diagnostic.Kind, msg: String, element: XElement? = null)
+    protected abstract fun onPrintMessage(
+        kind: Diagnostic.Kind,
+        msg: String,
+        element: XElement? = null
+    )
 
     fun addMessageWatcher(watcher: XMessager) {
         watchers.add(watcher)
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XTypeElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XTypeElement.kt
index 5109aff..aa692e1 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XTypeElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/XTypeElement.kt
@@ -65,11 +65,49 @@
     fun isInterface(): Boolean
 
     /**
-     * Returns `true` if this [XTypeElement] is declared as a Kotlin `object`
+     * Returns `true` if this [XTypeElement] represents a Kotlin functional interface,
+     * i.e. marked with the keyword `fun`
+     */
+    fun isFunctionalInterface(): Boolean
+
+    /**
+     * Returns `true` if this [XTypeElement] represents an ordinary class. ie not an enum, object,
+     * annotation, interface, or other type of specialty class.
+     */
+    fun isClass(): Boolean
+
+    /**
+     * Returns `true` if this [XTypeElement] represents a Kotlin data class
+     */
+    fun isDataClass(): Boolean
+
+    /**
+     * Returns `true` if this [XTypeElement] represents a Kotlin value class
+     */
+    fun isValueClass(): Boolean
+
+    /**
+     * Returns `true` if this [XTypeElement] represents a class with the Kotlin `expect` keyword
+     */
+    fun isExpect(): Boolean
+
+    /**
+     * Returns `true` if this [XTypeElement] represents a Kotlin annotation class or a Java
+     * annotation type.
+     */
+    fun isAnnotationClass(): Boolean
+
+    /**
+     * Returns `true` if this [XTypeElement] is a non-companion `object` in Kotlin
      */
     fun isKotlinObject(): Boolean
 
     /**
+     * Returns `true` if this [XTypeElement] is declared as a Kotlin `companion object`
+     */
+    fun isCompanionObject(): Boolean
+
+    /**
      * All fields, including private supers.
      * Room only ever reads fields this way.
      */
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacElement.kt
index 47eb36b..497a809 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacElement.kt
@@ -86,4 +86,8 @@
             MoreElements.getPackage(it.annotationType.asElement()).toString() == pkg
         }
     }
+
+    override val docComment: String? by lazy {
+        env.elementUtils.getDocComment(element)
+    }
 }
\ No newline at end of file
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacTypeElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacTypeElement.kt
index acaffb7..1266ef0 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacTypeElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacTypeElement.kt
@@ -21,7 +21,6 @@
 import androidx.room.compiler.processing.XHasModifiers
 import androidx.room.compiler.processing.XMethodElement
 import androidx.room.compiler.processing.XTypeElement
-import androidx.room.compiler.processing.javac.JavacTypeElement.JavacEnumTypeElement
 import androidx.room.compiler.processing.javac.kotlin.KotlinMetadataElement
 import com.google.auto.common.MoreElements
 import com.google.auto.common.MoreTypes
@@ -58,8 +57,6 @@
         element.enclosingType(env)
     }
 
-    override fun isInterface() = element.kind == ElementKind.INTERFACE
-
     private val _allFieldsIncludingPrivateSupers by lazy {
         element.getAllFieldsIncludingPrivateSupers(
             env.elementUtils
@@ -77,6 +74,24 @@
     }
 
     override fun isKotlinObject() = kotlinMetadata?.isObject() == true
+    override fun isCompanionObject() = kotlinMetadata?.isCompanionObject() == true
+    override fun isDataClass() = kotlinMetadata?.isDataClass() == true
+    override fun isValueClass() = kotlinMetadata?.isValueClass() == true
+    override fun isFunctionalInterface() = kotlinMetadata?.isFunctionalInterface() == true
+    override fun isExpect() = kotlinMetadata?.isExpect() == true
+
+    override fun isAnnotationClass(): Boolean {
+        return kotlinMetadata?.isAnnotationClass()
+            ?: (element.kind == ElementKind.ANNOTATION_TYPE)
+    }
+
+    override fun isClass(): Boolean {
+        return kotlinMetadata?.isClass() ?: (element.kind == ElementKind.CLASS)
+    }
+
+    override fun isInterface(): Boolean {
+        return kotlinMetadata?.isInterface() ?: (element.kind == ElementKind.INTERFACE)
+    }
 
     override fun findPrimaryConstructor(): JavacConstructorElement? {
         val primarySignature = kotlinMetadata?.findPrimaryConstructorSignature() ?: return null
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
index 2ae8d57..2b3fc32 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
@@ -39,6 +39,7 @@
 internal interface KmExecutable {
     val parameters: List<KmValueParameter>
 }
+
 /**
  * Represents the kotlin metadata of a function
  */
@@ -68,6 +69,7 @@
 ) {
     val typeParameters
         get() = type.typeArguments
+
     fun isNullable() = Flag.Type.IS_NULLABLE(type.flags)
 }
 
@@ -188,25 +190,42 @@
     }
 }
 
-internal fun KotlinClassMetadata.Class.isObject(): Boolean = ObjectReader().let {
-    this@isObject.accept(it)
-    it.isObject
+internal class KotlinMetadataClassFlags(val classMetadata: KotlinClassMetadata.Class) {
+
+    private val flags: Flags by lazy {
+        var theFlags: Flags = 0
+        classMetadata.accept(object : KmClassVisitor() {
+            override fun visit(flags: Flags, name: ClassName) {
+                theFlags = flags
+                super.visit(flags, name)
+            }
+        })
+        return@lazy theFlags
+    }
+
+    fun isObject(): Boolean = Flag.Class.IS_OBJECT(flags)
+
+    fun isCompanionObject(): Boolean = Flag.Class.IS_COMPANION_OBJECT(flags)
+
+    fun isAnnotationClass(): Boolean = Flag.Class.IS_ANNOTATION_CLASS(flags)
+
+    fun isInterface(): Boolean = Flag.Class.IS_INTERFACE(flags)
+
+    fun isClass(): Boolean = Flag.Class.IS_CLASS(flags)
+
+    fun isDataClass(): Boolean = Flag.Class.IS_DATA(flags)
+
+    fun isValueClass(): Boolean = Flag.Class.IS_INLINE(flags)
+
+    fun isFunctionalInterface(): Boolean = Flag.Class.IS_FUN(flags)
+
+    fun isExpect(): Boolean = Flag.Class.IS_EXPECT(flags)
 }
 
 internal fun KotlinClassMetadata.Class.readProperties(): List<KmProperty> =
     mutableListOf<KmProperty>().apply { accept(PropertyReader(this)) }
 
 /**
- * Reads whether the given class is a kotlin object
- */
-private class ObjectReader : KmClassVisitor() {
-    var isObject: Boolean = false
-    override fun visit(flags: Flags, name: ClassName) {
-        isObject = Flag.Class.IS_OBJECT(flags)
-    }
-}
-
-/**
  * Reads the properties of a class declaration
  */
 private class PropertyReader(
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElement.kt
index 963c20a..cf281c4 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElement.kt
@@ -45,6 +45,9 @@
     private val functionList: List<KmFunction> by lazy { classMetadata.readFunctions() }
     private val constructorList: List<KmConstructor> by lazy { classMetadata.readConstructors() }
     private val propertyList: List<KmProperty> by lazy { classMetadata.readProperties() }
+    private val classFlags: KotlinMetadataClassFlags by lazy {
+        KotlinMetadataClassFlags(classMetadata)
+    }
 
     private val ExecutableElement.descriptor: String
         get() = descriptor()
@@ -53,7 +56,15 @@
         it.isPrimary()
     }?.descriptor
 
-    fun isObject(): Boolean = classMetadata.isObject()
+    fun isObject(): Boolean = classFlags.isObject()
+    fun isCompanionObject(): Boolean = classFlags.isCompanionObject()
+    fun isAnnotationClass(): Boolean = classFlags.isAnnotationClass()
+    fun isClass(): Boolean = classFlags.isClass()
+    fun isInterface(): Boolean = classFlags.isInterface()
+    fun isDataClass(): Boolean = classFlags.isDataClass()
+    fun isValueClass(): Boolean = classFlags.isValueClass()
+    fun isFunctionalInterface(): Boolean = classFlags.isFunctionalInterface()
+    fun isExpect(): Boolean = classFlags.isExpect()
 
     fun getFunctionMetadata(method: ExecutableElement): KmFunction? {
         check(method.kind == ElementKind.METHOD) {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspElement.kt
index 22fa748..37ef859 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspElement.kt
@@ -61,4 +61,10 @@
             KSFileAsOriginatingElement(it)
         }
     }
+
+    override val docComment: String? by lazy {
+        // TODO: Not yet implemented in KSP.
+        // https://github.com/google/ksp/issues/392
+        null
+    }
 }
\ No newline at end of file
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFileMemberContainer.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFileMemberContainer.kt
index 9d91bb4..60df4da 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFileMemberContainer.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFileMemberContainer.kt
@@ -58,6 +58,12 @@
 
     override val fallbackLocationText: String = ksFile.filePath
 
+    override val docComment: String? by lazy {
+        // TODO: Not yet implemented in KSP.
+        // https://github.com/google/ksp/issues/392
+        null
+    }
+
     companion object {
         private fun KSFile.findClassName(): String {
             return annotations.firstOrNull {
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
index c7f17c6..404c5f5 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspTypeElement.kt
@@ -40,6 +40,7 @@
 import com.google.devtools.ksp.symbol.Modifier
 import com.google.devtools.ksp.symbol.Origin
 import com.squareup.javapoet.ClassName
+import javax.tools.Diagnostic
 
 internal sealed class KspTypeElement(
     env: KspProcessingEnv,
@@ -253,6 +254,40 @@
         return declaration.classKind == ClassKind.OBJECT
     }
 
+    override fun isCompanionObject(): Boolean {
+        return declaration.isCompanionObject
+    }
+
+    override fun isAnnotationClass(): Boolean {
+        return declaration.classKind == ClassKind.ANNOTATION_CLASS
+    }
+
+    override fun isClass(): Boolean {
+        return declaration.classKind == ClassKind.CLASS
+    }
+
+    override fun isDataClass(): Boolean {
+        return Modifier.DATA in declaration.modifiers
+    }
+
+    override fun isValueClass(): Boolean {
+        return Modifier.INLINE in declaration.modifiers
+    }
+
+    override fun isFunctionalInterface(): Boolean {
+        // TODO: Update this once KSP supports it
+        // https://github.com/google/ksp/issues/393
+        env.messager.printMessage(
+            Diagnostic.Kind.WARNING,
+            "XProcessing does not yet support checking for functional interfaces in KSP."
+        )
+        return false
+    }
+
+    override fun isExpect(): Boolean {
+        return Modifier.EXPECT in declaration.modifiers
+    }
+
     override fun isFinal(): Boolean {
         // workaround for https://github.com/android/kotlin/issues/128
         return !isInterface() && !declaration.isOpen()
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
index aad60a8..cab0ab2 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticContinuationParameterElement.kt
@@ -82,6 +82,9 @@
     override val fallbackLocationText: String
         get() = "return type of ${containing.fallbackLocationText}"
 
+    // Not applicable
+    override val docComment: String? get() = null
+
     override fun asMemberOf(other: XType): XType {
         check(other is KspType)
         val continuation = env.resolver.requireContinuationClass()
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
index 7ad376f..3c35af4 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
@@ -80,6 +80,12 @@
         )
     }
 
+    override val docComment: String? by lazy {
+        // Not yet implemented in KSP.
+        // https://github.com/google/ksp/issues/392
+        null
+    }
+
     final override fun asMemberOf(other: XType): XMethodType {
         return KspSyntheticPropertyMethodType.create(
             element = this,
@@ -226,6 +232,12 @@
                 return origin.field.asMemberOf(other)
             }
 
+            override val docComment: String? by lazy {
+                // Not yet implemented in KSP.
+                // https://github.com/google/ksp/issues/392
+                null
+            }
+
             override fun kindName(): String {
                 return "method parameter"
             }
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
index faded70..b8727eb 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
@@ -202,6 +202,12 @@
                 inner class InnerKotlinClass
                 class NestedKotlinClass
             }
+            annotation class KotlinAnnotation
+            data class DataClass(val foo: Int)
+            inline class InlineClass(val foo: Int)
+            fun interface FunInterface {
+               fun foo()
+            }
             """.trimIndent()
         )
         val javaSrc = Source.java(
@@ -213,8 +219,15 @@
             }
             """.trimIndent()
         )
+        val javaAnnotationSrc = Source.java(
+            "JavaAnnotation",
+            """
+            public @interface JavaAnnotation {
+            }
+            """.trimIndent()
+        )
         runProcessorTest(
-            sources = listOf(kotlinSrc, javaSrc)
+            sources = listOf(kotlinSrc, javaSrc, javaAnnotationSrc)
         ) { invocation ->
             fun getModifiers(element: XTypeElement): Set<String> {
                 val result = mutableSetOf<String>()
@@ -224,8 +237,15 @@
                 if (element.isProtected()) result.add("protected")
                 if (element.isPublic()) result.add("public")
                 if (element.isKotlinObject()) result.add("object")
+                if (element.isCompanionObject()) result.add("companion")
+                if (element.isFunctionalInterface()) result.add("fun")
+                if (element.isClass()) result.add("class")
+                if (element.isDataClass()) result.add("data")
+                if (element.isValueClass()) result.add("value")
+                if (element.isExpect()) result.add("expect")
                 if (element.isInterface()) result.add("interface")
                 if (element.isStatic()) result.add("static")
+                if (element.isAnnotationClass()) result.add("annotation")
                 return result
             }
 
@@ -235,32 +255,54 @@
             )
 
             assertThat(getModifiers("OpenClass"))
-                .containsExactly("public")
+                .containsExactly("public", "class")
             assertThat(getModifiers("AbstractClass"))
-                .containsExactly("abstract", "public")
+                .containsExactly("abstract", "public", "class")
             assertThat(getModifiers("MyObject"))
                 .containsExactly("final", "public", "object")
             assertThat(getModifiers("MyInterface"))
                 .containsExactly("abstract", "interface", "public")
             assertThat(getModifiers("Final"))
-                .containsExactly("final", "public")
+                .containsExactly("final", "public", "class")
             assertThat(getModifiers("PrivateClass"))
                 .containsExactlyElementsIn(
                     if (invocation.isKsp) {
-                        listOf("private", "final")
+                        listOf("private", "final", "class")
                     } else {
                         // java does not support top level private classes.
-                        listOf("final")
+                        listOf("final", "class")
                     }
                 )
             assertThat(getModifiers("OuterKotlinClass.InnerKotlinClass"))
-                .containsExactly("final", "public")
+                .containsExactly("final", "public", "class")
             assertThat(getModifiers("OuterKotlinClass.NestedKotlinClass"))
-                .containsExactly("final", "public", "static")
+                .containsExactly("final", "public", "static", "class")
             assertThat(getModifiers("OuterJavaClass.InnerJavaClass"))
-                .containsExactly("public")
+                .containsExactly("public", "class")
             assertThat(getModifiers("OuterJavaClass.NestedJavaClass"))
-                .containsExactly("public", "static")
+                .containsExactly("public", "static", "class")
+            assertThat(getModifiers("JavaAnnotation"))
+                .containsExactly("abstract", "public", "annotation")
+            assertThat(getModifiers("KotlinAnnotation")).apply {
+                // KSP vs KAPT metadata have a difference in final vs abstract modifiers
+                // for annotation types.
+                if (invocation.isKsp) {
+                    containsExactly("final", "public", "annotation")
+                } else {
+                    containsExactly("abstract", "public", "annotation")
+                }
+            }
+            assertThat(getModifiers("DataClass"))
+                .containsExactly("public", "final", "class", "data")
+            assertThat(getModifiers("InlineClass"))
+                .containsExactly("public", "final", "class", "value")
+
+            if (!invocation.isKsp) {
+                // TODO: Enable for ksp too once it supports fun interfaces
+                //  https://github.com/google/ksp/issues/393
+                assertThat(getModifiers("FunInterface"))
+                    .containsExactly("public", "abstract", "interface", "fun")
+            }
         }
     }
 
diff --git a/room/compiler/build.gradle b/room/compiler/build.gradle
index 26115ea..7e73bf4b 100644
--- a/room/compiler/build.gradle
+++ b/room/compiler/build.gradle
@@ -36,13 +36,6 @@
     main.java.srcDirs += antlrOut
 }
 
-// Temporary hack to stop AS to adding two guavas into test's classpath
-configurations.all {
-    resolutionStrategy {
-        force GUAVA
-    }
-}
-
 configurations {
     /**
      * shadowed is used for dependencies which we jarjar into the library jar instead of adding it
diff --git a/security/crypto/build.gradle b/security/crypto/build.gradle
index 3fa3338..665ee42 100644
--- a/security/crypto/build.gradle
+++ b/security/crypto/build.gradle
@@ -31,11 +31,11 @@
     implementation("com.google.crypto.tink:tink-android:1.5.0")
     implementation("androidx.collection:collection:1.1.0")
 
-    androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
-    androidTestImplementation(ANDROIDX_TEST_CORE)
-    androidTestImplementation(ANDROIDX_TEST_RUNNER)
-    androidTestImplementation(ANDROIDX_TEST_RULES)
-    androidTestImplementation(MOCKITO_CORE)
+    androidTestImplementation(libs.testExtJunit)
+    androidTestImplementation(libs.testCore)
+    androidTestImplementation(libs.testRunner)
+    androidTestImplementation(libs.testRules)
+    androidTestImplementation(libs.mockitoCore)
 
 }
 
diff --git a/security/security-crypto-ktx/build.gradle b/security/security-crypto-ktx/build.gradle
index 12aaa02..f977990 100644
--- a/security/security-crypto-ktx/build.gradle
+++ b/security/security-crypto-ktx/build.gradle
@@ -28,13 +28,13 @@
 dependencies {
     api("androidx.security:security-crypto:1.1.0-alpha03")
 
-    api(KOTLIN_STDLIB)
-    androidTestImplementation(JUNIT)
-    androidTestImplementation(TRUTH)
-    androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
-    androidTestImplementation(ANDROIDX_TEST_CORE)
-    androidTestImplementation(ANDROIDX_TEST_RUNNER)
-    androidTestImplementation(ANDROIDX_TEST_RULES)
+    api(libs.kotlinStdlib)
+    androidTestImplementation(libs.junit)
+    androidTestImplementation(libs.truth)
+    androidTestImplementation(libs.testExtJunit)
+    androidTestImplementation(libs.testCore)
+    androidTestImplementation(libs.testRunner)
+    androidTestImplementation(libs.testRules)
 }
 
 android {
diff --git a/slices/core/src/main/res/values-af/strings.xml b/slices/core/src/main/res/values-af/strings.xml
index c6a4763..cea048b 100644
--- a/slices/core/src/main/res/values-af/strings.xml
+++ b/slices/core/src/main/res/values-af/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Laat <xliff:g id="APP_0">%1$s</xliff:g> toe om <xliff:g id="APP_2">%2$s</xliff:g>-skyfies te wys?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Dit kan inligting in <xliff:g id="APP">%1$s</xliff:g> lees"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Dit kan handelinge binne <xliff:g id="APP">%1$s</xliff:g> uitvoer"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Laat toe"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Weier"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-am/strings.xml b/slices/core/src/main/res/values-am/strings.xml
index 3fc492a..96be387 100644
--- a/slices/core/src/main/res/values-am/strings.xml
+++ b/slices/core/src/main/res/values-am/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> የ<xliff:g id="APP_2">%2$s</xliff:g> ቁራጮችን እንዲያሳይ ይፈቀድለት?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- ከ<xliff:g id="APP">%1$s</xliff:g> የመጣ መረጃን ማንበብ ይችላል"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- በ<xliff:g id="APP">%1$s</xliff:g> ውስጥ እርምጃዎችን መውሰድ ይችላል"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"ፍቀድ"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"ከልክል"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ar/strings.xml b/slices/core/src/main/res/values-ar/strings.xml
index 2d76a8d..c195f16 100644
--- a/slices/core/src/main/res/values-ar/strings.xml
+++ b/slices/core/src/main/res/values-ar/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"هل تريد السماح لتطبيق <xliff:g id="APP_0">%1$s</xliff:g> بعرض شرائح <xliff:g id="APP_2">%2$s</xliff:g>؟"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- إمكانية قراءة المعلومات من <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- إمكانية اتخاذ إجراءات داخل <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"سماح"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"رفض"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-as/strings.xml b/slices/core/src/main/res/values-as/strings.xml
index ea2a877..e8c88e0 100644
--- a/slices/core/src/main/res/values-as/strings.xml
+++ b/slices/core/src/main/res/values-as/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g>ক <xliff:g id="APP_2">%2$s</xliff:g>ৰ অংশ দেখুওৱাবলৈ অনুমতি দিবনে?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- ই <xliff:g id="APP">%1$s</xliff:g>ৰ তথ্য পঢ়িব পাৰে"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- ই <xliff:g id="APP">%1$s</xliff:g>ৰ ভিতৰত কাৰ্য কৰিব পাৰে"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"অনুমতি দিয়ক"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"অস্বীকাৰ কৰক"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-az/strings.xml b/slices/core/src/main/res/values-az/strings.xml
index 2f1bce4..bd71cb1 100644
--- a/slices/core/src/main/res/values-az/strings.xml
+++ b/slices/core/src/main/res/values-az/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> tətbiqinə <xliff:g id="APP_2">%2$s</xliff:g> hissələrini göstərmək üçün icazə verilsin?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- <xliff:g id="APP">%1$s</xliff:g> tətbiqindən məlumat oxuya bilər"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- <xliff:g id="APP">%1$s</xliff:g> daxilində əməliyyatlar edə bilər"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"İcazə verin"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Rədd edin"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-b+sr+Latn/strings.xml b/slices/core/src/main/res/values-b+sr+Latn/strings.xml
index 3e20b9e..476441d 100644
--- a/slices/core/src/main/res/values-b+sr+Latn/strings.xml
+++ b/slices/core/src/main/res/values-b+sr+Latn/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Želite li da dozvolite aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> da prikazuje isečke iz aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Može da čita podatke iz aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Može da obavlja radnje u aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Dozvoli"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Odbij"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-be/strings.xml b/slices/core/src/main/res/values-be/strings.xml
index 84cd4a22..85988a8 100644
--- a/slices/core/src/main/res/values-be/strings.xml
+++ b/slices/core/src/main/res/values-be/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Дазволіць праграме <xliff:g id="APP_0">%1$s</xliff:g> паказваць фрагменты праграмы <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Можа счытваць інфармацыю з праграмы <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Можа выконваць дзеянні ў праграме <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Дазволіць"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Адмовіць"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-bg/strings.xml b/slices/core/src/main/res/values-bg/strings.xml
index dcd2606..1ff6667 100644
--- a/slices/core/src/main/res/values-bg/strings.xml
+++ b/slices/core/src/main/res/values-bg/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Ще разрешите ли на <xliff:g id="APP_0">%1$s</xliff:g> да показва части от <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Може да чете информация от <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Може да предприема действия в/ъв <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Разрешаване"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Отказ"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-bn/strings.xml b/slices/core/src/main/res/values-bn/strings.xml
index 4b46f9b..c9556dd 100644
--- a/slices/core/src/main/res/values-bn/strings.xml
+++ b/slices/core/src/main/res/values-bn/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> অ্যাপটিকে <xliff:g id="APP_2">%2$s</xliff:g> এর অংশ দেখানোর অনুমতি দেবেন?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- এটি <xliff:g id="APP">%1$s</xliff:g> এর তথ্য অ্যাক্সেস করতে পারবে"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- এটি <xliff:g id="APP">%1$s</xliff:g> এর মধ্যে কাজ করতে পারবে"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"অনুমতি দিন"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"খারিজ করুন"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-bs/strings.xml b/slices/core/src/main/res/values-bs/strings.xml
index b203a79..ed3104d5 100644
--- a/slices/core/src/main/res/values-bs/strings.xml
+++ b/slices/core/src/main/res/values-bs/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Dozvoliti aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> prikazivanje isječaka aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Može čitati informacije iz aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Može poduzeti radnje u aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Dozvoli"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Odbij"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ca/strings.xml b/slices/core/src/main/res/values-ca/strings.xml
index ac93488..5bff344 100644
--- a/slices/core/src/main/res/values-ca/strings.xml
+++ b/slices/core/src/main/res/values-ca/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Vols permetre que <xliff:g id="APP_0">%1$s</xliff:g> mostri porcions de l\'aplicació <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Pot llegir informació de l\'aplicació <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Pot dur a terme accions dins de l\'aplicació <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Permet"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Denega"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-cs/strings.xml b/slices/core/src/main/res/values-cs/strings.xml
index da1053b..432ed94 100644
--- a/slices/core/src/main/res/values-cs/strings.xml
+++ b/slices/core/src/main/res/values-cs/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Povolit aplikaci <xliff:g id="APP_0">%1$s</xliff:g> zobrazovat ukázky z aplikace <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Může číst informace z aplikace <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Může provádět akce v aplikaci <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Povolit"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Zamítnout"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-da/strings.xml b/slices/core/src/main/res/values-da/strings.xml
index 67a7ed0..eb148eb 100644
--- a/slices/core/src/main/res/values-da/strings.xml
+++ b/slices/core/src/main/res/values-da/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Vil du give <xliff:g id="APP_0">%1$s</xliff:g> tilladelse til at vise eksempler fra <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Den kan læse oplysninger fra <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Den kan foretage handlinger i <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Tillad"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Afvis"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-de/strings.xml b/slices/core/src/main/res/values-de/strings.xml
index 419fa20..b14bdb3 100644
--- a/slices/core/src/main/res/values-de/strings.xml
+++ b/slices/core/src/main/res/values-de/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> erlauben, Teile von <xliff:g id="APP_2">%2$s</xliff:g> anzuzeigen?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Darf Informationen aus <xliff:g id="APP">%1$s</xliff:g> lesen"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Darf Aktionen in <xliff:g id="APP">%1$s</xliff:g> ausführen"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Zulassen"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Ablehnen"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-el/strings.xml b/slices/core/src/main/res/values-el/strings.xml
index 898d2ea..8ae97bf 100644
--- a/slices/core/src/main/res/values-el/strings.xml
+++ b/slices/core/src/main/res/values-el/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Να επιτρέπεται στην εφαρμογή <xliff:g id="APP_0">%1$s</xliff:g> να εμφανίζει τμήματα της εφαρμογής <xliff:g id="APP_2">%2$s</xliff:g>;"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Μπορεί να διαβάζει πληροφορίες από την εφαρμογή <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Μπορεί να εκτελεί ενέργειες εντός της εφαρμογής <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Να επιτρέπεται"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Να μην επιτρέπεται"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-en-rAU/strings.xml b/slices/core/src/main/res/values-en-rAU/strings.xml
index b4c1f11..753ea3e 100644
--- a/slices/core/src/main/res/values-en-rAU/strings.xml
+++ b/slices/core/src/main/res/values-en-rAU/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– It can take actions inside <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Allow"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Deny"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-en-rCA/strings.xml b/slices/core/src/main/res/values-en-rCA/strings.xml
index b4c1f11..753ea3e 100644
--- a/slices/core/src/main/res/values-en-rCA/strings.xml
+++ b/slices/core/src/main/res/values-en-rCA/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– It can take actions inside <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Allow"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Deny"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-en-rGB/strings.xml b/slices/core/src/main/res/values-en-rGB/strings.xml
index b4c1f11..753ea3e 100644
--- a/slices/core/src/main/res/values-en-rGB/strings.xml
+++ b/slices/core/src/main/res/values-en-rGB/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– It can take actions inside <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Allow"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Deny"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-en-rIN/strings.xml b/slices/core/src/main/res/values-en-rIN/strings.xml
index b4c1f11..753ea3e 100644
--- a/slices/core/src/main/res/values-en-rIN/strings.xml
+++ b/slices/core/src/main/res/values-en-rIN/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Allow <xliff:g id="APP_0">%1$s</xliff:g> to show <xliff:g id="APP_2">%2$s</xliff:g> slices?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– It can read information from <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– It can take actions inside <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Allow"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Deny"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-en-rXC/strings.xml b/slices/core/src/main/res/values-en-rXC/strings.xml
index efb1d5f..22c86bc 100644
--- a/slices/core/src/main/res/values-en-rXC/strings.xml
+++ b/slices/core/src/main/res/values-en-rXC/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‏‎‏‎‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎Allow ‎‏‎‎‏‏‎<xliff:g id="APP_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to show ‎‏‎‎‏‏‎<xliff:g id="APP_2">%2$s</xliff:g>‎‏‎‎‏‏‏‎ slices?‎‏‎‎‏‎"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‏‏‎- It can read information from ‎‏‎‎‏‏‎<xliff:g id="APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‎‏‏‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‎- It can take actions inside ‎‏‎‎‏‏‎<xliff:g id="APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‎‎Allow‎‏‎‎‏‎"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‎‏‎‎‎‎‎‎‏‏‎‎‏‎Deny‎‏‎‎‏‎"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-es-rUS/strings.xml b/slices/core/src/main/res/values-es-rUS/strings.xml
index 31746f0..d004921 100644
--- a/slices/core/src/main/res/values-es-rUS/strings.xml
+++ b/slices/core/src/main/res/values-es-rUS/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"¿Permitir que <xliff:g id="APP_0">%1$s</xliff:g> muestre fragmentos de <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Puede leer información de <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Puede realizar acciones en <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Permitir"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Rechazar"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-es/strings.xml b/slices/core/src/main/res/values-es/strings.xml
index 3a65289..cdd8514 100644
--- a/slices/core/src/main/res/values-es/strings.xml
+++ b/slices/core/src/main/res/values-es/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"¿Permitir que <xliff:g id="APP_0">%1$s</xliff:g> muestre fragmentos de <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Puede leer información de <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Puede realizar acciones en <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Permitir"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Denegar"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-et/strings.xml b/slices/core/src/main/res/values-et/strings.xml
index 5462dd7..7d92095 100644
--- a/slices/core/src/main/res/values-et/strings.xml
+++ b/slices/core/src/main/res/values-et/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Kas lubada rakendusel <xliff:g id="APP_0">%1$s</xliff:g> näidata rakenduse <xliff:g id="APP_2">%2$s</xliff:g> lõike?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- See saab lugeda teavet rakendusest <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- See saab rakenduses <xliff:g id="APP">%1$s</xliff:g> toiminguid teha"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Lubamine"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Keelamine"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-eu/strings.xml b/slices/core/src/main/res/values-eu/strings.xml
index 8776fec..bea035d 100644
--- a/slices/core/src/main/res/values-eu/strings.xml
+++ b/slices/core/src/main/res/values-eu/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_2">%2$s</xliff:g> aplikazioaren zatiak erakusteko baimena eman nahi diozu <xliff:g id="APP_0">%1$s</xliff:g> aplikazioari?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- <xliff:g id="APP">%1$s</xliff:g> aplikazioaren informazioa irakur dezake."</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- <xliff:g id="APP">%1$s</xliff:g> aplikazioan ekintzak gauza ditzake."</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Baimendu"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Ukatu"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-fa/strings.xml b/slices/core/src/main/res/values-fa/strings.xml
index d5e0416..2abd384 100644
--- a/slices/core/src/main/res/values-fa/strings.xml
+++ b/slices/core/src/main/res/values-fa/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"به <xliff:g id="APP_0">%1$s</xliff:g> اجازه داده شود تکه‌های <xliff:g id="APP_2">%2$s</xliff:g> را نشان دهد؟"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- می‌تواند اطلاعات <xliff:g id="APP">%1$s</xliff:g> را بخواند"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- می‌تواند در <xliff:g id="APP">%1$s</xliff:g> اقدام انجام دهد"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"مجاز بودن"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"مجاز نبودن"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-fi/strings.xml b/slices/core/src/main/res/values-fi/strings.xml
index d682f1a..b826e98 100644
--- a/slices/core/src/main/res/values-fi/strings.xml
+++ b/slices/core/src/main/res/values-fi/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Saako <xliff:g id="APP_0">%1$s</xliff:g> näyttää osia sovelluksesta <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Se voi lukea tietoja sovelluksesta <xliff:g id="APP">%1$s</xliff:g>."</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Se voi suorittaa toimintoja sovelluksessa <xliff:g id="APP">%1$s</xliff:g>."</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Salli"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Estä"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-fr-rCA/strings.xml b/slices/core/src/main/res/values-fr-rCA/strings.xml
index a0e55d3..a5d3fd0 100644
--- a/slices/core/src/main/res/values-fr-rCA/strings.xml
+++ b/slices/core/src/main/res/values-fr-rCA/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Autoriser <xliff:g id="APP_0">%1$s</xliff:g> à afficher <xliff:g id="APP_2">%2$s</xliff:g> tranches?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Il peut lire de l\'information de <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Il peut effectuer des actions dans <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Autoriser"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Refuser"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-fr/strings.xml b/slices/core/src/main/res/values-fr/strings.xml
index 65f06bc..724da28 100644
--- a/slices/core/src/main/res/values-fr/strings.xml
+++ b/slices/core/src/main/res/values-fr/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Autoriser <xliff:g id="APP_0">%1$s</xliff:g> à afficher des éléments de <xliff:g id="APP_2">%2$s</xliff:g> ?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Accès aux informations de <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Capacité d\'action dans <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Autoriser"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Refuser"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-gl/strings.xml b/slices/core/src/main/res/values-gl/strings.xml
index 50befe5..5ef1215 100644
--- a/slices/core/src/main/res/values-gl/strings.xml
+++ b/slices/core/src/main/res/values-gl/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Queres permitir que <xliff:g id="APP_0">%1$s</xliff:g> mostre fragmentos de aplicación de <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Pode ler información da aplicación <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Pode levar a cabo accións dentro da aplicación <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Permitir"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Denegar"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-gu/strings.xml b/slices/core/src/main/res/values-gu/strings.xml
index 804b774..9b8f733 100644
--- a/slices/core/src/main/res/values-gu/strings.xml
+++ b/slices/core/src/main/res/values-gu/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g>ને <xliff:g id="APP_2">%2$s</xliff:g> સ્લાઇસ બતાવવાની મંજૂરી આપીએ?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- તે <xliff:g id="APP">%1$s</xliff:g>માંથી માહિતી વાંચી શકે છે"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- તે <xliff:g id="APP">%1$s</xliff:g>ની અંદર ક્રિયાઓ કરી શકે છે"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"મંજૂરી આપો"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"નકારો"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-hi/strings.xml b/slices/core/src/main/res/values-hi/strings.xml
index 9dfe2b0..f5215cb 100644
--- a/slices/core/src/main/res/values-hi/strings.xml
+++ b/slices/core/src/main/res/values-hi/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> को <xliff:g id="APP_2">%2$s</xliff:g> के हिस्से (स्लाइस) दिखाने की मंज़ूरी दें?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- यह <xliff:g id="APP">%1$s</xliff:g> से जानकारी पा सकता है"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- यह <xliff:g id="APP">%1$s</xliff:g> में कार्रवाई कर सकता है"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"अनुमति दें"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"अनुमति न दें"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-hr/strings.xml b/slices/core/src/main/res/values-hr/strings.xml
index 9e614b5..b7980bd 100644
--- a/slices/core/src/main/res/values-hr/strings.xml
+++ b/slices/core/src/main/res/values-hr/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Želite li dopustiti aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> da prikazuje isječke aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– može čitati informacije aplikacije <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– može vršiti radnje u aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Dopusti"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Odbij"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-hu/strings.xml b/slices/core/src/main/res/values-hu/strings.xml
index 004829f..89b800c 100644
--- a/slices/core/src/main/res/values-hu/strings.xml
+++ b/slices/core/src/main/res/values-hu/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Engedélyezi a(z) <xliff:g id="APP_0">%1$s</xliff:g> alkalmazásnak, hogy részleteket mutasson a(z) <xliff:g id="APP_2">%2$s</xliff:g> alkalmazásból?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Információkat olvashat a(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazásból"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Műveleteket végezhet a(z) <xliff:g id="APP">%1$s</xliff:g> alkalmazáson belül"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Engedélyezés"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Elutasítás"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-hy/strings.xml b/slices/core/src/main/res/values-hy/strings.xml
index 1d716d7..2512ee9 100644
--- a/slices/core/src/main/res/values-hy/strings.xml
+++ b/slices/core/src/main/res/values-hy/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Թույլատրե՞լ <xliff:g id="APP_0">%1$s</xliff:g> հավելվածին ցուցադրել հատվածներ <xliff:g id="APP_2">%2$s</xliff:g> հավելվածից"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Կարող է կարդալ տեղեկություններ <xliff:g id="APP">%1$s</xliff:g> հավելվածից"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Կարող է կատարել գործողություններ <xliff:g id="APP">%1$s</xliff:g> հավելվածում"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Թույլատրել"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Մերժել"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-in/strings.xml b/slices/core/src/main/res/values-in/strings.xml
index 860ed1c..87afa02 100644
--- a/slices/core/src/main/res/values-in/strings.xml
+++ b/slices/core/src/main/res/values-in/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Izinkan <xliff:g id="APP_0">%1$s</xliff:g> menampilkan potongan <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Dapat membaca informasi dari <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Dapat mengambil tindakan di dalam <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Izinkan"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Tolak"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-is/strings.xml b/slices/core/src/main/res/values-is/strings.xml
index da79a76..5845ff1 100644
--- a/slices/core/src/main/res/values-is/strings.xml
+++ b/slices/core/src/main/res/values-is/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Viltu leyfa <xliff:g id="APP_0">%1$s</xliff:g> að sýna sneiðar úr <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Það getur lesið upplýsingar úr <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Það getur gripið til aðgerða í <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Leyfa"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Hafna"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-it/strings.xml b/slices/core/src/main/res/values-it/strings.xml
index 5518d66..58509f9 100644
--- a/slices/core/src/main/res/values-it/strings.xml
+++ b/slices/core/src/main/res/values-it/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Vuoi consentire all\'app <xliff:g id="APP_0">%1$s</xliff:g> di mostrare porzioni dell\'app <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Può leggere informazioni dell\'app <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Può compiere azioni nell\'app <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Consenti"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Rifiuta"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-iw/strings.xml b/slices/core/src/main/res/values-iw/strings.xml
index 2151548..4a6791f 100644
--- a/slices/core/src/main/res/values-iw/strings.xml
+++ b/slices/core/src/main/res/values-iw/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"האם לאפשר ל-<xliff:g id="APP_0">%1$s</xliff:g> להציג חלקים מ-<xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- תהיה לה אפשרות לקרוא מידע מהאפליקציה <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- תהיה לה יכולת לנקוט פעולה בתוך <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"אישור"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"אני לא מרשה"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ja/strings.xml b/slices/core/src/main/res/values-ja/strings.xml
index 1c28f4c..e619da5 100644
--- a/slices/core/src/main/res/values-ja/strings.xml
+++ b/slices/core/src/main/res/values-ja/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_2">%2$s</xliff:g> のスライスの表示を <xliff:g id="APP_0">%1$s</xliff:g> に許可しますか?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- <xliff:g id="APP">%1$s</xliff:g> からの情報を読み取ることができます"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- <xliff:g id="APP">%1$s</xliff:g> 内部で操作することがあります"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"許可"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"拒否"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ka/strings.xml b/slices/core/src/main/res/values-ka/strings.xml
index b78206c..2558632 100644
--- a/slices/core/src/main/res/values-ka/strings.xml
+++ b/slices/core/src/main/res/values-ka/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"ანიჭებთ ნებართვას <xliff:g id="APP_0">%1$s</xliff:g>-ს, აჩვენოს <xliff:g id="APP_2">%2$s</xliff:g>-ის ფრაგმენტები?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- მას შეუძლია ინფორმაციის <xliff:g id="APP">%1$s</xliff:g>-დან წაკითხვა"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- მას შეუძლია ქმედებების <xliff:g id="APP">%1$s</xliff:g>-ში განხორციელება"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"დაშვება"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"უარყოფა"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-kk/strings.xml b/slices/core/src/main/res/values-kk/strings.xml
index fcb0509..21f8465 100644
--- a/slices/core/src/main/res/values-kk/strings.xml
+++ b/slices/core/src/main/res/values-kk/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> қолданбасына <xliff:g id="APP_2">%2$s</xliff:g> қолданбасының үзінділерін көрсетуге рұқсат берілсін бе?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- <xliff:g id="APP">%1$s</xliff:g> қолданбасындағы ақпаратты оқи алады"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- <xliff:g id="APP">%1$s</xliff:g> қолданбасында әрекет ете алады"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Рұқсат беру"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Тыйым салу"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-km/strings.xml b/slices/core/src/main/res/values-km/strings.xml
index 5d0a988..1a5755b 100644
--- a/slices/core/src/main/res/values-km/strings.xml
+++ b/slices/core/src/main/res/values-km/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"អនុញ្ញាតឱ្យ <xliff:g id="APP_0">%1$s</xliff:g> បង្ហាញ​ស្ថិតិប្រើប្រាស់​របស់ <xliff:g id="APP_2">%2$s</xliff:g> ?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- វា​អាច​អាន​ព័ត៌មាន​ពី <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- វាអាច​ធ្វើសកម្មភាព​នៅក្នុង <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"អនុញ្ញាត"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"បដិសេធ"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-kn/strings.xml b/slices/core/src/main/res/values-kn/strings.xml
index 7fe32e0..0f14a36 100644
--- a/slices/core/src/main/res/values-kn/strings.xml
+++ b/slices/core/src/main/res/values-kn/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_2">%2$s</xliff:g> ಸ್ಲೈಸ್‌ಗಳನ್ನು ತೋರಿಸಲು <xliff:g id="APP_0">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- ಇದು <xliff:g id="APP">%1$s</xliff:g> ನಿಂದ ಮಾಹಿತಿಯನ್ನು ಓದಬಹುದು"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- ಇದು <xliff:g id="APP">%1$s</xliff:g> ಒಳಗಡೆ ಕ್ರಿಯೆಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳಬಹುದು"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"ಅನುಮತಿಸಿ"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"ನಿರಾಕರಿಸಿ"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ko/strings.xml b/slices/core/src/main/res/values-ko/strings.xml
index 93c62f0..81a6707 100644
--- a/slices/core/src/main/res/values-ko/strings.xml
+++ b/slices/core/src/main/res/values-ko/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g>에서 <xliff:g id="APP_2">%2$s</xliff:g>의 슬라이스를 표시하도록 허용하시겠습니까?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- <xliff:g id="APP">%1$s</xliff:g>의 정보를 읽을 수 있음"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- <xliff:g id="APP">%1$s</xliff:g>에서 작업할 수 있음"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"허용"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"거부"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ky/strings.xml b/slices/core/src/main/res/values-ky/strings.xml
index 9615740..9a26322 100644
--- a/slices/core/src/main/res/values-ky/strings.xml
+++ b/slices/core/src/main/res/values-ky/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> колдонмосуна <xliff:g id="APP_2">%2$s</xliff:g> үлгүлөрүн көрсөтүүгө уруксат берилсинби?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- <xliff:g id="APP">%1$s</xliff:g> колдонмосунун маалыматын окуйт"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- <xliff:g id="APP">%1$s</xliff:g> колдонмосунда аракеттерди аткарат"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Уруксат берүү"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Тыюу салынат"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-lo/strings.xml b/slices/core/src/main/res/values-lo/strings.xml
index 9b18f5b..aeeedc9 100644
--- a/slices/core/src/main/res/values-lo/strings.xml
+++ b/slices/core/src/main/res/values-lo/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"ອະນຸຍາດ <xliff:g id="APP_0">%1$s</xliff:g> ໃຫ້ສະແດງ <xliff:g id="APP_2">%2$s</xliff:g> ສະໄລ້ບໍ?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- ມັນສາມາດອ່ານຂໍ້ມູນຈາກ <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- ມັນສາມາດໃຊ້ຄຳສັ່ງພາຍໃນ <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"ອະນຸຍາດ"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"ປະຕິເສດ"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-lt/strings.xml b/slices/core/src/main/res/values-lt/strings.xml
index 1e88cd6..604ee1d 100644
--- a/slices/core/src/main/res/values-lt/strings.xml
+++ b/slices/core/src/main/res/values-lt/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Leisti „<xliff:g id="APP_0">%1$s</xliff:g>“ rodyti „<xliff:g id="APP_2">%2$s</xliff:g>“ fragmentus?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Gali nuskaityti informaciją iš „<xliff:g id="APP">%1$s</xliff:g>“"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Gali imtis veiksmų programoje „<xliff:g id="APP">%1$s</xliff:g>“"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Leisti"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Atmesti"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-lv/strings.xml b/slices/core/src/main/res/values-lv/strings.xml
index 1f3ccde..60dbac8 100644
--- a/slices/core/src/main/res/values-lv/strings.xml
+++ b/slices/core/src/main/res/values-lv/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Vai atļaut lietotnei <xliff:g id="APP_0">%1$s</xliff:g> rādīt lietotnes <xliff:g id="APP_2">%2$s</xliff:g> sadaļas?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Var lasīt informāciju no lietotnes <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Var veikt darbības lietotnē <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Atļaut"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Neatļaut"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-mk/strings.xml b/slices/core/src/main/res/values-mk/strings.xml
index a5ccc53..fd0a8d2 100644
--- a/slices/core/src/main/res/values-mk/strings.xml
+++ b/slices/core/src/main/res/values-mk/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Да се дозволи <xliff:g id="APP_0">%1$s</xliff:g> да прикажува делови од <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Може да чита информации од <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Може да презема дејства во <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Дозволете"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Одбијте"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ml/strings.xml b/slices/core/src/main/res/values-ml/strings.xml
index 21802b7..bb565fa 100644
--- a/slices/core/src/main/res/values-ml/strings.xml
+++ b/slices/core/src/main/res/values-ml/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_2">%2$s</xliff:g> സ്ലൈസുകൾ കാണിക്കാൻ <xliff:g id="APP_0">%1$s</xliff:g>-നെ അനുവദിക്കണോ?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- ഇതിന് <xliff:g id="APP">%1$s</xliff:g>-ൽ നിന്ന് വിവരങ്ങൾ വായിക്കാനാകും"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- ഇതിന് <xliff:g id="APP">%1$s</xliff:g>-നുള്ളിൽ പ്രവർത്തനങ്ങൾ ചെയ്യാനാകും"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"അനുവദിക്കുക"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"നിരസിക്കുക"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-mn/strings.xml b/slices/core/src/main/res/values-mn/strings.xml
index 8e0661a..ce2b5b9 100644
--- a/slices/core/src/main/res/values-mn/strings.xml
+++ b/slices/core/src/main/res/values-mn/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g>-д <xliff:g id="APP_2">%2$s</xliff:g>-н хэсгүүдийг харуулахыг зөвшөөрөх үү?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Энэ <xliff:g id="APP">%1$s</xliff:g>-с мэдээлэл унших боломжтой"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Энэ <xliff:g id="APP">%1$s</xliff:g> дотор үйлдэл хийх боломжтой"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Зөвшөөрөх"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Татгалзах"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-mr/strings.xml b/slices/core/src/main/res/values-mr/strings.xml
index ab48521..7ed173d 100644
--- a/slices/core/src/main/res/values-mr/strings.xml
+++ b/slices/core/src/main/res/values-mr/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> ला <xliff:g id="APP_2">%2$s</xliff:g> चे तुकडे दाखवण्याची अनुमती द्यायची का?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- ते <xliff:g id="APP">%1$s</xliff:g> ची माहिती वाचू शकते"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- ते <xliff:g id="APP">%1$s</xliff:g> मध्ये कृती करू शकते"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"अनुमती द्या"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"नकार द्या"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ms/strings.xml b/slices/core/src/main/res/values-ms/strings.xml
index 4b20a63..e4dc766 100644
--- a/slices/core/src/main/res/values-ms/strings.xml
+++ b/slices/core/src/main/res/values-ms/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Benarkan <xliff:g id="APP_0">%1$s</xliff:g> menunjukkan hirisan <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Hos hirisan boleh membaca maklumat daripada <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Hos hirisan boleh mengambil tindakan dalam <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Benarkan"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Tolak"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-my/strings.xml b/slices/core/src/main/res/values-my/strings.xml
index 666640ef..109f680 100644
--- a/slices/core/src/main/res/values-my/strings.xml
+++ b/slices/core/src/main/res/values-my/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> အား <xliff:g id="APP_2">%2$s</xliff:g> ၏အချပ်များ ပြသခွင့်ပြုပါသလား။"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- ၎င်းသည် <xliff:g id="APP">%1$s</xliff:g> မှ အချက်အလက်ကို ဖတ်နိုင်သည်"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- ၎င်းသည် <xliff:g id="APP">%1$s</xliff:g> အတွင်း လုပ်ဆောင်ချက်များ ပြုလုပ်နိုင်သည်"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"ခွင့်ပြုရန်"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"ငြင်းပယ်ရန်"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-nb/strings.xml b/slices/core/src/main/res/values-nb/strings.xml
index 9448d03..d3246d5 100644
--- a/slices/core/src/main/res/values-nb/strings.xml
+++ b/slices/core/src/main/res/values-nb/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Vil du tillate at <xliff:g id="APP_0">%1$s</xliff:g> viser <xliff:g id="APP_2">%2$s</xliff:g>-utsnitt?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Den kan lese informasjon fra <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Den kan utføre handlinger i <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Tillat"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Ikke tillat"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ne/strings.xml b/slices/core/src/main/res/values-ne/strings.xml
index bfa42445..baba49e 100644
--- a/slices/core/src/main/res/values-ne/strings.xml
+++ b/slices/core/src/main/res/values-ne/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> लाई <xliff:g id="APP_2">%2$s</xliff:g> का स्लाइसहरू देखाउन अनुमति दिने हो?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- यसले <xliff:g id="APP">%1$s</xliff:g> को जानकारी पढ्न सक्छ"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- यसले <xliff:g id="APP">%1$s</xliff:g> भित्र कारबाही गर्न सक्छ"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"अनुमति दिनुहोस्"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"नदिने"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-nl/strings.xml b/slices/core/src/main/res/values-nl/strings.xml
index 4d8006e..ffbb174 100644
--- a/slices/core/src/main/res/values-nl/strings.xml
+++ b/slices/core/src/main/res/values-nl/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> toestaan om segmenten van <xliff:g id="APP_2">%2$s</xliff:g> te tonen?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Deze kan informatie lezen van <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Deze kan acties uitvoeren in <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Toestaan"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Weigeren"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-or/strings.xml b/slices/core/src/main/res/values-or/strings.xml
index a757613..672f51c 100644
--- a/slices/core/src/main/res/values-or/strings.xml
+++ b/slices/core/src/main/res/values-or/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_2">%2$s</xliff:g> ସ୍ଲାଇସ୍‌କୁ ଦେଖାଇବା ପାଇଁ <xliff:g id="APP_0">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- ଏହା <xliff:g id="APP">%1$s</xliff:g>ରୁ ସୂଚନାକୁ ପଢ଼ିପାରିବ"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- ଏହା <xliff:g id="APP">%1$s</xliff:g> ଭିତରେ କାମ କରିପାରିବ"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"ଅନୁମତି ଦିଅନ୍ତୁ"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"ଅଗ୍ରାହ୍ୟ କରନ୍ତୁ"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-pa/strings.xml b/slices/core/src/main/res/values-pa/strings.xml
index d68cc39..03c926e 100644
--- a/slices/core/src/main/res/values-pa/strings.xml
+++ b/slices/core/src/main/res/values-pa/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"ਕੀ <xliff:g id="APP_0">%1$s</xliff:g> ਨੂੰ <xliff:g id="APP_2">%2$s</xliff:g> ਦੇ ਹਿੱਸੇ ਦਿਖਾਉਣ ਦੇਣੇ ਹਨ?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- ਇਹ <xliff:g id="APP">%1$s</xliff:g> ਵਿੱਚੋਂ ਜਾਣਕਾਰੀ ਪੜ੍ਹ ਸਕਦਾ ਹੈ"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- ਇਸ <xliff:g id="APP">%1$s</xliff:g> ਦੇ ਅੰਦਰ ਕਾਰਵਾਈਆਂ ਕਰ ਸਕਦਾ ਹੈ"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"ਕਰਨ ਦਿਓ"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-pl/strings.xml b/slices/core/src/main/res/values-pl/strings.xml
index ea32902..7ef7e74 100644
--- a/slices/core/src/main/res/values-pl/strings.xml
+++ b/slices/core/src/main/res/values-pl/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Zezwolić aplikacji <xliff:g id="APP_0">%1$s</xliff:g> na pokazywanie wycinków z aplikacji <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Może odczytywać informacje z aplikacji <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Może wykonywać działania w aplikacji <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Zezwól"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Odmów"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-pt-rBR/strings.xml b/slices/core/src/main/res/values-pt-rBR/strings.xml
index b58e786..4920aed 100644
--- a/slices/core/src/main/res/values-pt-rBR/strings.xml
+++ b/slices/core/src/main/res/values-pt-rBR/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Permitir que <xliff:g id="APP_0">%1$s</xliff:g> mostre partes do app <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Pode ler informações do app <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Pode realizar ações no app <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Permitir"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Negar"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-pt-rPT/strings.xml b/slices/core/src/main/res/values-pt-rPT/strings.xml
index 832b5e5..cdf0555 100644
--- a/slices/core/src/main/res/values-pt-rPT/strings.xml
+++ b/slices/core/src/main/res/values-pt-rPT/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Permitir que a app <xliff:g id="APP_0">%1$s</xliff:g> mostre partes da app <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Pode ler informações da app <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Pode realizar ações na app <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Permitir"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Recusar"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-pt/strings.xml b/slices/core/src/main/res/values-pt/strings.xml
index b58e786..4920aed 100644
--- a/slices/core/src/main/res/values-pt/strings.xml
+++ b/slices/core/src/main/res/values-pt/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Permitir que <xliff:g id="APP_0">%1$s</xliff:g> mostre partes do app <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Pode ler informações do app <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Pode realizar ações no app <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Permitir"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Negar"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ro/strings.xml b/slices/core/src/main/res/values-ro/strings.xml
index 2db5e57..68da8f3 100644
--- a/slices/core/src/main/res/values-ro/strings.xml
+++ b/slices/core/src/main/res/values-ro/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Permiteți <xliff:g id="APP_0">%1$s</xliff:g> să afișeze porțiuni din <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Poate citi informații din <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Poate efectua acțiuni în <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Permiteți"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Refuzați"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ru/strings.xml b/slices/core/src/main/res/values-ru/strings.xml
index 89dafbc..5a933ca 100644
--- a/slices/core/src/main/res/values-ru/strings.xml
+++ b/slices/core/src/main/res/values-ru/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Разрешить приложению \"<xliff:g id="APP_0">%1$s</xliff:g>\" показывать фрагменты приложения \"<xliff:g id="APP_2">%2$s</xliff:g>\"?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Ему станут доступны данные из приложения \"<xliff:g id="APP">%1$s</xliff:g>\"."</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Оно сможет совершать действия в приложении \"<xliff:g id="APP">%1$s</xliff:g>\"."</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Да"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Нет"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-si/strings.xml b/slices/core/src/main/res/values-si/strings.xml
index e5e8478..74ff957 100644
--- a/slices/core/src/main/res/values-si/strings.xml
+++ b/slices/core/src/main/res/values-si/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> හට කොටස් <xliff:g id="APP_2">%2$s</xliff:g>ක් පෙන්වීමට ඉඩ දෙන්නද?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- එයට <xliff:g id="APP">%1$s</xliff:g> වෙතින් තොරතුරු කියවිය හැකිය"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- එයට <xliff:g id="APP">%1$s</xliff:g> ඇතුළත ක්‍රියාමාර්ග ගත හැකිය"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"ඉඩ දෙන්න"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"ප්‍රතික්ෂේප කර."</string>
 </resources>
diff --git a/slices/core/src/main/res/values-sk/strings.xml b/slices/core/src/main/res/values-sk/strings.xml
index 8070718..04053ff 100644
--- a/slices/core/src/main/res/values-sk/strings.xml
+++ b/slices/core/src/main/res/values-sk/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Povoliť aplikácii <xliff:g id="APP_0">%1$s</xliff:g> zobrazovať rezy z aplikácie <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Môže čítať informácie z aplikácie <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Môže vykonávať akcie v aplikácii <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Povoliť"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Zamietnuť"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-sl/strings.xml b/slices/core/src/main/res/values-sl/strings.xml
index b3ab6f4..88df9ec 100644
--- a/slices/core/src/main/res/values-sl/strings.xml
+++ b/slices/core/src/main/res/values-sl/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Ali aplikaciji <xliff:g id="APP_0">%1$s</xliff:g> dovolite prikazovanje izrezov iz aplikacije <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– lahko bere podatke v aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– lahko izvaja dejanja v aplikaciji <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Dovoli"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Zavrni"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-sq/strings.xml b/slices/core/src/main/res/values-sq/strings.xml
index 9ae77dd..5e56aea 100644
--- a/slices/core/src/main/res/values-sq/strings.xml
+++ b/slices/core/src/main/res/values-sq/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Të lejohet <xliff:g id="APP_0">%1$s</xliff:g> që të shfaqë pjesë të <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Mund të lexojë informacion nga <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Mund të ndërmarrë veprime brenda <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Lejo"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Refuzo"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-sr/strings.xml b/slices/core/src/main/res/values-sr/strings.xml
index b7c29c5..1064600 100644
--- a/slices/core/src/main/res/values-sr/strings.xml
+++ b/slices/core/src/main/res/values-sr/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Желите ли да дозволите апликацији <xliff:g id="APP_0">%1$s</xliff:g> да приказује исечке из апликације <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Може да чита податке из апликације <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Може да обавља радње у апликацији <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Дозволи"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Одбиј"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-sv/strings.xml b/slices/core/src/main/res/values-sv/strings.xml
index 9be28b3..3a78a19 100644
--- a/slices/core/src/main/res/values-sv/strings.xml
+++ b/slices/core/src/main/res/values-sv/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Tillåter du att bitar av <xliff:g id="APP_2">%2$s</xliff:g> visas i <xliff:g id="APP_0">%1$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– Kan läsa information från <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– Kan vidta åtgärder i <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Tillåt"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Neka"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-sw/strings.xml b/slices/core/src/main/res/values-sw/strings.xml
index 28459cd..e6a72a0 100644
--- a/slices/core/src/main/res/values-sw/strings.xml
+++ b/slices/core/src/main/res/values-sw/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Ungependa kuruhusu <xliff:g id="APP_0">%1$s</xliff:g> ionyeshe vipengee <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Inaweza kusoma maelezo kutoka <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Inaweza kuchukua hatua ndani ya <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Ruhusu"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Kataa"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ta/strings.xml b/slices/core/src/main/res/values-ta/strings.xml
index 36be75a..7f13957 100644
--- a/slices/core/src/main/res/values-ta/strings.xml
+++ b/slices/core/src/main/res/values-ta/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_2">%2$s</xliff:g> ஆப்ஸின் விழிப்பூட்டல்களைக் காண்பிக்க, <xliff:g id="APP_0">%1$s</xliff:g> ஆப்ஸை அனுமதிக்கவா?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- இது, <xliff:g id="APP">%1$s</xliff:g> பயன்பாட்டிலிருக்கும் தகவலைப் படிக்கும்"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- இது, <xliff:g id="APP">%1$s</xliff:g> பயன்பாட்டிற்குள் செயல்பாடுகளில் ஈடுபடும்"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"அனுமதி"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"நிராகரி"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-te/strings.xml b/slices/core/src/main/res/values-te/strings.xml
index ce51a47..acbfe1f 100644
--- a/slices/core/src/main/res/values-te/strings.xml
+++ b/slices/core/src/main/res/values-te/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_2">%2$s</xliff:g> స్లైస్‌లను చూపించడానికి <xliff:g id="APP_0">%1$s</xliff:g>ని అనుమతించాలా?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- ఇది <xliff:g id="APP">%1$s</xliff:g> నుండి సమాచారాన్ని చదవగలుగుతుంది"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- ఇది <xliff:g id="APP">%1$s</xliff:g> లోపల చర్యలు తీసుకోగలుగుతుంది"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"అనుమతించు"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"తిరస్కరించు"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-th/strings.xml b/slices/core/src/main/res/values-th/strings.xml
index 07371a0..b561742 100644
--- a/slices/core/src/main/res/values-th/strings.xml
+++ b/slices/core/src/main/res/values-th/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"อนุญาตให้ <xliff:g id="APP_0">%1$s</xliff:g> แสดงส่วนต่างๆ ของ <xliff:g id="APP_2">%2$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- อ่านข้อมูลจาก <xliff:g id="APP">%1$s</xliff:g> ได้"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- ดำเนินการใน <xliff:g id="APP">%1$s</xliff:g> ได้"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"อนุญาต"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"ปฏิเสธ"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-tl/strings.xml b/slices/core/src/main/res/values-tl/strings.xml
index e4bf3e0..3e0daf7 100644
--- a/slices/core/src/main/res/values-tl/strings.xml
+++ b/slices/core/src/main/res/values-tl/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Payagan ang <xliff:g id="APP_0">%1$s</xliff:g> na ipakita ang mga slice ng <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Nakakabasa ito ng impormasyon mula sa <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Nakakagawa ito ng mga pagkilos sa loob ng <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Payagan"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Tanggihan"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-tr/strings.xml b/slices/core/src/main/res/values-tr/strings.xml
index 2cbcfda..d8d3c87 100644
--- a/slices/core/src/main/res/values-tr/strings.xml
+++ b/slices/core/src/main/res/values-tr/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> uygulamasının, <xliff:g id="APP_2">%2$s</xliff:g> dilimlerini göstermesine izin verilsin mi?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- <xliff:g id="APP">%1$s</xliff:g> uygulamasından bilgileri okuyabilir"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- <xliff:g id="APP">%1$s</xliff:g> uygulamasında işlem yapabilir"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"İzin ver"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Reddet"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-uk/strings.xml b/slices/core/src/main/res/values-uk/strings.xml
index b842f5c..86dd1bd 100644
--- a/slices/core/src/main/res/values-uk/strings.xml
+++ b/slices/core/src/main/res/values-uk/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Дозволити додатку <xliff:g id="APP_0">%1$s</xliff:g> показувати фрагменти додатка <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Може переглядати інформацію з додатка <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Може виконувати дії в додатку <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Дозволити"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Заборонити"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-ur/strings.xml b/slices/core/src/main/res/values-ur/strings.xml
index 8999e25..39a9820 100644
--- a/slices/core/src/main/res/values-ur/strings.xml
+++ b/slices/core/src/main/res/values-ur/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> کو <xliff:g id="APP_2">%2$s</xliff:g> کے سلائسز دکھانے کی اجازت دیں؟"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- یہ <xliff:g id="APP">%1$s</xliff:g> کی معلومات پڑھ سکتا ہے"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- یہ <xliff:g id="APP">%1$s</xliff:g> کے اندر کارروائیاں کر سکتا ہے"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"اجازت دیں"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"مسترد کریں"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-uz/strings.xml b/slices/core/src/main/res/values-uz/strings.xml
index 9fcb4ce..1d6febd 100644
--- a/slices/core/src/main/res/values-uz/strings.xml
+++ b/slices/core/src/main/res/values-uz/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"<xliff:g id="APP_0">%1$s</xliff:g> ilovasiga <xliff:g id="APP_2">%2$s</xliff:g> ilovasidan fragmentlar ko‘rsatishga ruxsat berilsinmi?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"– <xliff:g id="APP">%1$s</xliff:g> ma’lumotlarini o‘qiy oladi"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"– <xliff:g id="APP">%1$s</xliff:g> ichida amallar bajara oladi"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Ruxsat"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Rad etish"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-vi/strings.xml b/slices/core/src/main/res/values-vi/strings.xml
index c067ac8..d8e71a5 100644
--- a/slices/core/src/main/res/values-vi/strings.xml
+++ b/slices/core/src/main/res/values-vi/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Cho phép <xliff:g id="APP_0">%1$s</xliff:g> hiển thị các lát của <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Có thể đọc thông tin từ <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Có thể thực hiện hành động bên trong <xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Cho phép"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Từ chối"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-zh-rCN/strings.xml b/slices/core/src/main/res/values-zh-rCN/strings.xml
index 6ab2d3e..2ec34bc 100644
--- a/slices/core/src/main/res/values-zh-rCN/strings.xml
+++ b/slices/core/src/main/res/values-zh-rCN/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"要允许“<xliff:g id="APP_0">%1$s</xliff:g>”显示“<xliff:g id="APP_2">%2$s</xliff:g>”图块吗?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- 可以读取“<xliff:g id="APP">%1$s</xliff:g>”中的信息"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- 可以在“<xliff:g id="APP">%1$s</xliff:g>”内执行操作"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"允许"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"拒绝"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-zh-rHK/strings.xml b/slices/core/src/main/res/values-zh-rHK/strings.xml
index 5cf6943..118c2ac 100644
--- a/slices/core/src/main/res/values-zh-rHK/strings.xml
+++ b/slices/core/src/main/res/values-zh-rHK/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"要允許「<xliff:g id="APP_0">%1$s</xliff:g>」顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的快訊嗎?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- 可以讀取「<xliff:g id="APP">%1$s</xliff:g>」中的資料"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- 可以在「<xliff:g id="APP">%1$s</xliff:g>」內執行操作"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"允許"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"拒絕"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-zh-rTW/strings.xml b/slices/core/src/main/res/values-zh-rTW/strings.xml
index df1ab8b..53c802d 100644
--- a/slices/core/src/main/res/values-zh-rTW/strings.xml
+++ b/slices/core/src/main/res/values-zh-rTW/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"要允許「<xliff:g id="APP_0">%1$s</xliff:g>」顯示「<xliff:g id="APP_2">%2$s</xliff:g>」的區塊嗎?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- 它可以讀取「<xliff:g id="APP">%1$s</xliff:g>」的資訊"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- 它可以在「<xliff:g id="APP">%1$s</xliff:g>」內執行操作"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"允許"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"拒絕"</string>
 </resources>
diff --git a/slices/core/src/main/res/values-zu/strings.xml b/slices/core/src/main/res/values-zu/strings.xml
index d9ada48..b1fac39 100644
--- a/slices/core/src/main/res/values-zu/strings.xml
+++ b/slices/core/src/main/res/values-zu/strings.xml
@@ -21,7 +21,6 @@
     <string name="abc_slice_permission_title" msgid="4175332421259324948">"Vumela i-<xliff:g id="APP_0">%1$s</xliff:g> ukuthi ibonise izingcezu ze-<xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="abc_slice_permission_text_1" msgid="4525743640399572811">"- Ingafunda ulwazi kusukela ku-<xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="abc_slice_permission_text_2" msgid="7323565634860251794">"- Ingenza izenzo ngaphakathi kwe-<xliff:g id="APP">%1$s</xliff:g>"</string>
-
     <string name="abc_slice_permission_allow" msgid="5024599872061409708">"Vumela"</string>
     <string name="abc_slice_permission_deny" msgid="3819478292430407705">"Phika"</string>
 </resources>
diff --git a/slices/view/src/main/res/values-my/strings.xml b/slices/view/src/main/res/values-my/strings.xml
index 4a3e3d4..5b9d57c 100644
--- a/slices/view/src/main/res/values-my/strings.xml
+++ b/slices/view/src/main/res/values-my/strings.xml
@@ -19,7 +19,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_slice_more_content" msgid="6405516388971241142">"+ <xliff:g id="NUMBER">%1$d</xliff:g>"</string>
     <string name="abc_slice_more" msgid="1983560225998630901">"နောက်ထပ်"</string>
-    <string name="abc_slice_show_more" msgid="1567717014004692768">"နောက်ထပ် ပြပါ"</string>
+    <string name="abc_slice_show_more" msgid="1567717014004692768">"ပိုပြပါ"</string>
     <string name="abc_slice_updated" msgid="8155085405396453848">"<xliff:g id="TIME">%1$s</xliff:g> က အပ်ဒိတ်လုပ်ထားသည်"</string>
     <plurals name="abc_slice_duration_min" formatted="false" msgid="6996334305156847955">
       <item quantity="other">ပြီးခဲ့သော<xliff:g id="ID_2">%d</xliff:g>မိနစ်</item>
diff --git a/startup/startup-runtime-lint/build.gradle b/startup/startup-runtime-lint/build.gradle
index 5423d95..22a35542 100644
--- a/startup/startup-runtime-lint/build.gradle
+++ b/startup/startup-runtime-lint/build.gradle
@@ -25,13 +25,7 @@
 }
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly(LINT_API_LATEST)
-    } else {
-        compileOnly(LINT_API_MIN)
-    }
+    compileOnly(LINT_API_MIN)
     compileOnly(KOTLIN_STDLIB)
 
     testImplementation(KOTLIN_STDLIB)
diff --git a/tracing/tracing/build.gradle b/tracing/tracing/build.gradle
index fbd0e02..7582a61 100644
--- a/tracing/tracing/build.gradle
+++ b/tracing/tracing/build.gradle
@@ -29,7 +29,7 @@
 }
 
 dependencies {
-    implementation("androidx.annotation:annotation:1.1.0")
+    implementation("androidx.annotation:annotation:1.2.0")
     androidTestImplementation(KOTLIN_STDLIB)
     androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
     androidTestImplementation(ANDROIDX_TEST_CORE)
diff --git a/tracing/tracing/lint-baseline.xml b/tracing/tracing/lint-baseline.xml
index 2c1ddc6..e17f06f 100644
--- a/tracing/tracing/lint-baseline.xml
+++ b/tracing/tracing/lint-baseline.xml
@@ -1,15 +1,3 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 29; however, the containing class androidx.tracing.Trace is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                return android.os.Trace.isEnabled();"
-        errorLine2="                                        ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/tracing/Trace.java"
-            line="62"
-            column="41"/>
-    </issue>
-
 </issues>
diff --git a/tracing/tracing/src/main/java/androidx/tracing/Trace.java b/tracing/tracing/src/main/java/androidx/tracing/Trace.java
index 9e63bc9..0520f2e 100644
--- a/tracing/tracing/src/main/java/androidx/tracing/Trace.java
+++ b/tracing/tracing/src/main/java/androidx/tracing/Trace.java
@@ -57,12 +57,10 @@
      */
     @SuppressLint("NewApi")
     public static boolean isEnabled() {
-        try {
-            if (sIsTagEnabledMethod == null) {
-                return android.os.Trace.isEnabled();
-            }
-        } catch (NoSuchMethodError | NoClassDefFoundError ignore) {
+        if (Build.VERSION.SDK_INT >= 29) {
+            return TraceApi29Impl.isEnabled();
         }
+
         return isEnabledFallback();
     }
 
diff --git a/tracing/tracing/src/main/java/androidx/tracing/TraceApi29Impl.java b/tracing/tracing/src/main/java/androidx/tracing/TraceApi29Impl.java
index 0665212..14ba157 100644
--- a/tracing/tracing/src/main/java/androidx/tracing/TraceApi29Impl.java
+++ b/tracing/tracing/src/main/java/androidx/tracing/TraceApi29Impl.java
@@ -16,6 +16,7 @@
 
 package androidx.tracing;
 
+import androidx.annotation.DoNotInline;
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 
@@ -35,6 +36,14 @@
     }
 
     /**
+     * Checks whether or not tracing is currently enabled.
+     */
+    @DoNotInline
+    public static boolean isEnabled() {
+        return android.os.Trace.isEnabled();
+    }
+
+    /**
      * Writes a trace message to indicate that a given section of code has
      * begun. Must be followed by a call to {@link #endAsyncSection(String, int)} with the same
      * methodName and cookie.
diff --git a/versionedparcelable/versionedparcelable/src/androidTest/java/androidx/versionedparcelable/ParcelUtilsTest.java b/versionedparcelable/versionedparcelable/src/androidTest/java/androidx/versionedparcelable/ParcelUtilsTest.java
index 8ca1a22..cd2540b 100644
--- a/versionedparcelable/versionedparcelable/src/androidTest/java/androidx/versionedparcelable/ParcelUtilsTest.java
+++ b/versionedparcelable/versionedparcelable/src/androidTest/java/androidx/versionedparcelable/ParcelUtilsTest.java
@@ -79,6 +79,17 @@
         assertThat(result).isNull();
     }
 
+    @Test
+    public void putVersionedParcelableNullClearsKey() {
+        Bundle bundle = new Bundle();
+
+        ParcelUtils.putVersionedParcelable(bundle, "key", new ParcelUtilsParcelable());
+        assertThat(bundle.getBundle("key")).isNotNull();
+
+        ParcelUtils.putVersionedParcelable(bundle, "key", null);
+        assertThat(bundle.getBundle("key")).isNull();
+    }
+
     @VersionedParcelize
     public static class ParcelUtilsParcelable implements VersionedParcelable {
         @ParcelField(1)
diff --git a/versionedparcelable/versionedparcelable/src/main/java/androidx/versionedparcelable/ParcelUtils.java b/versionedparcelable/versionedparcelable/src/main/java/androidx/versionedparcelable/ParcelUtils.java
index 7f01a16a..15b615e 100644
--- a/versionedparcelable/versionedparcelable/src/main/java/androidx/versionedparcelable/ParcelUtils.java
+++ b/versionedparcelable/versionedparcelable/src/main/java/androidx/versionedparcelable/ParcelUtils.java
@@ -98,11 +98,12 @@
     public static void putVersionedParcelable(@NonNull Bundle b, @NonNull String key,
             @Nullable VersionedParcelable obj) {
         if (obj == null) {
-            return;
+            b.putParcelable(key, null);
+        } else {
+            Bundle innerBundle = new Bundle();
+            innerBundle.putParcelable(INNER_BUNDLE_KEY, toParcelable(obj));
+            b.putParcelable(key, innerBundle);
         }
-        Bundle innerBundle = new Bundle();
-        innerBundle.putParcelable(INNER_BUNDLE_KEY, toParcelable(obj));
-        b.putParcelable(key, innerBundle);
     }
 
     /**
diff --git a/wear/compose/material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/ChipTest.kt b/wear/compose/material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/ChipTest.kt
index fc4ae01..fe6d6f3 100644
--- a/wear/compose/material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/ChipTest.kt
+++ b/wear/compose/material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/ChipTest.kt
@@ -21,6 +21,7 @@
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.shape.CornerSize
 import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.testutils.assertShape
@@ -36,16 +37,21 @@
 import androidx.compose.ui.test.assertHeightIsEqualTo
 import androidx.compose.ui.test.assertIsEnabled
 import androidx.compose.ui.test.assertIsNotEnabled
+import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
 import androidx.compose.ui.test.captureToImage
+import androidx.compose.ui.test.getUnclippedBoundsInRoot
 import androidx.compose.ui.test.junit4.ComposeContentTestRule
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onChild
 import androidx.compose.ui.test.onChildAt
+import androidx.compose.ui.test.onNodeWithContentDescription
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.performClick
+import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.height
 import org.junit.Assert.assertEquals
 import org.junit.Rule
 import org.junit.Test
@@ -228,6 +234,27 @@
     fun gives_base_chip_correct_height() =
         verifyHeight(ChipDefaults.Height)
 
+    @Test
+    fun has_icon_in_correct_location_when_only_single_line_of_text() {
+        val iconTag = "TestIcon"
+        val chipTag = "chip"
+        rule
+            .setContentWithThemeForSizeAssertions(useUnmergedTree = true) {
+                Chip(
+                    onClick = {},
+                    label = { Text("Blue green orange") },
+                    icon = { CreateImage(iconTag) },
+                    modifier = Modifier.testTag(chipTag)
+                )
+            }
+        val itemBounds = rule.onNodeWithTag(chipTag).getUnclippedBoundsInRoot()
+        val iconBounds = rule.onNodeWithTag(iconTag, useUnmergedTree = true)
+            .getUnclippedBoundsInRoot()
+
+        rule.onNodeWithContentDescription(iconTag, useUnmergedTree = true)
+            .assertTopPositionInRootIsEqualTo((itemBounds.height - iconBounds.height) / 2)
+    }
+
     private fun verifyHeight(expectedHeight: Dp) {
         rule.verifyHeight(expectedHeight) {
             Chip(
@@ -254,6 +281,17 @@
         )
 
     @Test
+    fun three_slot_layout_gives_primary_enabled_colors() =
+        verifyThreeSlotColors(
+            TestChipColors.Primary,
+            ChipStatus.Enabled,
+            { MaterialTheme.colors.primary },
+            { MaterialTheme.colors.onPrimary },
+            { MaterialTheme.colors.onPrimary },
+            { MaterialTheme.colors.onPrimary }
+        )
+
+    @Test
     fun gives_primary_disabled_colors() =
         verifyColors(
             TestChipColors.Primary,
@@ -263,6 +301,17 @@
         )
 
     @Test
+    fun three_slot_layout_gives_primary_disabled_colors() =
+        verifyThreeSlotColors(
+            TestChipColors.Primary,
+            ChipStatus.Disabled,
+            { MaterialTheme.colors.primary },
+            { MaterialTheme.colors.onPrimary },
+            { MaterialTheme.colors.onPrimary },
+            { MaterialTheme.colors.onPrimary }
+        )
+
+    @Test
     fun gives_secondary_enabled_colors() =
         verifyColors(
             TestChipColors.Secondary,
@@ -272,6 +321,17 @@
         )
 
     @Test
+    fun three_slot_layout_gives_secondary_enabled_colors() =
+        verifyThreeSlotColors(
+            TestChipColors.Secondary,
+            ChipStatus.Enabled,
+            { MaterialTheme.colors.surface },
+            { MaterialTheme.colors.onSurface },
+            { MaterialTheme.colors.onSurface },
+            { MaterialTheme.colors.onSurface }
+        )
+
+    @Test
     fun gives_secondary_disabled_colors() =
         verifyColors(
             TestChipColors.Secondary,
@@ -281,6 +341,17 @@
         )
 
     @Test
+    fun three_slot_layout_gives_secondary_disabled_colors() =
+        verifyThreeSlotColors(
+            TestChipColors.Secondary,
+            ChipStatus.Enabled,
+            { MaterialTheme.colors.surface },
+            { MaterialTheme.colors.onSurface },
+            { MaterialTheme.colors.onSurface },
+            { MaterialTheme.colors.onSurface }
+        )
+
+    @Test
     fun allows_custom_enabled_background_color_override() {
         val overrideColor = Color.Yellow
         rule.setContentWithTheme {
@@ -344,6 +415,60 @@
     }
 
     @Test
+    fun allows_custom_enabled_secondary_label_color_override() {
+        val overrideColor = Color.Red
+        var actualContentColor = Color.Transparent
+        var actualSecondaryContentColor = Color.Transparent
+        var expectedContent = Color.Transparent
+        rule.setContentWithTheme {
+            expectedContent = MaterialTheme.colors.onPrimary
+            Chip(
+                onClick = {},
+                colors = ChipDefaults.chipColors(
+                    secondaryContentColor = overrideColor
+                ),
+                label = {
+                    actualContentColor = LocalContentColor.current
+                },
+                secondaryLabel = {
+                    actualSecondaryContentColor = LocalContentColor.current
+                },
+                enabled = true,
+                modifier = Modifier.testTag("test-item")
+            )
+        }
+        assertEquals(expectedContent, actualContentColor)
+        assertEquals(overrideColor, actualSecondaryContentColor)
+    }
+
+    @Test
+    fun allows_custom_enabled_icon_tint_color_override() {
+        val overrideColor = Color.Red
+        var actualContentColor = Color.Transparent
+        var actualIconTintColor = Color.Transparent
+        var expectedContent = Color.Transparent
+        rule.setContentWithTheme {
+            expectedContent = MaterialTheme.colors.onPrimary
+            Chip(
+                onClick = {},
+                colors = ChipDefaults.chipColors(
+                    iconTintColor = overrideColor
+                ),
+                label = {
+                    actualContentColor = LocalContentColor.current
+                },
+                icon = {
+                    actualIconTintColor = LocalContentColor.current
+                },
+                enabled = true,
+                modifier = Modifier.testTag("test-item")
+            )
+        }
+        assertEquals(expectedContent, actualContentColor)
+        assertEquals(overrideColor, actualIconTintColor)
+    }
+
+    @Test
     fun allows_custom_disabled_content_color_override() {
         val overrideColor = Color.Yellow
         var actualContentColor = Color.Transparent
@@ -406,6 +531,114 @@
                 .assertContainsColor(expectedBackground, 50.0f)
         }
     }
+
+    private fun verifyThreeSlotColors(
+        testChipColors: TestChipColors,
+        status: ChipStatus,
+        backgroundColor: @Composable () -> Color,
+        contentColor: @Composable () -> Color,
+        secondaryContentColor: @Composable () -> Color,
+        iconColor: @Composable () -> Color
+    ) {
+        var expectedBackground = Color.Transparent
+        var expectedContent = Color.Transparent
+        var expectedSecondaryContent = Color.Transparent
+        var expectedIcon = Color.Transparent
+        var actualContent = Color.Transparent
+        var actualSecondaryContent = Color.Transparent
+        var actualIcon = Color.Transparent
+        var expectedAlpha = 0.0f
+
+        rule.setContentWithTheme {
+            expectedBackground = backgroundColor()
+            expectedContent = contentColor()
+            expectedSecondaryContent = secondaryContentColor()
+            expectedIcon = iconColor()
+            expectedAlpha = ContentAlpha.disabled
+            Box(
+                modifier = Modifier
+                    .fillMaxSize()
+                    .background(expectedBackground)
+            ) {
+                Chip(
+                    onClick = {},
+                    colors = testChipColors.chipColors(),
+                    label = { actualContent = LocalContentColor.current },
+                    secondaryLabel = { actualSecondaryContent = LocalContentColor.current },
+                    icon = { actualIcon = LocalContentColor.current },
+                    enabled = status.enabled(),
+                    modifier = Modifier.testTag("test-item")
+                )
+            }
+        }
+
+        if (status.enabled()) {
+            assertEquals(expectedContent, actualContent)
+            assertEquals(expectedSecondaryContent, actualSecondaryContent)
+            assertEquals(expectedIcon, actualIcon)
+        } else {
+            assertEquals(expectedContent.copy(alpha = expectedAlpha), actualContent)
+            assertEquals(
+                expectedSecondaryContent.copy(alpha = expectedAlpha),
+                actualSecondaryContent
+            )
+            assertEquals(expectedIcon.copy(alpha = expectedAlpha), actualIcon)
+        }
+
+        if (expectedBackground != Color.Transparent) {
+            rule.onNodeWithTag("test-item").onChildAt(0)
+                .captureToImage()
+                .assertContainsColor(expectedBackground, 50.0f)
+        }
+    }
+}
+
+class ChipFontTest {
+    @get:Rule
+    val rule = createComposeRule()
+
+    @Test
+    fun gives_correct_text_style_base() {
+        var actualTextStyle = TextStyle.Default
+        var expectedTextStyle = TextStyle.Default
+        rule.setContentWithTheme {
+            expectedTextStyle = MaterialTheme.typography.button
+            Chip(
+                onClick = {},
+                colors = ChipDefaults.primaryChipColors(),
+                content = {
+                    actualTextStyle = LocalTextStyle.current
+                },
+                enabled = true,
+                modifier = Modifier.testTag("test-item")
+            )
+        }
+        assertEquals(expectedTextStyle, actualTextStyle)
+    }
+
+    @Test
+    fun gives_correct_text_style_three_slot_chip() {
+        var actualLabelTextStyle = TextStyle.Default
+        var actualSecondaryLabelTextStyle = TextStyle.Default
+        var expectedTextStyle = TextStyle.Default
+        rule.setContentWithTheme {
+            expectedTextStyle = MaterialTheme.typography.button
+            Chip(
+                onClick = {},
+                colors = ChipDefaults.primaryChipColors(),
+                label = {
+                    actualLabelTextStyle = LocalTextStyle.current
+                },
+                secondaryLabel = {
+                    actualSecondaryLabelTextStyle = LocalTextStyle.current
+                },
+                enabled = true,
+                modifier = Modifier.testTag("test-item")
+            )
+        }
+        assertEquals(expectedTextStyle, actualLabelTextStyle)
+        assertEquals(expectedTextStyle, actualSecondaryLabelTextStyle)
+    }
 }
 
 private fun ComposeContentTestRule.verifyHeight(expected: Dp, content: @Composable () -> Unit) {
diff --git a/wear/compose/material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/MaterialTest.kt b/wear/compose/material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/MaterialTest.kt
index d79bd27..5f4fb02 100644
--- a/wear/compose/material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/MaterialTest.kt
+++ b/wear/compose/material/src/androidAndroidTest/kotlin/androidx/wear/compose/material/MaterialTest.kt
@@ -19,16 +19,19 @@
 import android.util.Log
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.sizeIn
 import androidx.compose.material.Surface
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.Add
 import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.ImageBitmap
 import androidx.compose.ui.graphics.asAndroidBitmap
 import androidx.compose.ui.graphics.toPixelMap
+import androidx.compose.ui.layout.ContentScale
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.semantics.SemanticsActions
 import androidx.compose.ui.test.SemanticsNodeInteraction
@@ -110,9 +113,13 @@
 @Composable
 fun CreateImage(iconLabel: String = "TestIcon") {
     val testImage = Icons.Outlined.Add
-    Image(testImage, iconLabel)
+    Image(
+        testImage, iconLabel,
+        modifier = Modifier.fillMaxSize().testTag(iconLabel),
+        contentScale = ContentScale.Fit,
+        alignment = Alignment.Center
+    )
 }
-
 /**
  * assertContainsColor - uses a threshold on an ImageBitmap's color distribution
  * to check that a UI element is predominantly the expected color.
diff --git a/wear/compose/material/src/androidMain/kotlin/androidx/wear/compose/material/Chip.kt b/wear/compose/material/src/androidMain/kotlin/androidx/wear/compose/material/Chip.kt
index f4f85c0..f2b9c62 100644
--- a/wear/compose/material/src/androidMain/kotlin/androidx/wear/compose/material/Chip.kt
+++ b/wear/compose/material/src/androidMain/kotlin/androidx/wear/compose/material/Chip.kt
@@ -18,11 +18,18 @@
 import androidx.compose.foundation.Indication
 import androidx.compose.foundation.LocalIndication
 import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.Interaction
 import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.material.ContentAlpha
 import androidx.compose.material.Surface
 import androidx.compose.runtime.Composable
@@ -32,6 +39,7 @@
 import androidx.compose.runtime.State
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.paint
 import androidx.compose.ui.graphics.Color
@@ -42,8 +50,45 @@
 import androidx.compose.ui.unit.dp
 
 /**
- * The most basic chip that provides a single content slot, used as the building block for other
- * chips.
+ * Base level Wear Material [Chip] that offers a single slot to take any content.
+ *
+ * Is used as the container for more opinionated [Chip] components that take specific content such
+ * as icons and labels.
+ *
+ * The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
+ * of [Typography.button] style. The [Chip] can have an icon or image horizontally
+ * parallel to the two lines of text.
+ *
+ * The [Chip] can have different styles with configurable content colors, background colors
+ * including gradients, these are provided by [ChipColors] implementations.
+ *
+ * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
+ * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default
+ * will have a solid background of [Colors.primary] and content color of
+ * [Colors.onPrimary].
+ *
+ * Chips can be enabled or disabled. A disabled chip will not respond to click events.
+ *
+ * @param onClick Will be called when the user clicks the chip
+ * @param colors [ChipColors] that will be used to resolve the background and content color for
+ * this chip in different states. See [ChipDefaults.chipColors].
+ * @param modifier Modifier to be applied to the chip
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
+ * be clickable
+ * @param onClickLabel Semantic / accessibility label for the [onClick] action
+ * @param contentPadding The spacing values to apply internally between the container and the
+ * content
+ * @param shape Defines the chip's shape. It is strongly recommended to use the default as this
+ * shape is a key characteristic of the Wear Material Theme
+ * @param interactionSource The [MutableInteractionSource] representing the stream of
+ * [Interaction]s for this Chip. You can create and pass in your own remembered
+ * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
+ * appearance / behavior of this Chip in different [Interaction]s.
+ * @param indication Indication to be shown when surface is pressed. By default, indication from
+ * [LocalIndication] will be used. Pass `null` to show no indication, or current value from
+ * [LocalIndication] to show theme default
+ * @param role The type of user interface element. Accessibility services might use this
+ * to describe the element or do customizations
  */
 @Composable
 fun Chip(
@@ -93,6 +138,7 @@
         ) {
             CompositionLocalProvider(
                 LocalContentColor provides colors.contentColor(enabled = enabled).value,
+                LocalTextStyle provides MaterialTheme.typography.button,
                 content = content
             )
         }
@@ -100,6 +146,108 @@
 }
 
 /**
+ * Wear Material [Chip] that offers three slots and a specific layout for an icon, label and
+ * secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with the icon,
+ * if provided, a the start of a row, with a column next containing the two label slots.
+ *
+ * The [Chip] is Stadium shaped and has a max height designed to take no more than two lines of text
+ * of [Typography.button] style. If no secondary label is provided then the label
+ * can be two lines of text. The label and secondary label should be consistently aligned.
+ *
+ * If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that
+ * the text starts next to the icon.
+ *
+ * The [Chip] can have different styles with configurable content colors, background colors
+ * including gradients, these are provided by [ChipColors] implementations.
+ *
+ * The recommended set of [ChipColors] styles can be obtained from [ChipDefaults], e.g.
+ * [ChipDefaults.primaryChipColors] to get a color scheme for a primary [Chip] which by default
+ * will have a solid background of [Colors.primary] and content color of
+ * [Colors.onPrimary].
+ *
+ * Chips can be enabled or disabled. A disabled chip will not respond to click events.
+ *
+ * @param label A slot for providing the chips main label. The contents are expected to be text
+ * which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.
+ * @param onClick Will be called when the user clicks the chip
+ * @param modifier Modifier to be applied to the chip
+ * @param secondaryLabel A slot for providing the chips secondary label. The contents are expected
+ * to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned if
+ * not. label and secondaryLabel contents should be consistently aligned.
+ * @param colors [ChipColors] that will be used to resolve the background and content color for
+ * this chip in different states. See [ChipDefaults.chipColors]. Defaults to
+ * [ChipDefaults.primaryChipColors]
+ * @param enabled Controls the enabled state of the chip. When `false`, this chip will not
+ * be clickable
+ * @param onClickLabel Semantic / accessibility label for the [onClick] action
+ * @param interactionSource The [MutableInteractionSource] representing the stream of
+ * [Interaction]s for this Chip. You can create and pass in your own remembered
+ * [MutableInteractionSource] if you want to observe [Interaction]s and customize the
+ * appearance / behavior of this Chip in different [Interaction]s.
+ * @param indication Indication to be shown when surface is pressed. By default, indication from
+ * [LocalIndication] will be used. Pass `null` to show no indication, or current value from
+ * [LocalIndication] to show theme default
+ * @param contentPadding The spacing values to apply internally between the container and the
+ * content
+ */
+@Composable
+fun Chip(
+    label: @Composable () -> Unit,
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    secondaryLabel: (@Composable () -> Unit)? = null,
+    icon: (@Composable () -> Unit)? = null,
+    colors: ChipColors = ChipDefaults.primaryChipColors(),
+    enabled: Boolean = true,
+    onClickLabel: String? = null,
+    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
+    indication: Indication? = LocalIndication.current,
+    contentPadding: PaddingValues = ChipDefaults.contentPadding(icon != null),
+) {
+    Chip(
+        onClick = onClick,
+        colors = colors,
+        modifier = modifier,
+        enabled = enabled,
+        onClickLabel = onClickLabel,
+        interactionSource = interactionSource,
+        indication = indication,
+        contentPadding = contentPadding
+    ) {
+        Row(
+            verticalAlignment = Alignment.CenterVertically,
+            modifier = Modifier.fillMaxSize()
+        ) {
+            if (icon != null) {
+                Box(
+                    modifier = Modifier.wrapContentSize(align = Alignment.Center)
+                ) {
+                    CompositionLocalProvider(
+                        LocalContentColor provides colors.iconTintColor(enabled).value,
+                        content = icon
+                    )
+                }
+                Spacer(modifier = Modifier.size(ChipDefaults.IconSpacing))
+            }
+            Column {
+                CompositionLocalProvider(
+                    LocalContentColor provides colors.contentColor(enabled).value,
+                    LocalTextStyle provides MaterialTheme.typography.button,
+                    content = label
+                )
+                if (secondaryLabel != null) {
+                    CompositionLocalProvider(
+                        LocalContentColor provides colors.secondaryContentColor(enabled).value,
+                        LocalTextStyle provides MaterialTheme.typography.button,
+                        content = secondaryLabel
+                    )
+                }
+            }
+        }
+    }
+}
+
+/**
  * Represents the background and content colors used in a chip in different states.
  *
  * See [ChipDefaults.primaryChipColors] for the default colors used in a primary styled [Chip].
@@ -107,13 +255,19 @@
  */
 @Stable
 interface ChipColors {
+    /**
+     * Represents the background treatment for this chip, depending on [enabled]. Backgrounds can
+     * be solid, transparent or have a gradient applied.
+     *
+     * @param enabled Whether the chip is enabled
+     */
     @Composable
     fun background(enabled: Boolean): State<Painter>
 
     /**
      * Represents the content color for this chip, depending on [enabled].
      *
-     * @param enabled whether the chip is enabled
+     * @param enabled Whether the chip is enabled
      */
     @Composable
     fun contentColor(enabled: Boolean): State<Color>
@@ -121,13 +275,15 @@
     /**
      * Represents the secondary content color for this chip, depending on [enabled].
      *
-     * @param enabled whether the chip is enabled
+     * @param enabled Whether the chip is enabled
      */
     @Composable
     fun secondaryContentColor(enabled: Boolean): State<Color>
 
     /**
      * Represents the icon tint color for this chip, depending on [enabled].
+     *
+     * @param enabled Whether the chip is enabled
      */
     @Composable
     fun iconTintColor(enabled: Boolean): State<Color>
@@ -138,6 +294,14 @@
  */
 public object ChipDefaults {
 
+    /**
+     * Creates a [ChipColors] that represents the default background and content colors for a
+     * primary [Chip]. Primary chips have a colored background with a contrasting content color. If
+     * a chip is disabled then the color will have an alpha([ContentAlpha.disabled]) value applied.
+     *
+     * @param backgroundColor The background color of this [Chip] when enabled
+     * @param contentColor The content color of this [Chip] when enabled
+     */
     @Composable
     public fun primaryChipColors(
         backgroundColor: Color = MaterialTheme.colors.primary,
@@ -149,6 +313,15 @@
         )
     }
 
+    /**
+     * Creates a [ChipColors] that represents the default background and content colors for a
+     * secondary [Chip]. Secondary chips have a muted background with a contrasting content color.
+     * If a chip is disabled then the color will have an alpha([ContentAlpha.disabled]) value
+     * applied.
+     *
+     * @param backgroundColor The background color of this [Chip] when enabled
+     * @param contentColor The content color of this [Chip] when enabled
+     */
     @Composable
     public fun secondaryChipColors(
         backgroundColor: Color = MaterialTheme.colors.surface,
@@ -161,9 +334,23 @@
     }
 
     private val ChipHorizontalPadding = 16.dp
+    private val ChipWithIconHorizontalPadding = 12.dp
     private val ChipVerticalPadding = 6.dp
 
     /**
+     * Creates a [PaddingValues] for a [Chip] based on whether the chip has a icon. For chips with
+     * icons a smaller start and end padding are applied to compensate for the space that the icon
+     * consumes.
+     *
+     * @param hasIcon Whether the [Chip] has an icon.
+     */
+    public fun contentPadding(
+        hasIcon: Boolean
+    ): PaddingValues {
+        return if (hasIcon) ContentWithIconPadding else ContentPadding
+    }
+
+    /**
      * The default content padding used by [Chip]
      */
     public val ContentPadding = PaddingValues(
@@ -174,6 +361,16 @@
     )
 
     /**
+     * The content padding used by a [Chip] which includes an icon
+     */
+    public val ContentWithIconPadding = PaddingValues(
+        start = ChipWithIconHorizontalPadding,
+        top = ChipVerticalPadding,
+        end = ChipWithIconHorizontalPadding,
+        bottom = ChipVerticalPadding
+    )
+
+    /**
      * The default height applied for the [Chip].
      * Note that you can override it by applying Modifier.heightIn directly on [Chip].
      */
@@ -182,10 +379,21 @@
     /**
      * The default size of the icon when used inside a [Chip].
      */
-    internal val IconSize = 24.dp
+    public val IconSize = 24.dp
 
     /**
-     * The default size of the spacing between an icon and a text when they used inside a [Chip].
+     * The size of the icon when used inside a Large "Avatar" [Chip].
+     */
+    public val LargeIconSize = 32.dp
+
+    /**
+     * The size of the icon when used inside a "Compact" [Chip].
+     */
+    public val SmallIconSize = 20.dp
+
+    /**
+     * The default size of the spacing between an icon and a text when they are used inside a
+     * [Chip].
      */
     internal val IconSpacing = 8.dp
 
@@ -193,14 +401,14 @@
      * Creates a [ChipColors] that represents the default background and content colors used in
      * a [Chip].
      *
-     * @param backgroundColor the background color of this [Chip] when enabled
-     * @param contentColor the content color of this [Chip] when enabled
-     * @param secondaryContentColor the content color of this [Chip] when enabled
-     * @param iconTintColor the content color of this [Chip] when enabled
-     * @param disabledBackgroundColor the background color of this [Chip] when not enabled
-     * @param disabledContentColor the content color of this [Chip] when not enabled
-     * @param disabledSecondaryContentColor the content color of this [Chip] when not enabled
-     * @param disabledIconTintColor the content color of this [Chip] when not enabled
+     * @param backgroundColor The background color of this [Chip] when enabled
+     * @param contentColor The content color of this [Chip] when enabled
+     * @param secondaryContentColor The content color of this [Chip] when enabled
+     * @param iconTintColor The content color of this [Chip] when enabled
+     * @param disabledBackgroundColor The background color of this [Chip] when not enabled
+     * @param disabledContentColor The content color of this [Chip] when not enabled
+     * @param disabledSecondaryContentColor The content color of this [Chip] when not enabled
+     * @param disabledIconTintColor The content color of this [Chip] when not enabled
      */
     @Composable
     fun chipColors(
diff --git a/wear/wear-complications-data/api/restricted_current.txt b/wear/wear-complications-data/api/restricted_current.txt
index 8463171..4b1188f 100644
--- a/wear/wear-complications-data/api/restricted_current.txt
+++ b/wear/wear-complications-data/api/restricted_current.txt
@@ -165,7 +165,7 @@
     property public final java.util.Map<androidx.wear.complications.data.ComplicationType,android.graphics.RectF> perComplicationTypeBounds;
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class ComplicationHelperActivity extends android.app.Activity implements androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback {
+  @RequiresApi(android.os.Build.VERSION_CODES.N) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class ComplicationHelperActivity extends android.app.Activity implements androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback {
     ctor public ComplicationHelperActivity();
     method public static android.content.Intent createPermissionRequestHelperIntent(android.content.Context, android.content.ComponentName);
     method public static android.content.Intent createProviderChooserHelperIntent(android.content.Context, android.content.ComponentName, int, java.util.Collection<androidx.wear.complications.data.ComplicationType!>, String?);
diff --git a/wear/wear-complications-data/src/main/java/androidx/wear/complications/ComplicationHelperActivity.java b/wear/wear-complications-data/src/main/java/androidx/wear/complications/ComplicationHelperActivity.java
index de5f491..10b577e 100644
--- a/wear/wear-complications-data/src/main/java/androidx/wear/complications/ComplicationHelperActivity.java
+++ b/wear/wear-complications-data/src/main/java/androidx/wear/complications/ComplicationHelperActivity.java
@@ -16,7 +16,6 @@
 
 package androidx.wear.complications;
 
-import android.annotation.TargetApi;
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -30,6 +29,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 import androidx.core.app.ActivityCompat;
 import androidx.wear.complications.data.ComplicationType;
@@ -57,7 +57,7 @@
  *
  * @hide
  */
-@TargetApi(Build.VERSION_CODES.N)
+@RequiresApi(Build.VERSION_CODES.N)
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 @SuppressWarnings("ForbiddenSuperClass")
 public final class ComplicationHelperActivity extends Activity
diff --git a/wear/wear-watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt b/wear/wear-watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
index 0d88448..7c8eb54 100644
--- a/wear/wear-watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
+++ b/wear/wear-watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
@@ -92,7 +92,12 @@
                     deferredService.completeExceptionally(ServiceStartFailureException())
                 }
             }
-            if (!context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)) {
+            if (!context.bindService(
+                    intent,
+                    serviceConnection,
+                    Context.BIND_AUTO_CREATE or Context.BIND_IMPORTANT
+                )
+            ) {
                 throw ServiceNotBoundException()
             }
             return WatchFaceControlClientImpl(
diff --git a/wear/wear-watchface-complications-rendering/api/current.txt b/wear/wear-watchface-complications-rendering/api/current.txt
index dad6070..cea9495 100644
--- a/wear/wear-watchface-complications-rendering/api/current.txt
+++ b/wear/wear-watchface-complications-rendering/api/current.txt
@@ -13,8 +13,6 @@
     method public void setHighlighted(boolean value);
     property public final androidx.wear.watchface.complications.rendering.ComplicationDrawable drawable;
     property public boolean isHighlighted;
-    field public static final float EXPANSION_DP = 6.0f;
-    field public static final float STROKE_WIDTH_DP = 3.0f;
   }
 
   public final class ComplicationDrawable extends android.graphics.drawable.Drawable {
diff --git a/wear/wear-watchface-complications-rendering/api/public_plus_experimental_current.txt b/wear/wear-watchface-complications-rendering/api/public_plus_experimental_current.txt
index dad6070..cea9495 100644
--- a/wear/wear-watchface-complications-rendering/api/public_plus_experimental_current.txt
+++ b/wear/wear-watchface-complications-rendering/api/public_plus_experimental_current.txt
@@ -13,8 +13,6 @@
     method public void setHighlighted(boolean value);
     property public final androidx.wear.watchface.complications.rendering.ComplicationDrawable drawable;
     property public boolean isHighlighted;
-    field public static final float EXPANSION_DP = 6.0f;
-    field public static final float STROKE_WIDTH_DP = 3.0f;
   }
 
   public final class ComplicationDrawable extends android.graphics.drawable.Drawable {
diff --git a/wear/wear-watchface-complications-rendering/api/restricted_current.txt b/wear/wear-watchface-complications-rendering/api/restricted_current.txt
index 3710976..e15553d 100644
--- a/wear/wear-watchface-complications-rendering/api/restricted_current.txt
+++ b/wear/wear-watchface-complications-rendering/api/restricted_current.txt
@@ -13,8 +13,6 @@
     method public void setHighlighted(boolean value);
     property public final androidx.wear.watchface.complications.rendering.ComplicationDrawable drawable;
     property public boolean isHighlighted;
-    field public static final float EXPANSION_DP = 6.0f;
-    field public static final float STROKE_WIDTH_DP = 3.0f;
   }
 
   public final class ComplicationDrawable extends android.graphics.drawable.Drawable {
diff --git a/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/CanvasComplicationDrawable.kt b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/CanvasComplicationDrawable.kt
index c59f06e..3dde0c8 100644
--- a/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/CanvasComplicationDrawable.kt
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/CanvasComplicationDrawable.kt
@@ -53,8 +53,8 @@
 ) : CanvasComplication {
 
     private companion object {
-        const val EXPANSION_DP = 6.0f
-        const val STROKE_WIDTH_DP = 3.0f
+        internal const val EXPANSION_DP = 6.0f
+        internal const val STROKE_WIDTH_DP = 3.0f
     }
 
     private val complicationHighlightRenderer by lazy {
diff --git a/wear/wear-watchface-data/api/restricted_current.txt b/wear/wear-watchface-data/api/restricted_current.txt
index 9090fcf..dc55cb7 100644
--- a/wear/wear-watchface-data/api/restricted_current.txt
+++ b/wear/wear-watchface-data/api/restricted_current.txt
@@ -106,7 +106,7 @@
     method public static android.support.wearable.complications.ComplicationText makeTimeAsComplicationText(android.content.Context);
   }
 
-  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class ContentDescriptionLabel implements android.os.Parcelable {
+  @RequiresApi(android.os.Build.VERSION_CODES.KITKAT) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final class ContentDescriptionLabel implements android.os.Parcelable {
     ctor public ContentDescriptionLabel(android.graphics.Rect, android.support.wearable.complications.ComplicationTextTemplate);
     ctor public ContentDescriptionLabel(android.graphics.Rect, android.support.wearable.complications.ComplicationText);
     ctor public ContentDescriptionLabel(android.content.Context, android.graphics.Rect, android.support.wearable.complications.ComplicationData);
diff --git a/wear/wear-watchface-data/src/main/java/android/support/wearable/watchface/accessibility/ContentDescriptionLabel.java b/wear/wear-watchface-data/src/main/java/android/support/wearable/watchface/accessibility/ContentDescriptionLabel.java
index fbc0738..ddb401f 100644
--- a/wear/wear-watchface-data/src/main/java/android/support/wearable/watchface/accessibility/ContentDescriptionLabel.java
+++ b/wear/wear-watchface-data/src/main/java/android/support/wearable/watchface/accessibility/ContentDescriptionLabel.java
@@ -16,7 +16,6 @@
 
 package android.support.wearable.watchface.accessibility;
 
-import android.annotation.TargetApi;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.graphics.Rect;
@@ -32,6 +31,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 
 import org.jetbrains.annotations.NotNull;
@@ -43,7 +43,7 @@
  * @hide
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-@TargetApi(VERSION_CODES.KITKAT)
+@RequiresApi(VERSION_CODES.KITKAT)
 @SuppressWarnings("BanParcelableUsage")
 public final class ContentDescriptionLabel implements Parcelable {
 
diff --git a/window/window/src/main/java/androidx/window/DisplayFeature.kt b/window/window/src/main/java/androidx/window/DisplayFeature.kt
index 5d3207c..72ed2c9 100644
--- a/window/window/src/main/java/androidx/window/DisplayFeature.kt
+++ b/window/window/src/main/java/androidx/window/DisplayFeature.kt
@@ -26,7 +26,7 @@
  * visual or touch discontinuity, make some area invisible or create a logical divider or
  * separation in the screen space.
  *
- * @see FoldingFeature that represents a screen fold that intersects the application window.
+ * @see FoldingFeature Represents a screen fold that intersects the application window.
  */
 public interface DisplayFeature {
     /**
diff --git a/window/window/src/main/java/androidx/window/WindowBackend.kt b/window/window/src/main/java/androidx/window/WindowBackend.kt
index 29bc71f..6f6e351 100644
--- a/window/window/src/main/java/androidx/window/WindowBackend.kt
+++ b/window/window/src/main/java/androidx/window/WindowBackend.kt
@@ -20,9 +20,8 @@
 import java.util.concurrent.Executor
 
 /**
- * Backing interface for {@link androidx.window.WindowManager} instances that server as the default
- * information
- * supplier.
+ * Backing interface for [WindowManager] instances that serve as the default
+ * information supplier.
  */
 public interface WindowBackend {
     /**
diff --git a/window/window/src/main/java/androidx/window/WindowInfoRepo.kt b/window/window/src/main/java/androidx/window/WindowInfoRepo.kt
index 32ea8e3..053bdb3 100644
--- a/window/window/src/main/java/androidx/window/WindowInfoRepo.kt
+++ b/window/window/src/main/java/androidx/window/WindowInfoRepo.kt
@@ -61,8 +61,8 @@
      * areas of the display are not available to windows created for the associated [Context].
      * For example, devices with foldable displays that wrap around the enclosure may split the
      * physical display into different regions, one for the front and one for the back, each acting
-     * as different logical displays. In this case [.getMaximumWindowMetrics] would return
-     * the region describing the side of the device the associated [context&#39;s][Context]
+     * as different logical displays. In this case [getMaximumWindowMetrics] would return
+     * the region describing the side of the device the associated [context's][Context]
      * window is placed.
      *
      * @see currentWindowMetrics
diff --git a/work/workmanager-gcm/api/2.6.0-beta01.txt b/work/workmanager-gcm/api/2.6.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/work/workmanager-gcm/api/2.6.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/work/workmanager-gcm/api/public_plus_experimental_2.6.0-beta01.txt b/work/workmanager-gcm/api/public_plus_experimental_2.6.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/work/workmanager-gcm/api/public_plus_experimental_2.6.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/work/workmanager-gcm/api/res-2.6.0-beta01.txt b/work/workmanager-gcm/api/res-2.6.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/workmanager-gcm/api/res-2.6.0-beta01.txt
diff --git a/work/workmanager-gcm/api/restricted_2.6.0-beta01.txt b/work/workmanager-gcm/api/restricted_2.6.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/work/workmanager-gcm/api/restricted_2.6.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/work/workmanager-ktx/api/2.6.0-beta01.txt b/work/workmanager-ktx/api/2.6.0-beta01.txt
new file mode 100644
index 0000000..2c5f419
--- /dev/null
+++ b/work/workmanager-ktx/api/2.6.0-beta01.txt
@@ -0,0 +1,40 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public abstract class CoroutineWorker extends androidx.work.ListenableWorker {
+    ctor public CoroutineWorker(android.content.Context appContext, androidx.work.WorkerParameters params);
+    method public abstract suspend Object? doWork(kotlin.coroutines.Continuation<? super androidx.work.ListenableWorker.Result> p);
+    method @Deprecated public kotlinx.coroutines.CoroutineDispatcher getCoroutineContext();
+    method public final void onStopped();
+    method public final suspend Object? setForeground(androidx.work.ForegroundInfo foregroundInfo, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public final suspend Object? setProgress(androidx.work.Data data, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result> startWork();
+    property @Deprecated public kotlinx.coroutines.CoroutineDispatcher coroutineContext;
+  }
+
+  public final class DataKt {
+    method public static inline <reified T> boolean hasKeyWithValueOfType(androidx.work.Data, String key);
+    method public static inline androidx.work.Data workDataOf(kotlin.Pair<java.lang.String,?>... pairs);
+  }
+
+  public final class ListenableFutureKt {
+  }
+
+  public final class OneTimeWorkRequestKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder! OneTimeWorkRequestBuilder();
+    method public static inline androidx.work.OneTimeWorkRequest.Builder setInputMerger(androidx.work.OneTimeWorkRequest.Builder, kotlin.reflect.KClass<? extends androidx.work.InputMerger> inputMerger);
+  }
+
+  public final class OperationKt {
+    method public static suspend inline Object? await(androidx.work.Operation, kotlin.coroutines.Continuation<? super androidx.work.Operation.State.SUCCESS> p);
+  }
+
+  public final class PeriodicWorkRequestKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit);
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(java.time.Duration repeatInterval);
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit, long flexTimeInterval, java.util.concurrent.TimeUnit flexTimeIntervalUnit);
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(java.time.Duration repeatInterval, java.time.Duration flexTimeInterval);
+  }
+
+}
+
diff --git a/work/workmanager-ktx/api/public_plus_experimental_2.6.0-beta01.txt b/work/workmanager-ktx/api/public_plus_experimental_2.6.0-beta01.txt
new file mode 100644
index 0000000..2c5f419
--- /dev/null
+++ b/work/workmanager-ktx/api/public_plus_experimental_2.6.0-beta01.txt
@@ -0,0 +1,40 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public abstract class CoroutineWorker extends androidx.work.ListenableWorker {
+    ctor public CoroutineWorker(android.content.Context appContext, androidx.work.WorkerParameters params);
+    method public abstract suspend Object? doWork(kotlin.coroutines.Continuation<? super androidx.work.ListenableWorker.Result> p);
+    method @Deprecated public kotlinx.coroutines.CoroutineDispatcher getCoroutineContext();
+    method public final void onStopped();
+    method public final suspend Object? setForeground(androidx.work.ForegroundInfo foregroundInfo, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public final suspend Object? setProgress(androidx.work.Data data, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result> startWork();
+    property @Deprecated public kotlinx.coroutines.CoroutineDispatcher coroutineContext;
+  }
+
+  public final class DataKt {
+    method public static inline <reified T> boolean hasKeyWithValueOfType(androidx.work.Data, String key);
+    method public static inline androidx.work.Data workDataOf(kotlin.Pair<java.lang.String,?>... pairs);
+  }
+
+  public final class ListenableFutureKt {
+  }
+
+  public final class OneTimeWorkRequestKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder! OneTimeWorkRequestBuilder();
+    method public static inline androidx.work.OneTimeWorkRequest.Builder setInputMerger(androidx.work.OneTimeWorkRequest.Builder, kotlin.reflect.KClass<? extends androidx.work.InputMerger> inputMerger);
+  }
+
+  public final class OperationKt {
+    method public static suspend inline Object? await(androidx.work.Operation, kotlin.coroutines.Continuation<? super androidx.work.Operation.State.SUCCESS> p);
+  }
+
+  public final class PeriodicWorkRequestKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit);
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(java.time.Duration repeatInterval);
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit, long flexTimeInterval, java.util.concurrent.TimeUnit flexTimeIntervalUnit);
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(java.time.Duration repeatInterval, java.time.Duration flexTimeInterval);
+  }
+
+}
+
diff --git a/work/workmanager-ktx/api/res-2.6.0-beta01.txt b/work/workmanager-ktx/api/res-2.6.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/workmanager-ktx/api/res-2.6.0-beta01.txt
diff --git a/work/workmanager-ktx/api/restricted_2.6.0-beta01.txt b/work/workmanager-ktx/api/restricted_2.6.0-beta01.txt
new file mode 100644
index 0000000..2c5f419
--- /dev/null
+++ b/work/workmanager-ktx/api/restricted_2.6.0-beta01.txt
@@ -0,0 +1,40 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public abstract class CoroutineWorker extends androidx.work.ListenableWorker {
+    ctor public CoroutineWorker(android.content.Context appContext, androidx.work.WorkerParameters params);
+    method public abstract suspend Object? doWork(kotlin.coroutines.Continuation<? super androidx.work.ListenableWorker.Result> p);
+    method @Deprecated public kotlinx.coroutines.CoroutineDispatcher getCoroutineContext();
+    method public final void onStopped();
+    method public final suspend Object? setForeground(androidx.work.ForegroundInfo foregroundInfo, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public final suspend Object? setProgress(androidx.work.Data data, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result> startWork();
+    property @Deprecated public kotlinx.coroutines.CoroutineDispatcher coroutineContext;
+  }
+
+  public final class DataKt {
+    method public static inline <reified T> boolean hasKeyWithValueOfType(androidx.work.Data, String key);
+    method public static inline androidx.work.Data workDataOf(kotlin.Pair<java.lang.String,?>... pairs);
+  }
+
+  public final class ListenableFutureKt {
+  }
+
+  public final class OneTimeWorkRequestKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder! OneTimeWorkRequestBuilder();
+    method public static inline androidx.work.OneTimeWorkRequest.Builder setInputMerger(androidx.work.OneTimeWorkRequest.Builder, kotlin.reflect.KClass<? extends androidx.work.InputMerger> inputMerger);
+  }
+
+  public final class OperationKt {
+    method public static suspend inline Object? await(androidx.work.Operation, kotlin.coroutines.Continuation<? super androidx.work.Operation.State.SUCCESS> p);
+  }
+
+  public final class PeriodicWorkRequestKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit);
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(java.time.Duration repeatInterval);
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit, long flexTimeInterval, java.util.concurrent.TimeUnit flexTimeIntervalUnit);
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(java.time.Duration repeatInterval, java.time.Duration flexTimeInterval);
+  }
+
+}
+
diff --git a/work/workmanager-lint/build.gradle b/work/workmanager-lint/build.gradle
index 557fb01..7329d99 100644
--- a/work/workmanager-lint/build.gradle
+++ b/work/workmanager-lint/build.gradle
@@ -25,13 +25,7 @@
 }
 
 dependencies {
-    // compileOnly because we use lintChecks and it doesn't allow other types of deps
-    // this ugly hack exists because of b/63873667
-    if (rootProject.hasProperty("android.injected.invoked.from.ide")) {
-        compileOnly(libs.androidLintApi)
-    } else {
-        compileOnly(LINT_API_MIN)
-    }
+    compileOnly(LINT_API_MIN)
     compileOnly(libs.kotlinStdlib)
 
     testImplementation(libs.kotlinStdlib)
diff --git a/work/workmanager-multiprocess/api/2.6.0-beta01.txt b/work/workmanager-multiprocess/api/2.6.0-beta01.txt
new file mode 100644
index 0000000..e033a49
--- /dev/null
+++ b/work/workmanager-multiprocess/api/2.6.0-beta01.txt
@@ -0,0 +1,26 @@
+// Signature format: 4.0
+package androidx.work.multiprocess {
+
+  public abstract class RemoteCoroutineWorker extends androidx.work.multiprocess.RemoteListenableWorker {
+    ctor public RemoteCoroutineWorker(android.content.Context context, androidx.work.WorkerParameters parameters);
+    method public abstract suspend Object? doRemoteWork(kotlin.coroutines.Continuation<? super androidx.work.ListenableWorker.Result> p);
+    method public final void onStopped();
+    method public final suspend Object? setProgress(androidx.work.Data data, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result> startRemoteWork();
+  }
+
+  public abstract class RemoteListenableWorker extends androidx.work.ListenableWorker {
+    ctor public RemoteListenableWorker(android.content.Context, androidx.work.WorkerParameters);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startRemoteWork();
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+    field public static final String ARGUMENT_CLASS_NAME = "androidx.work.impl.workers.RemoteListenableWorker.ARGUMENT_CLASS_NAME";
+    field public static final String ARGUMENT_PACKAGE_NAME = "androidx.work.impl.workers.RemoteListenableWorker.ARGUMENT_PACKAGE_NAME";
+  }
+
+  public class RemoteWorkerService extends android.app.Service {
+    ctor public RemoteWorkerService();
+    method public android.os.IBinder? onBind(android.content.Intent);
+  }
+
+}
+
diff --git a/work/workmanager-multiprocess/api/public_plus_experimental_2.6.0-beta01.txt b/work/workmanager-multiprocess/api/public_plus_experimental_2.6.0-beta01.txt
new file mode 100644
index 0000000..e033a49
--- /dev/null
+++ b/work/workmanager-multiprocess/api/public_plus_experimental_2.6.0-beta01.txt
@@ -0,0 +1,26 @@
+// Signature format: 4.0
+package androidx.work.multiprocess {
+
+  public abstract class RemoteCoroutineWorker extends androidx.work.multiprocess.RemoteListenableWorker {
+    ctor public RemoteCoroutineWorker(android.content.Context context, androidx.work.WorkerParameters parameters);
+    method public abstract suspend Object? doRemoteWork(kotlin.coroutines.Continuation<? super androidx.work.ListenableWorker.Result> p);
+    method public final void onStopped();
+    method public final suspend Object? setProgress(androidx.work.Data data, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result> startRemoteWork();
+  }
+
+  public abstract class RemoteListenableWorker extends androidx.work.ListenableWorker {
+    ctor public RemoteListenableWorker(android.content.Context, androidx.work.WorkerParameters);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startRemoteWork();
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+    field public static final String ARGUMENT_CLASS_NAME = "androidx.work.impl.workers.RemoteListenableWorker.ARGUMENT_CLASS_NAME";
+    field public static final String ARGUMENT_PACKAGE_NAME = "androidx.work.impl.workers.RemoteListenableWorker.ARGUMENT_PACKAGE_NAME";
+  }
+
+  public class RemoteWorkerService extends android.app.Service {
+    ctor public RemoteWorkerService();
+    method public android.os.IBinder? onBind(android.content.Intent);
+  }
+
+}
+
diff --git a/work/workmanager-multiprocess/api/res-2.6.0-beta01.txt b/work/workmanager-multiprocess/api/res-2.6.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/workmanager-multiprocess/api/res-2.6.0-beta01.txt
diff --git a/work/workmanager-multiprocess/api/restricted_2.6.0-beta01.txt b/work/workmanager-multiprocess/api/restricted_2.6.0-beta01.txt
new file mode 100644
index 0000000..e033a49
--- /dev/null
+++ b/work/workmanager-multiprocess/api/restricted_2.6.0-beta01.txt
@@ -0,0 +1,26 @@
+// Signature format: 4.0
+package androidx.work.multiprocess {
+
+  public abstract class RemoteCoroutineWorker extends androidx.work.multiprocess.RemoteListenableWorker {
+    ctor public RemoteCoroutineWorker(android.content.Context context, androidx.work.WorkerParameters parameters);
+    method public abstract suspend Object? doRemoteWork(kotlin.coroutines.Continuation<? super androidx.work.ListenableWorker.Result> p);
+    method public final void onStopped();
+    method public final suspend Object? setProgress(androidx.work.Data data, kotlin.coroutines.Continuation<? super kotlin.Unit> p);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result> startRemoteWork();
+  }
+
+  public abstract class RemoteListenableWorker extends androidx.work.ListenableWorker {
+    ctor public RemoteListenableWorker(android.content.Context, androidx.work.WorkerParameters);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startRemoteWork();
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+    field public static final String ARGUMENT_CLASS_NAME = "androidx.work.impl.workers.RemoteListenableWorker.ARGUMENT_CLASS_NAME";
+    field public static final String ARGUMENT_PACKAGE_NAME = "androidx.work.impl.workers.RemoteListenableWorker.ARGUMENT_PACKAGE_NAME";
+  }
+
+  public class RemoteWorkerService extends android.app.Service {
+    ctor public RemoteWorkerService();
+    method public android.os.IBinder? onBind(android.content.Intent);
+  }
+
+}
+
diff --git a/work/workmanager-rxjava2/api/2.6.0-beta01.txt b/work/workmanager-rxjava2/api/2.6.0-beta01.txt
new file mode 100644
index 0000000..2d667ee
--- /dev/null
+++ b/work/workmanager-rxjava2/api/2.6.0-beta01.txt
@@ -0,0 +1,14 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public abstract class RxWorker extends androidx.work.ListenableWorker {
+    ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
+    method @MainThread public abstract io.reactivex.Single<androidx.work.ListenableWorker.Result!> createWork();
+    method protected io.reactivex.Scheduler getBackgroundScheduler();
+    method public final io.reactivex.Completable setCompletableProgress(androidx.work.Data);
+    method @Deprecated public final io.reactivex.Single<java.lang.Void!> setProgress(androidx.work.Data);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+}
+
diff --git a/work/workmanager-rxjava2/api/public_plus_experimental_2.6.0-beta01.txt b/work/workmanager-rxjava2/api/public_plus_experimental_2.6.0-beta01.txt
new file mode 100644
index 0000000..2d667ee
--- /dev/null
+++ b/work/workmanager-rxjava2/api/public_plus_experimental_2.6.0-beta01.txt
@@ -0,0 +1,14 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public abstract class RxWorker extends androidx.work.ListenableWorker {
+    ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
+    method @MainThread public abstract io.reactivex.Single<androidx.work.ListenableWorker.Result!> createWork();
+    method protected io.reactivex.Scheduler getBackgroundScheduler();
+    method public final io.reactivex.Completable setCompletableProgress(androidx.work.Data);
+    method @Deprecated public final io.reactivex.Single<java.lang.Void!> setProgress(androidx.work.Data);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+}
+
diff --git a/work/workmanager-rxjava2/api/res-2.6.0-beta01.txt b/work/workmanager-rxjava2/api/res-2.6.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/workmanager-rxjava2/api/res-2.6.0-beta01.txt
diff --git a/work/workmanager-rxjava2/api/restricted_2.6.0-beta01.txt b/work/workmanager-rxjava2/api/restricted_2.6.0-beta01.txt
new file mode 100644
index 0000000..2d667ee
--- /dev/null
+++ b/work/workmanager-rxjava2/api/restricted_2.6.0-beta01.txt
@@ -0,0 +1,14 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public abstract class RxWorker extends androidx.work.ListenableWorker {
+    ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
+    method @MainThread public abstract io.reactivex.Single<androidx.work.ListenableWorker.Result!> createWork();
+    method protected io.reactivex.Scheduler getBackgroundScheduler();
+    method public final io.reactivex.Completable setCompletableProgress(androidx.work.Data);
+    method @Deprecated public final io.reactivex.Single<java.lang.Void!> setProgress(androidx.work.Data);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+}
+
diff --git a/work/workmanager-rxjava3/api/2.6.0-beta01.txt b/work/workmanager-rxjava3/api/2.6.0-beta01.txt
new file mode 100644
index 0000000..9293340
--- /dev/null
+++ b/work/workmanager-rxjava3/api/2.6.0-beta01.txt
@@ -0,0 +1,13 @@
+// Signature format: 4.0
+package androidx.work.rxjava3 {
+
+  public abstract class RxWorker extends androidx.work.ListenableWorker {
+    ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
+    method @MainThread public abstract io.reactivex.rxjava3.core.Single<androidx.work.ListenableWorker.Result!> createWork();
+    method protected io.reactivex.rxjava3.core.Scheduler getBackgroundScheduler();
+    method public final io.reactivex.rxjava3.core.Completable setCompletableProgress(androidx.work.Data);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+}
+
diff --git a/work/workmanager-rxjava3/api/public_plus_experimental_2.6.0-beta01.txt b/work/workmanager-rxjava3/api/public_plus_experimental_2.6.0-beta01.txt
new file mode 100644
index 0000000..9293340
--- /dev/null
+++ b/work/workmanager-rxjava3/api/public_plus_experimental_2.6.0-beta01.txt
@@ -0,0 +1,13 @@
+// Signature format: 4.0
+package androidx.work.rxjava3 {
+
+  public abstract class RxWorker extends androidx.work.ListenableWorker {
+    ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
+    method @MainThread public abstract io.reactivex.rxjava3.core.Single<androidx.work.ListenableWorker.Result!> createWork();
+    method protected io.reactivex.rxjava3.core.Scheduler getBackgroundScheduler();
+    method public final io.reactivex.rxjava3.core.Completable setCompletableProgress(androidx.work.Data);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+}
+
diff --git a/work/workmanager-rxjava3/api/res-2.6.0-beta01.txt b/work/workmanager-rxjava3/api/res-2.6.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/workmanager-rxjava3/api/res-2.6.0-beta01.txt
diff --git a/work/workmanager-rxjava3/api/restricted_2.6.0-beta01.txt b/work/workmanager-rxjava3/api/restricted_2.6.0-beta01.txt
new file mode 100644
index 0000000..9293340
--- /dev/null
+++ b/work/workmanager-rxjava3/api/restricted_2.6.0-beta01.txt
@@ -0,0 +1,13 @@
+// Signature format: 4.0
+package androidx.work.rxjava3 {
+
+  public abstract class RxWorker extends androidx.work.ListenableWorker {
+    ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
+    method @MainThread public abstract io.reactivex.rxjava3.core.Single<androidx.work.ListenableWorker.Result!> createWork();
+    method protected io.reactivex.rxjava3.core.Scheduler getBackgroundScheduler();
+    method public final io.reactivex.rxjava3.core.Completable setCompletableProgress(androidx.work.Data);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+}
+
diff --git a/work/workmanager-testing/api/2.6.0-beta01.txt b/work/workmanager-testing/api/2.6.0-beta01.txt
new file mode 100644
index 0000000..f3f3fe2
--- /dev/null
+++ b/work/workmanager-testing/api/2.6.0-beta01.txt
@@ -0,0 +1,52 @@
+// Signature format: 4.0
+package androidx.work.testing {
+
+  public class SynchronousExecutor implements java.util.concurrent.Executor {
+    ctor public SynchronousExecutor();
+    method public void execute(Runnable);
+  }
+
+  public interface TestDriver {
+    method public void setAllConstraintsMet(java.util.UUID);
+    method public void setInitialDelayMet(java.util.UUID);
+    method public void setPeriodDelayMet(java.util.UUID);
+  }
+
+  public class TestListenableWorkerBuilder<W extends androidx.work.ListenableWorker> {
+    method public W build();
+    method public static androidx.work.testing.TestListenableWorkerBuilder<? extends androidx.work.ListenableWorker> from(android.content.Context, androidx.work.WorkRequest);
+    method public static <W extends androidx.work.ListenableWorker> androidx.work.testing.TestListenableWorkerBuilder<W!> from(android.content.Context, Class<W!>);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setForegroundUpdater(androidx.work.ForegroundUpdater);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setId(java.util.UUID);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setInputData(androidx.work.Data);
+    method @RequiresApi(28) public androidx.work.testing.TestListenableWorkerBuilder<W!> setNetwork(android.net.Network);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setProgressUpdater(androidx.work.ProgressUpdater);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setRunAttemptCount(int);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setTags(java.util.List<java.lang.String!>);
+    method @RequiresApi(24) public androidx.work.testing.TestListenableWorkerBuilder<W!> setTriggeredContentAuthorities(java.util.List<java.lang.String!>);
+    method @RequiresApi(24) public androidx.work.testing.TestListenableWorkerBuilder<W!> setTriggeredContentUris(java.util.List<android.net.Uri!>);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setWorkerFactory(androidx.work.WorkerFactory);
+  }
+
+  public final class TestListenableWorkerBuilderKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.testing.TestListenableWorkerBuilder<W>! TestListenableWorkerBuilder(android.content.Context context, optional androidx.work.Data inputData, optional java.util.List<? extends java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<? extends java.lang.String> triggeredContentAuthorities);
+  }
+
+  public class TestWorkerBuilder<W extends androidx.work.Worker> extends androidx.work.testing.TestListenableWorkerBuilder<W> {
+    method public static androidx.work.testing.TestWorkerBuilder<? extends androidx.work.Worker> from(android.content.Context, androidx.work.WorkRequest, java.util.concurrent.Executor);
+    method public static <W extends androidx.work.Worker> androidx.work.testing.TestWorkerBuilder<W!> from(android.content.Context, Class<W!>, java.util.concurrent.Executor);
+  }
+
+  public final class TestWorkerBuilderKt {
+    method public static inline <reified W extends androidx.work.Worker> androidx.work.testing.TestWorkerBuilder<W>! TestWorkerBuilder(android.content.Context context, java.util.concurrent.Executor executor, optional androidx.work.Data inputData, optional java.util.List<? extends java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<? extends java.lang.String> triggeredContentAuthorities);
+  }
+
+  public final class WorkManagerTestInitHelper {
+    method @Deprecated public static androidx.work.testing.TestDriver? getTestDriver();
+    method public static androidx.work.testing.TestDriver? getTestDriver(android.content.Context);
+    method public static void initializeTestWorkManager(android.content.Context);
+    method public static void initializeTestWorkManager(android.content.Context, androidx.work.Configuration);
+  }
+
+}
+
diff --git a/work/workmanager-testing/api/public_plus_experimental_2.6.0-beta01.txt b/work/workmanager-testing/api/public_plus_experimental_2.6.0-beta01.txt
new file mode 100644
index 0000000..f3f3fe2
--- /dev/null
+++ b/work/workmanager-testing/api/public_plus_experimental_2.6.0-beta01.txt
@@ -0,0 +1,52 @@
+// Signature format: 4.0
+package androidx.work.testing {
+
+  public class SynchronousExecutor implements java.util.concurrent.Executor {
+    ctor public SynchronousExecutor();
+    method public void execute(Runnable);
+  }
+
+  public interface TestDriver {
+    method public void setAllConstraintsMet(java.util.UUID);
+    method public void setInitialDelayMet(java.util.UUID);
+    method public void setPeriodDelayMet(java.util.UUID);
+  }
+
+  public class TestListenableWorkerBuilder<W extends androidx.work.ListenableWorker> {
+    method public W build();
+    method public static androidx.work.testing.TestListenableWorkerBuilder<? extends androidx.work.ListenableWorker> from(android.content.Context, androidx.work.WorkRequest);
+    method public static <W extends androidx.work.ListenableWorker> androidx.work.testing.TestListenableWorkerBuilder<W!> from(android.content.Context, Class<W!>);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setForegroundUpdater(androidx.work.ForegroundUpdater);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setId(java.util.UUID);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setInputData(androidx.work.Data);
+    method @RequiresApi(28) public androidx.work.testing.TestListenableWorkerBuilder<W!> setNetwork(android.net.Network);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setProgressUpdater(androidx.work.ProgressUpdater);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setRunAttemptCount(int);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setTags(java.util.List<java.lang.String!>);
+    method @RequiresApi(24) public androidx.work.testing.TestListenableWorkerBuilder<W!> setTriggeredContentAuthorities(java.util.List<java.lang.String!>);
+    method @RequiresApi(24) public androidx.work.testing.TestListenableWorkerBuilder<W!> setTriggeredContentUris(java.util.List<android.net.Uri!>);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setWorkerFactory(androidx.work.WorkerFactory);
+  }
+
+  public final class TestListenableWorkerBuilderKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.testing.TestListenableWorkerBuilder<W>! TestListenableWorkerBuilder(android.content.Context context, optional androidx.work.Data inputData, optional java.util.List<? extends java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<? extends java.lang.String> triggeredContentAuthorities);
+  }
+
+  public class TestWorkerBuilder<W extends androidx.work.Worker> extends androidx.work.testing.TestListenableWorkerBuilder<W> {
+    method public static androidx.work.testing.TestWorkerBuilder<? extends androidx.work.Worker> from(android.content.Context, androidx.work.WorkRequest, java.util.concurrent.Executor);
+    method public static <W extends androidx.work.Worker> androidx.work.testing.TestWorkerBuilder<W!> from(android.content.Context, Class<W!>, java.util.concurrent.Executor);
+  }
+
+  public final class TestWorkerBuilderKt {
+    method public static inline <reified W extends androidx.work.Worker> androidx.work.testing.TestWorkerBuilder<W>! TestWorkerBuilder(android.content.Context context, java.util.concurrent.Executor executor, optional androidx.work.Data inputData, optional java.util.List<? extends java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<? extends java.lang.String> triggeredContentAuthorities);
+  }
+
+  public final class WorkManagerTestInitHelper {
+    method @Deprecated public static androidx.work.testing.TestDriver? getTestDriver();
+    method public static androidx.work.testing.TestDriver? getTestDriver(android.content.Context);
+    method public static void initializeTestWorkManager(android.content.Context);
+    method public static void initializeTestWorkManager(android.content.Context, androidx.work.Configuration);
+  }
+
+}
+
diff --git a/work/workmanager-testing/api/res-2.6.0-beta01.txt b/work/workmanager-testing/api/res-2.6.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/workmanager-testing/api/res-2.6.0-beta01.txt
diff --git a/work/workmanager-testing/api/restricted_2.6.0-beta01.txt b/work/workmanager-testing/api/restricted_2.6.0-beta01.txt
new file mode 100644
index 0000000..f3f3fe2
--- /dev/null
+++ b/work/workmanager-testing/api/restricted_2.6.0-beta01.txt
@@ -0,0 +1,52 @@
+// Signature format: 4.0
+package androidx.work.testing {
+
+  public class SynchronousExecutor implements java.util.concurrent.Executor {
+    ctor public SynchronousExecutor();
+    method public void execute(Runnable);
+  }
+
+  public interface TestDriver {
+    method public void setAllConstraintsMet(java.util.UUID);
+    method public void setInitialDelayMet(java.util.UUID);
+    method public void setPeriodDelayMet(java.util.UUID);
+  }
+
+  public class TestListenableWorkerBuilder<W extends androidx.work.ListenableWorker> {
+    method public W build();
+    method public static androidx.work.testing.TestListenableWorkerBuilder<? extends androidx.work.ListenableWorker> from(android.content.Context, androidx.work.WorkRequest);
+    method public static <W extends androidx.work.ListenableWorker> androidx.work.testing.TestListenableWorkerBuilder<W!> from(android.content.Context, Class<W!>);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setForegroundUpdater(androidx.work.ForegroundUpdater);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setId(java.util.UUID);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setInputData(androidx.work.Data);
+    method @RequiresApi(28) public androidx.work.testing.TestListenableWorkerBuilder<W!> setNetwork(android.net.Network);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setProgressUpdater(androidx.work.ProgressUpdater);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setRunAttemptCount(int);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setTags(java.util.List<java.lang.String!>);
+    method @RequiresApi(24) public androidx.work.testing.TestListenableWorkerBuilder<W!> setTriggeredContentAuthorities(java.util.List<java.lang.String!>);
+    method @RequiresApi(24) public androidx.work.testing.TestListenableWorkerBuilder<W!> setTriggeredContentUris(java.util.List<android.net.Uri!>);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setWorkerFactory(androidx.work.WorkerFactory);
+  }
+
+  public final class TestListenableWorkerBuilderKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.testing.TestListenableWorkerBuilder<W>! TestListenableWorkerBuilder(android.content.Context context, optional androidx.work.Data inputData, optional java.util.List<? extends java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<? extends java.lang.String> triggeredContentAuthorities);
+  }
+
+  public class TestWorkerBuilder<W extends androidx.work.Worker> extends androidx.work.testing.TestListenableWorkerBuilder<W> {
+    method public static androidx.work.testing.TestWorkerBuilder<? extends androidx.work.Worker> from(android.content.Context, androidx.work.WorkRequest, java.util.concurrent.Executor);
+    method public static <W extends androidx.work.Worker> androidx.work.testing.TestWorkerBuilder<W!> from(android.content.Context, Class<W!>, java.util.concurrent.Executor);
+  }
+
+  public final class TestWorkerBuilderKt {
+    method public static inline <reified W extends androidx.work.Worker> androidx.work.testing.TestWorkerBuilder<W>! TestWorkerBuilder(android.content.Context context, java.util.concurrent.Executor executor, optional androidx.work.Data inputData, optional java.util.List<? extends java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<? extends java.lang.String> triggeredContentAuthorities);
+  }
+
+  public final class WorkManagerTestInitHelper {
+    method @Deprecated public static androidx.work.testing.TestDriver? getTestDriver();
+    method public static androidx.work.testing.TestDriver? getTestDriver(android.content.Context);
+    method public static void initializeTestWorkManager(android.content.Context);
+    method public static void initializeTestWorkManager(android.content.Context, androidx.work.Configuration);
+  }
+
+}
+
diff --git a/work/workmanager/api/2.6.0-beta01.txt b/work/workmanager/api/2.6.0-beta01.txt
new file mode 100644
index 0000000..54713f5
--- /dev/null
+++ b/work/workmanager/api/2.6.0-beta01.txt
@@ -0,0 +1,400 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public final class ArrayCreatingInputMerger extends androidx.work.InputMerger {
+    ctor public ArrayCreatingInputMerger();
+    method public androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public enum BackoffPolicy {
+    enum_constant public static final androidx.work.BackoffPolicy EXPONENTIAL;
+    enum_constant public static final androidx.work.BackoffPolicy LINEAR;
+  }
+
+  public final class Configuration {
+    method public String? getDefaultProcessName();
+    method public java.util.concurrent.Executor getExecutor();
+    method public androidx.work.InputMergerFactory getInputMergerFactory();
+    method public int getMaxJobSchedulerId();
+    method public int getMinJobSchedulerId();
+    method public androidx.work.RunnableScheduler getRunnableScheduler();
+    method public java.util.concurrent.Executor getTaskExecutor();
+    method public androidx.work.WorkerFactory getWorkerFactory();
+    field public static final int MIN_SCHEDULER_LIMIT = 20; // 0x14
+  }
+
+  public static final class Configuration.Builder {
+    ctor public Configuration.Builder();
+    method public androidx.work.Configuration build();
+    method public androidx.work.Configuration.Builder setDefaultProcessName(String);
+    method public androidx.work.Configuration.Builder setExecutor(java.util.concurrent.Executor);
+    method public androidx.work.Configuration.Builder setInputMergerFactory(androidx.work.InputMergerFactory);
+    method public androidx.work.Configuration.Builder setJobSchedulerJobIdRange(int, int);
+    method public androidx.work.Configuration.Builder setMaxSchedulerLimit(int);
+    method public androidx.work.Configuration.Builder setMinimumLoggingLevel(int);
+    method public androidx.work.Configuration.Builder setRunnableScheduler(androidx.work.RunnableScheduler);
+    method public androidx.work.Configuration.Builder setTaskExecutor(java.util.concurrent.Executor);
+    method public androidx.work.Configuration.Builder setWorkerFactory(androidx.work.WorkerFactory);
+  }
+
+  public static interface Configuration.Provider {
+    method public androidx.work.Configuration getWorkManagerConfiguration();
+  }
+
+  public final class Constraints {
+    ctor public Constraints(androidx.work.Constraints);
+    method public androidx.work.NetworkType getRequiredNetworkType();
+    method public boolean requiresBatteryNotLow();
+    method public boolean requiresCharging();
+    method @RequiresApi(23) public boolean requiresDeviceIdle();
+    method public boolean requiresStorageNotLow();
+    field public static final androidx.work.Constraints NONE;
+  }
+
+  public static final class Constraints.Builder {
+    ctor public Constraints.Builder();
+    method @RequiresApi(24) public androidx.work.Constraints.Builder addContentUriTrigger(android.net.Uri, boolean);
+    method public androidx.work.Constraints build();
+    method public androidx.work.Constraints.Builder setRequiredNetworkType(androidx.work.NetworkType);
+    method public androidx.work.Constraints.Builder setRequiresBatteryNotLow(boolean);
+    method public androidx.work.Constraints.Builder setRequiresCharging(boolean);
+    method @RequiresApi(23) public androidx.work.Constraints.Builder setRequiresDeviceIdle(boolean);
+    method public androidx.work.Constraints.Builder setRequiresStorageNotLow(boolean);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(java.time.Duration!);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(java.time.Duration!);
+  }
+
+  public final class Data {
+    ctor public Data(androidx.work.Data);
+    method @androidx.room.TypeConverter public static androidx.work.Data fromByteArray(byte[]);
+    method public boolean getBoolean(String, boolean);
+    method public boolean[]? getBooleanArray(String);
+    method public byte getByte(String, byte);
+    method public byte[]? getByteArray(String);
+    method public double getDouble(String, double);
+    method public double[]? getDoubleArray(String);
+    method public float getFloat(String, float);
+    method public float[]? getFloatArray(String);
+    method public int getInt(String, int);
+    method public int[]? getIntArray(String);
+    method public java.util.Map<java.lang.String!,java.lang.Object!> getKeyValueMap();
+    method public long getLong(String, long);
+    method public long[]? getLongArray(String);
+    method public String? getString(String);
+    method public String![]? getStringArray(String);
+    method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
+    method public byte[] toByteArray();
+    field public static final androidx.work.Data EMPTY;
+    field public static final int MAX_DATA_BYTES = 10240; // 0x2800
+  }
+
+  public static final class Data.Builder {
+    ctor public Data.Builder();
+    method public androidx.work.Data build();
+    method public androidx.work.Data.Builder putAll(androidx.work.Data);
+    method public androidx.work.Data.Builder putAll(java.util.Map<java.lang.String!,java.lang.Object!>);
+    method public androidx.work.Data.Builder putBoolean(String, boolean);
+    method public androidx.work.Data.Builder putBooleanArray(String, boolean[]);
+    method public androidx.work.Data.Builder putByte(String, byte);
+    method public androidx.work.Data.Builder putByteArray(String, byte[]);
+    method public androidx.work.Data.Builder putDouble(String, double);
+    method public androidx.work.Data.Builder putDoubleArray(String, double[]);
+    method public androidx.work.Data.Builder putFloat(String, float);
+    method public androidx.work.Data.Builder putFloatArray(String, float[]);
+    method public androidx.work.Data.Builder putInt(String, int);
+    method public androidx.work.Data.Builder putIntArray(String, int[]);
+    method public androidx.work.Data.Builder putLong(String, long);
+    method public androidx.work.Data.Builder putLongArray(String, long[]);
+    method public androidx.work.Data.Builder putString(String, String?);
+    method public androidx.work.Data.Builder putStringArray(String, String![]);
+  }
+
+  public class DelegatingWorkerFactory extends androidx.work.WorkerFactory {
+    ctor public DelegatingWorkerFactory();
+    method public final void addFactory(androidx.work.WorkerFactory);
+    method public final androidx.work.ListenableWorker? createWorker(android.content.Context, String, androidx.work.WorkerParameters);
+  }
+
+  public enum ExistingPeriodicWorkPolicy {
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy KEEP;
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy REPLACE;
+  }
+
+  public enum ExistingWorkPolicy {
+    enum_constant public static final androidx.work.ExistingWorkPolicy APPEND;
+    enum_constant public static final androidx.work.ExistingWorkPolicy APPEND_OR_REPLACE;
+    enum_constant public static final androidx.work.ExistingWorkPolicy KEEP;
+    enum_constant public static final androidx.work.ExistingWorkPolicy REPLACE;
+  }
+
+  public final class ForegroundInfo {
+    ctor public ForegroundInfo(int, android.app.Notification);
+    ctor public ForegroundInfo(int, android.app.Notification, int);
+    method public int getForegroundServiceType();
+    method public android.app.Notification getNotification();
+    method public int getNotificationId();
+  }
+
+  public interface ForegroundUpdater {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setForegroundAsync(android.content.Context, java.util.UUID, androidx.work.ForegroundInfo);
+  }
+
+  public abstract class InputMerger {
+    ctor public InputMerger();
+    method public abstract androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public abstract class InputMergerFactory {
+    ctor public InputMergerFactory();
+    method public abstract androidx.work.InputMerger? createInputMerger(String);
+  }
+
+  public abstract class ListenableWorker {
+    ctor @Keep public ListenableWorker(android.content.Context, androidx.work.WorkerParameters);
+    method public final android.content.Context getApplicationContext();
+    method public final java.util.UUID getId();
+    method public final androidx.work.Data getInputData();
+    method @RequiresApi(28) public final android.net.Network? getNetwork();
+    method @IntRange(from=0) public final int getRunAttemptCount();
+    method public final java.util.Set<java.lang.String!> getTags();
+    method @RequiresApi(24) public final java.util.List<java.lang.String!> getTriggeredContentAuthorities();
+    method @RequiresApi(24) public final java.util.List<android.net.Uri!> getTriggeredContentUris();
+    method public final boolean isStopped();
+    method public void onStopped();
+    method public final com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setForegroundAsync(androidx.work.ForegroundInfo);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setProgressAsync(androidx.work.Data);
+    method @MainThread public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+  public abstract static class ListenableWorker.Result {
+    method public static androidx.work.ListenableWorker.Result failure();
+    method public static androidx.work.ListenableWorker.Result failure(androidx.work.Data);
+    method public abstract androidx.work.Data getOutputData();
+    method public static androidx.work.ListenableWorker.Result retry();
+    method public static androidx.work.ListenableWorker.Result success();
+    method public static androidx.work.ListenableWorker.Result success(androidx.work.Data);
+  }
+
+  public enum NetworkType {
+    enum_constant public static final androidx.work.NetworkType CONNECTED;
+    enum_constant public static final androidx.work.NetworkType METERED;
+    enum_constant public static final androidx.work.NetworkType NOT_REQUIRED;
+    enum_constant public static final androidx.work.NetworkType NOT_ROAMING;
+    enum_constant @RequiresApi(30) public static final androidx.work.NetworkType TEMPORARILY_UNMETERED;
+    enum_constant public static final androidx.work.NetworkType UNMETERED;
+  }
+
+  public final class OneTimeWorkRequest extends androidx.work.WorkRequest {
+    method public static androidx.work.OneTimeWorkRequest from(Class<? extends androidx.work.ListenableWorker>);
+    method public static java.util.List<androidx.work.OneTimeWorkRequest!> from(java.util.List<java.lang.Class<? extends androidx.work.ListenableWorker>!>);
+  }
+
+  public static final class OneTimeWorkRequest.Builder extends androidx.work.WorkRequest.Builder<androidx.work.OneTimeWorkRequest.Builder,androidx.work.OneTimeWorkRequest> {
+    ctor public OneTimeWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>);
+    method public androidx.work.OneTimeWorkRequest.Builder setInputMerger(Class<? extends androidx.work.InputMerger>);
+  }
+
+  public interface Operation {
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.Operation.State.SUCCESS!> getResult();
+    method public androidx.lifecycle.LiveData<androidx.work.Operation.State!> getState();
+  }
+
+  public abstract static class Operation.State {
+  }
+
+  public static final class Operation.State.FAILURE extends androidx.work.Operation.State {
+    ctor public Operation.State.FAILURE(Throwable);
+    method public Throwable getThrowable();
+  }
+
+  public static final class Operation.State.IN_PROGRESS extends androidx.work.Operation.State {
+  }
+
+  public static final class Operation.State.SUCCESS extends androidx.work.Operation.State {
+  }
+
+  public final class OverwritingInputMerger extends androidx.work.InputMerger {
+    ctor public OverwritingInputMerger();
+    method public androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public final class PeriodicWorkRequest extends androidx.work.WorkRequest {
+    field public static final long MIN_PERIODIC_FLEX_MILLIS = 300000L; // 0x493e0L
+    field public static final long MIN_PERIODIC_INTERVAL_MILLIS = 900000L; // 0xdbba0L
+  }
+
+  public static final class PeriodicWorkRequest.Builder extends androidx.work.WorkRequest.Builder<androidx.work.PeriodicWorkRequest.Builder,androidx.work.PeriodicWorkRequest> {
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>, long, java.util.concurrent.TimeUnit);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>, java.time.Duration);
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>, long, java.util.concurrent.TimeUnit, long, java.util.concurrent.TimeUnit);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>, java.time.Duration, java.time.Duration);
+  }
+
+  public interface ProgressUpdater {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> updateProgress(android.content.Context, java.util.UUID, androidx.work.Data);
+  }
+
+  public interface RunnableScheduler {
+    method public void cancel(Runnable);
+    method public void scheduleWithDelay(@IntRange(from=0) long, Runnable);
+  }
+
+  public abstract class WorkContinuation {
+    ctor public WorkContinuation();
+    method public static androidx.work.WorkContinuation combine(java.util.List<androidx.work.WorkContinuation!>);
+    method public abstract androidx.work.Operation enqueue();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos();
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosLiveData();
+    method public final androidx.work.WorkContinuation then(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation then(java.util.List<androidx.work.OneTimeWorkRequest!>);
+  }
+
+  public final class WorkInfo {
+    method public java.util.UUID getId();
+    method public androidx.work.Data getOutputData();
+    method public androidx.work.Data getProgress();
+    method @IntRange(from=0) public int getRunAttemptCount();
+    method public androidx.work.WorkInfo.State getState();
+    method public java.util.Set<java.lang.String!> getTags();
+  }
+
+  public enum WorkInfo.State {
+    method public boolean isFinished();
+    enum_constant public static final androidx.work.WorkInfo.State BLOCKED;
+    enum_constant public static final androidx.work.WorkInfo.State CANCELLED;
+    enum_constant public static final androidx.work.WorkInfo.State ENQUEUED;
+    enum_constant public static final androidx.work.WorkInfo.State FAILED;
+    enum_constant public static final androidx.work.WorkInfo.State RUNNING;
+    enum_constant public static final androidx.work.WorkInfo.State SUCCEEDED;
+  }
+
+  public abstract class WorkManager {
+    method public final androidx.work.WorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public final androidx.work.WorkContinuation beginWith(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation beginWith(java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract androidx.work.Operation cancelAllWork();
+    method public abstract androidx.work.Operation cancelAllWorkByTag(String);
+    method public abstract androidx.work.Operation cancelUniqueWork(String);
+    method public abstract androidx.work.Operation cancelWorkById(java.util.UUID);
+    method public abstract android.app.PendingIntent createCancelPendingIntent(java.util.UUID);
+    method public final androidx.work.Operation enqueue(androidx.work.WorkRequest);
+    method public abstract androidx.work.Operation enqueue(java.util.List<? extends androidx.work.WorkRequest>);
+    method public abstract androidx.work.Operation enqueueUniquePeriodicWork(String, androidx.work.ExistingPeriodicWorkPolicy, androidx.work.PeriodicWorkRequest);
+    method public androidx.work.Operation enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.Operation enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method @Deprecated public static androidx.work.WorkManager getInstance();
+    method public static androidx.work.WorkManager getInstance(android.content.Context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Long!> getLastCancelAllTimeMillis();
+    method public abstract androidx.lifecycle.LiveData<java.lang.Long!> getLastCancelAllTimeMillisLiveData();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.WorkInfo!> getWorkInfoById(java.util.UUID);
+    method public abstract androidx.lifecycle.LiveData<androidx.work.WorkInfo!> getWorkInfoByIdLiveData(java.util.UUID);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos(androidx.work.WorkQuery);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTag(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTagLiveData(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWork(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWorkLiveData(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosLiveData(androidx.work.WorkQuery);
+    method public static void initialize(android.content.Context, androidx.work.Configuration);
+    method public abstract androidx.work.Operation pruneWork();
+  }
+
+  public final class WorkManagerInitializer implements androidx.startup.Initializer<androidx.work.WorkManager> {
+    ctor public WorkManagerInitializer();
+    method public androidx.work.WorkManager create(android.content.Context);
+    method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<?>>!> dependencies();
+  }
+
+  public final class WorkQuery {
+    method public java.util.List<java.util.UUID!> getIds();
+    method public java.util.List<androidx.work.WorkInfo.State!> getStates();
+    method public java.util.List<java.lang.String!> getTags();
+    method public java.util.List<java.lang.String!> getUniqueWorkNames();
+  }
+
+  public static final class WorkQuery.Builder {
+    method public androidx.work.WorkQuery.Builder addIds(java.util.List<java.util.UUID!>);
+    method public androidx.work.WorkQuery.Builder addStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public androidx.work.WorkQuery.Builder addTags(java.util.List<java.lang.String!>);
+    method public androidx.work.WorkQuery.Builder addUniqueWorkNames(java.util.List<java.lang.String!>);
+    method public androidx.work.WorkQuery build();
+    method public static androidx.work.WorkQuery.Builder fromIds(java.util.List<java.util.UUID!>);
+    method public static androidx.work.WorkQuery.Builder fromStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public static androidx.work.WorkQuery.Builder fromTags(java.util.List<java.lang.String!>);
+    method public static androidx.work.WorkQuery.Builder fromUniqueWorkNames(java.util.List<java.lang.String!>);
+  }
+
+  public abstract class WorkRequest {
+    method public java.util.UUID getId();
+    field public static final long DEFAULT_BACKOFF_DELAY_MILLIS = 30000L; // 0x7530L
+    field public static final long MAX_BACKOFF_MILLIS = 18000000L; // 0x112a880L
+    field public static final long MIN_BACKOFF_MILLIS = 10000L; // 0x2710L
+  }
+
+  public abstract static class WorkRequest.Builder<B extends androidx.work.WorkRequest.Builder<?, ?>, W extends androidx.work.WorkRequest> {
+    method public final B addTag(String);
+    method public final W build();
+    method public final B keepResultsForAtLeast(long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public final B keepResultsForAtLeast(java.time.Duration);
+    method public final B setBackoffCriteria(androidx.work.BackoffPolicy, long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public final B setBackoffCriteria(androidx.work.BackoffPolicy, java.time.Duration);
+    method public final B setConstraints(androidx.work.Constraints);
+    method public B setInitialDelay(long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public B setInitialDelay(java.time.Duration);
+    method public final B setInputData(androidx.work.Data);
+  }
+
+  public abstract class Worker extends androidx.work.ListenableWorker {
+    ctor @Keep public Worker(android.content.Context, androidx.work.WorkerParameters);
+    method @WorkerThread public abstract androidx.work.ListenableWorker.Result doWork();
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+  public abstract class WorkerFactory {
+    ctor public WorkerFactory();
+    method public abstract androidx.work.ListenableWorker? createWorker(android.content.Context, String, androidx.work.WorkerParameters);
+  }
+
+  public final class WorkerParameters {
+    method public java.util.UUID getId();
+    method public androidx.work.Data getInputData();
+    method @RequiresApi(28) public android.net.Network? getNetwork();
+    method @IntRange(from=0) public int getRunAttemptCount();
+    method public java.util.Set<java.lang.String!> getTags();
+    method @RequiresApi(24) public java.util.List<java.lang.String!> getTriggeredContentAuthorities();
+    method @RequiresApi(24) public java.util.List<android.net.Uri!> getTriggeredContentUris();
+  }
+
+}
+
+package androidx.work.multiprocess {
+
+  public abstract class RemoteWorkContinuation {
+    method public static androidx.work.multiprocess.RemoteWorkContinuation combine(java.util.List<androidx.work.multiprocess.RemoteWorkContinuation!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue();
+    method public final androidx.work.multiprocess.RemoteWorkContinuation then(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation then(java.util.List<androidx.work.OneTimeWorkRequest!>);
+  }
+
+  public abstract class RemoteWorkManager {
+    method public final androidx.work.multiprocess.RemoteWorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public final androidx.work.multiprocess.RemoteWorkContinuation beginWith(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation beginWith(java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelAllWork();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelAllWorkByTag(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelUniqueWork(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelWorkById(java.util.UUID);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue(androidx.work.WorkRequest);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue(java.util.List<androidx.work.WorkRequest!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniquePeriodicWork(String, androidx.work.ExistingPeriodicWorkPolicy, androidx.work.PeriodicWorkRequest);
+    method public final com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public static androidx.work.multiprocess.RemoteWorkManager getInstance(android.content.Context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos(androidx.work.WorkQuery);
+  }
+
+}
+
diff --git a/work/workmanager/api/public_plus_experimental_2.6.0-beta01.txt b/work/workmanager/api/public_plus_experimental_2.6.0-beta01.txt
new file mode 100644
index 0000000..54713f5
--- /dev/null
+++ b/work/workmanager/api/public_plus_experimental_2.6.0-beta01.txt
@@ -0,0 +1,400 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public final class ArrayCreatingInputMerger extends androidx.work.InputMerger {
+    ctor public ArrayCreatingInputMerger();
+    method public androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public enum BackoffPolicy {
+    enum_constant public static final androidx.work.BackoffPolicy EXPONENTIAL;
+    enum_constant public static final androidx.work.BackoffPolicy LINEAR;
+  }
+
+  public final class Configuration {
+    method public String? getDefaultProcessName();
+    method public java.util.concurrent.Executor getExecutor();
+    method public androidx.work.InputMergerFactory getInputMergerFactory();
+    method public int getMaxJobSchedulerId();
+    method public int getMinJobSchedulerId();
+    method public androidx.work.RunnableScheduler getRunnableScheduler();
+    method public java.util.concurrent.Executor getTaskExecutor();
+    method public androidx.work.WorkerFactory getWorkerFactory();
+    field public static final int MIN_SCHEDULER_LIMIT = 20; // 0x14
+  }
+
+  public static final class Configuration.Builder {
+    ctor public Configuration.Builder();
+    method public androidx.work.Configuration build();
+    method public androidx.work.Configuration.Builder setDefaultProcessName(String);
+    method public androidx.work.Configuration.Builder setExecutor(java.util.concurrent.Executor);
+    method public androidx.work.Configuration.Builder setInputMergerFactory(androidx.work.InputMergerFactory);
+    method public androidx.work.Configuration.Builder setJobSchedulerJobIdRange(int, int);
+    method public androidx.work.Configuration.Builder setMaxSchedulerLimit(int);
+    method public androidx.work.Configuration.Builder setMinimumLoggingLevel(int);
+    method public androidx.work.Configuration.Builder setRunnableScheduler(androidx.work.RunnableScheduler);
+    method public androidx.work.Configuration.Builder setTaskExecutor(java.util.concurrent.Executor);
+    method public androidx.work.Configuration.Builder setWorkerFactory(androidx.work.WorkerFactory);
+  }
+
+  public static interface Configuration.Provider {
+    method public androidx.work.Configuration getWorkManagerConfiguration();
+  }
+
+  public final class Constraints {
+    ctor public Constraints(androidx.work.Constraints);
+    method public androidx.work.NetworkType getRequiredNetworkType();
+    method public boolean requiresBatteryNotLow();
+    method public boolean requiresCharging();
+    method @RequiresApi(23) public boolean requiresDeviceIdle();
+    method public boolean requiresStorageNotLow();
+    field public static final androidx.work.Constraints NONE;
+  }
+
+  public static final class Constraints.Builder {
+    ctor public Constraints.Builder();
+    method @RequiresApi(24) public androidx.work.Constraints.Builder addContentUriTrigger(android.net.Uri, boolean);
+    method public androidx.work.Constraints build();
+    method public androidx.work.Constraints.Builder setRequiredNetworkType(androidx.work.NetworkType);
+    method public androidx.work.Constraints.Builder setRequiresBatteryNotLow(boolean);
+    method public androidx.work.Constraints.Builder setRequiresCharging(boolean);
+    method @RequiresApi(23) public androidx.work.Constraints.Builder setRequiresDeviceIdle(boolean);
+    method public androidx.work.Constraints.Builder setRequiresStorageNotLow(boolean);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(java.time.Duration!);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(java.time.Duration!);
+  }
+
+  public final class Data {
+    ctor public Data(androidx.work.Data);
+    method @androidx.room.TypeConverter public static androidx.work.Data fromByteArray(byte[]);
+    method public boolean getBoolean(String, boolean);
+    method public boolean[]? getBooleanArray(String);
+    method public byte getByte(String, byte);
+    method public byte[]? getByteArray(String);
+    method public double getDouble(String, double);
+    method public double[]? getDoubleArray(String);
+    method public float getFloat(String, float);
+    method public float[]? getFloatArray(String);
+    method public int getInt(String, int);
+    method public int[]? getIntArray(String);
+    method public java.util.Map<java.lang.String!,java.lang.Object!> getKeyValueMap();
+    method public long getLong(String, long);
+    method public long[]? getLongArray(String);
+    method public String? getString(String);
+    method public String![]? getStringArray(String);
+    method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
+    method public byte[] toByteArray();
+    field public static final androidx.work.Data EMPTY;
+    field public static final int MAX_DATA_BYTES = 10240; // 0x2800
+  }
+
+  public static final class Data.Builder {
+    ctor public Data.Builder();
+    method public androidx.work.Data build();
+    method public androidx.work.Data.Builder putAll(androidx.work.Data);
+    method public androidx.work.Data.Builder putAll(java.util.Map<java.lang.String!,java.lang.Object!>);
+    method public androidx.work.Data.Builder putBoolean(String, boolean);
+    method public androidx.work.Data.Builder putBooleanArray(String, boolean[]);
+    method public androidx.work.Data.Builder putByte(String, byte);
+    method public androidx.work.Data.Builder putByteArray(String, byte[]);
+    method public androidx.work.Data.Builder putDouble(String, double);
+    method public androidx.work.Data.Builder putDoubleArray(String, double[]);
+    method public androidx.work.Data.Builder putFloat(String, float);
+    method public androidx.work.Data.Builder putFloatArray(String, float[]);
+    method public androidx.work.Data.Builder putInt(String, int);
+    method public androidx.work.Data.Builder putIntArray(String, int[]);
+    method public androidx.work.Data.Builder putLong(String, long);
+    method public androidx.work.Data.Builder putLongArray(String, long[]);
+    method public androidx.work.Data.Builder putString(String, String?);
+    method public androidx.work.Data.Builder putStringArray(String, String![]);
+  }
+
+  public class DelegatingWorkerFactory extends androidx.work.WorkerFactory {
+    ctor public DelegatingWorkerFactory();
+    method public final void addFactory(androidx.work.WorkerFactory);
+    method public final androidx.work.ListenableWorker? createWorker(android.content.Context, String, androidx.work.WorkerParameters);
+  }
+
+  public enum ExistingPeriodicWorkPolicy {
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy KEEP;
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy REPLACE;
+  }
+
+  public enum ExistingWorkPolicy {
+    enum_constant public static final androidx.work.ExistingWorkPolicy APPEND;
+    enum_constant public static final androidx.work.ExistingWorkPolicy APPEND_OR_REPLACE;
+    enum_constant public static final androidx.work.ExistingWorkPolicy KEEP;
+    enum_constant public static final androidx.work.ExistingWorkPolicy REPLACE;
+  }
+
+  public final class ForegroundInfo {
+    ctor public ForegroundInfo(int, android.app.Notification);
+    ctor public ForegroundInfo(int, android.app.Notification, int);
+    method public int getForegroundServiceType();
+    method public android.app.Notification getNotification();
+    method public int getNotificationId();
+  }
+
+  public interface ForegroundUpdater {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setForegroundAsync(android.content.Context, java.util.UUID, androidx.work.ForegroundInfo);
+  }
+
+  public abstract class InputMerger {
+    ctor public InputMerger();
+    method public abstract androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public abstract class InputMergerFactory {
+    ctor public InputMergerFactory();
+    method public abstract androidx.work.InputMerger? createInputMerger(String);
+  }
+
+  public abstract class ListenableWorker {
+    ctor @Keep public ListenableWorker(android.content.Context, androidx.work.WorkerParameters);
+    method public final android.content.Context getApplicationContext();
+    method public final java.util.UUID getId();
+    method public final androidx.work.Data getInputData();
+    method @RequiresApi(28) public final android.net.Network? getNetwork();
+    method @IntRange(from=0) public final int getRunAttemptCount();
+    method public final java.util.Set<java.lang.String!> getTags();
+    method @RequiresApi(24) public final java.util.List<java.lang.String!> getTriggeredContentAuthorities();
+    method @RequiresApi(24) public final java.util.List<android.net.Uri!> getTriggeredContentUris();
+    method public final boolean isStopped();
+    method public void onStopped();
+    method public final com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setForegroundAsync(androidx.work.ForegroundInfo);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setProgressAsync(androidx.work.Data);
+    method @MainThread public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+  public abstract static class ListenableWorker.Result {
+    method public static androidx.work.ListenableWorker.Result failure();
+    method public static androidx.work.ListenableWorker.Result failure(androidx.work.Data);
+    method public abstract androidx.work.Data getOutputData();
+    method public static androidx.work.ListenableWorker.Result retry();
+    method public static androidx.work.ListenableWorker.Result success();
+    method public static androidx.work.ListenableWorker.Result success(androidx.work.Data);
+  }
+
+  public enum NetworkType {
+    enum_constant public static final androidx.work.NetworkType CONNECTED;
+    enum_constant public static final androidx.work.NetworkType METERED;
+    enum_constant public static final androidx.work.NetworkType NOT_REQUIRED;
+    enum_constant public static final androidx.work.NetworkType NOT_ROAMING;
+    enum_constant @RequiresApi(30) public static final androidx.work.NetworkType TEMPORARILY_UNMETERED;
+    enum_constant public static final androidx.work.NetworkType UNMETERED;
+  }
+
+  public final class OneTimeWorkRequest extends androidx.work.WorkRequest {
+    method public static androidx.work.OneTimeWorkRequest from(Class<? extends androidx.work.ListenableWorker>);
+    method public static java.util.List<androidx.work.OneTimeWorkRequest!> from(java.util.List<java.lang.Class<? extends androidx.work.ListenableWorker>!>);
+  }
+
+  public static final class OneTimeWorkRequest.Builder extends androidx.work.WorkRequest.Builder<androidx.work.OneTimeWorkRequest.Builder,androidx.work.OneTimeWorkRequest> {
+    ctor public OneTimeWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>);
+    method public androidx.work.OneTimeWorkRequest.Builder setInputMerger(Class<? extends androidx.work.InputMerger>);
+  }
+
+  public interface Operation {
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.Operation.State.SUCCESS!> getResult();
+    method public androidx.lifecycle.LiveData<androidx.work.Operation.State!> getState();
+  }
+
+  public abstract static class Operation.State {
+  }
+
+  public static final class Operation.State.FAILURE extends androidx.work.Operation.State {
+    ctor public Operation.State.FAILURE(Throwable);
+    method public Throwable getThrowable();
+  }
+
+  public static final class Operation.State.IN_PROGRESS extends androidx.work.Operation.State {
+  }
+
+  public static final class Operation.State.SUCCESS extends androidx.work.Operation.State {
+  }
+
+  public final class OverwritingInputMerger extends androidx.work.InputMerger {
+    ctor public OverwritingInputMerger();
+    method public androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public final class PeriodicWorkRequest extends androidx.work.WorkRequest {
+    field public static final long MIN_PERIODIC_FLEX_MILLIS = 300000L; // 0x493e0L
+    field public static final long MIN_PERIODIC_INTERVAL_MILLIS = 900000L; // 0xdbba0L
+  }
+
+  public static final class PeriodicWorkRequest.Builder extends androidx.work.WorkRequest.Builder<androidx.work.PeriodicWorkRequest.Builder,androidx.work.PeriodicWorkRequest> {
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>, long, java.util.concurrent.TimeUnit);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>, java.time.Duration);
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>, long, java.util.concurrent.TimeUnit, long, java.util.concurrent.TimeUnit);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>, java.time.Duration, java.time.Duration);
+  }
+
+  public interface ProgressUpdater {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> updateProgress(android.content.Context, java.util.UUID, androidx.work.Data);
+  }
+
+  public interface RunnableScheduler {
+    method public void cancel(Runnable);
+    method public void scheduleWithDelay(@IntRange(from=0) long, Runnable);
+  }
+
+  public abstract class WorkContinuation {
+    ctor public WorkContinuation();
+    method public static androidx.work.WorkContinuation combine(java.util.List<androidx.work.WorkContinuation!>);
+    method public abstract androidx.work.Operation enqueue();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos();
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosLiveData();
+    method public final androidx.work.WorkContinuation then(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation then(java.util.List<androidx.work.OneTimeWorkRequest!>);
+  }
+
+  public final class WorkInfo {
+    method public java.util.UUID getId();
+    method public androidx.work.Data getOutputData();
+    method public androidx.work.Data getProgress();
+    method @IntRange(from=0) public int getRunAttemptCount();
+    method public androidx.work.WorkInfo.State getState();
+    method public java.util.Set<java.lang.String!> getTags();
+  }
+
+  public enum WorkInfo.State {
+    method public boolean isFinished();
+    enum_constant public static final androidx.work.WorkInfo.State BLOCKED;
+    enum_constant public static final androidx.work.WorkInfo.State CANCELLED;
+    enum_constant public static final androidx.work.WorkInfo.State ENQUEUED;
+    enum_constant public static final androidx.work.WorkInfo.State FAILED;
+    enum_constant public static final androidx.work.WorkInfo.State RUNNING;
+    enum_constant public static final androidx.work.WorkInfo.State SUCCEEDED;
+  }
+
+  public abstract class WorkManager {
+    method public final androidx.work.WorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public final androidx.work.WorkContinuation beginWith(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation beginWith(java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract androidx.work.Operation cancelAllWork();
+    method public abstract androidx.work.Operation cancelAllWorkByTag(String);
+    method public abstract androidx.work.Operation cancelUniqueWork(String);
+    method public abstract androidx.work.Operation cancelWorkById(java.util.UUID);
+    method public abstract android.app.PendingIntent createCancelPendingIntent(java.util.UUID);
+    method public final androidx.work.Operation enqueue(androidx.work.WorkRequest);
+    method public abstract androidx.work.Operation enqueue(java.util.List<? extends androidx.work.WorkRequest>);
+    method public abstract androidx.work.Operation enqueueUniquePeriodicWork(String, androidx.work.ExistingPeriodicWorkPolicy, androidx.work.PeriodicWorkRequest);
+    method public androidx.work.Operation enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.Operation enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method @Deprecated public static androidx.work.WorkManager getInstance();
+    method public static androidx.work.WorkManager getInstance(android.content.Context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Long!> getLastCancelAllTimeMillis();
+    method public abstract androidx.lifecycle.LiveData<java.lang.Long!> getLastCancelAllTimeMillisLiveData();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.WorkInfo!> getWorkInfoById(java.util.UUID);
+    method public abstract androidx.lifecycle.LiveData<androidx.work.WorkInfo!> getWorkInfoByIdLiveData(java.util.UUID);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos(androidx.work.WorkQuery);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTag(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTagLiveData(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWork(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWorkLiveData(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosLiveData(androidx.work.WorkQuery);
+    method public static void initialize(android.content.Context, androidx.work.Configuration);
+    method public abstract androidx.work.Operation pruneWork();
+  }
+
+  public final class WorkManagerInitializer implements androidx.startup.Initializer<androidx.work.WorkManager> {
+    ctor public WorkManagerInitializer();
+    method public androidx.work.WorkManager create(android.content.Context);
+    method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<?>>!> dependencies();
+  }
+
+  public final class WorkQuery {
+    method public java.util.List<java.util.UUID!> getIds();
+    method public java.util.List<androidx.work.WorkInfo.State!> getStates();
+    method public java.util.List<java.lang.String!> getTags();
+    method public java.util.List<java.lang.String!> getUniqueWorkNames();
+  }
+
+  public static final class WorkQuery.Builder {
+    method public androidx.work.WorkQuery.Builder addIds(java.util.List<java.util.UUID!>);
+    method public androidx.work.WorkQuery.Builder addStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public androidx.work.WorkQuery.Builder addTags(java.util.List<java.lang.String!>);
+    method public androidx.work.WorkQuery.Builder addUniqueWorkNames(java.util.List<java.lang.String!>);
+    method public androidx.work.WorkQuery build();
+    method public static androidx.work.WorkQuery.Builder fromIds(java.util.List<java.util.UUID!>);
+    method public static androidx.work.WorkQuery.Builder fromStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public static androidx.work.WorkQuery.Builder fromTags(java.util.List<java.lang.String!>);
+    method public static androidx.work.WorkQuery.Builder fromUniqueWorkNames(java.util.List<java.lang.String!>);
+  }
+
+  public abstract class WorkRequest {
+    method public java.util.UUID getId();
+    field public static final long DEFAULT_BACKOFF_DELAY_MILLIS = 30000L; // 0x7530L
+    field public static final long MAX_BACKOFF_MILLIS = 18000000L; // 0x112a880L
+    field public static final long MIN_BACKOFF_MILLIS = 10000L; // 0x2710L
+  }
+
+  public abstract static class WorkRequest.Builder<B extends androidx.work.WorkRequest.Builder<?, ?>, W extends androidx.work.WorkRequest> {
+    method public final B addTag(String);
+    method public final W build();
+    method public final B keepResultsForAtLeast(long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public final B keepResultsForAtLeast(java.time.Duration);
+    method public final B setBackoffCriteria(androidx.work.BackoffPolicy, long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public final B setBackoffCriteria(androidx.work.BackoffPolicy, java.time.Duration);
+    method public final B setConstraints(androidx.work.Constraints);
+    method public B setInitialDelay(long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public B setInitialDelay(java.time.Duration);
+    method public final B setInputData(androidx.work.Data);
+  }
+
+  public abstract class Worker extends androidx.work.ListenableWorker {
+    ctor @Keep public Worker(android.content.Context, androidx.work.WorkerParameters);
+    method @WorkerThread public abstract androidx.work.ListenableWorker.Result doWork();
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+  public abstract class WorkerFactory {
+    ctor public WorkerFactory();
+    method public abstract androidx.work.ListenableWorker? createWorker(android.content.Context, String, androidx.work.WorkerParameters);
+  }
+
+  public final class WorkerParameters {
+    method public java.util.UUID getId();
+    method public androidx.work.Data getInputData();
+    method @RequiresApi(28) public android.net.Network? getNetwork();
+    method @IntRange(from=0) public int getRunAttemptCount();
+    method public java.util.Set<java.lang.String!> getTags();
+    method @RequiresApi(24) public java.util.List<java.lang.String!> getTriggeredContentAuthorities();
+    method @RequiresApi(24) public java.util.List<android.net.Uri!> getTriggeredContentUris();
+  }
+
+}
+
+package androidx.work.multiprocess {
+
+  public abstract class RemoteWorkContinuation {
+    method public static androidx.work.multiprocess.RemoteWorkContinuation combine(java.util.List<androidx.work.multiprocess.RemoteWorkContinuation!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue();
+    method public final androidx.work.multiprocess.RemoteWorkContinuation then(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation then(java.util.List<androidx.work.OneTimeWorkRequest!>);
+  }
+
+  public abstract class RemoteWorkManager {
+    method public final androidx.work.multiprocess.RemoteWorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public final androidx.work.multiprocess.RemoteWorkContinuation beginWith(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation beginWith(java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelAllWork();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelAllWorkByTag(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelUniqueWork(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelWorkById(java.util.UUID);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue(androidx.work.WorkRequest);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue(java.util.List<androidx.work.WorkRequest!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniquePeriodicWork(String, androidx.work.ExistingPeriodicWorkPolicy, androidx.work.PeriodicWorkRequest);
+    method public final com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public static androidx.work.multiprocess.RemoteWorkManager getInstance(android.content.Context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos(androidx.work.WorkQuery);
+  }
+
+}
+
diff --git a/work/workmanager/api/res-2.6.0-beta01.txt b/work/workmanager/api/res-2.6.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/workmanager/api/res-2.6.0-beta01.txt
diff --git a/work/workmanager/api/restricted_2.6.0-beta01.txt b/work/workmanager/api/restricted_2.6.0-beta01.txt
new file mode 100644
index 0000000..54713f5
--- /dev/null
+++ b/work/workmanager/api/restricted_2.6.0-beta01.txt
@@ -0,0 +1,400 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public final class ArrayCreatingInputMerger extends androidx.work.InputMerger {
+    ctor public ArrayCreatingInputMerger();
+    method public androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public enum BackoffPolicy {
+    enum_constant public static final androidx.work.BackoffPolicy EXPONENTIAL;
+    enum_constant public static final androidx.work.BackoffPolicy LINEAR;
+  }
+
+  public final class Configuration {
+    method public String? getDefaultProcessName();
+    method public java.util.concurrent.Executor getExecutor();
+    method public androidx.work.InputMergerFactory getInputMergerFactory();
+    method public int getMaxJobSchedulerId();
+    method public int getMinJobSchedulerId();
+    method public androidx.work.RunnableScheduler getRunnableScheduler();
+    method public java.util.concurrent.Executor getTaskExecutor();
+    method public androidx.work.WorkerFactory getWorkerFactory();
+    field public static final int MIN_SCHEDULER_LIMIT = 20; // 0x14
+  }
+
+  public static final class Configuration.Builder {
+    ctor public Configuration.Builder();
+    method public androidx.work.Configuration build();
+    method public androidx.work.Configuration.Builder setDefaultProcessName(String);
+    method public androidx.work.Configuration.Builder setExecutor(java.util.concurrent.Executor);
+    method public androidx.work.Configuration.Builder setInputMergerFactory(androidx.work.InputMergerFactory);
+    method public androidx.work.Configuration.Builder setJobSchedulerJobIdRange(int, int);
+    method public androidx.work.Configuration.Builder setMaxSchedulerLimit(int);
+    method public androidx.work.Configuration.Builder setMinimumLoggingLevel(int);
+    method public androidx.work.Configuration.Builder setRunnableScheduler(androidx.work.RunnableScheduler);
+    method public androidx.work.Configuration.Builder setTaskExecutor(java.util.concurrent.Executor);
+    method public androidx.work.Configuration.Builder setWorkerFactory(androidx.work.WorkerFactory);
+  }
+
+  public static interface Configuration.Provider {
+    method public androidx.work.Configuration getWorkManagerConfiguration();
+  }
+
+  public final class Constraints {
+    ctor public Constraints(androidx.work.Constraints);
+    method public androidx.work.NetworkType getRequiredNetworkType();
+    method public boolean requiresBatteryNotLow();
+    method public boolean requiresCharging();
+    method @RequiresApi(23) public boolean requiresDeviceIdle();
+    method public boolean requiresStorageNotLow();
+    field public static final androidx.work.Constraints NONE;
+  }
+
+  public static final class Constraints.Builder {
+    ctor public Constraints.Builder();
+    method @RequiresApi(24) public androidx.work.Constraints.Builder addContentUriTrigger(android.net.Uri, boolean);
+    method public androidx.work.Constraints build();
+    method public androidx.work.Constraints.Builder setRequiredNetworkType(androidx.work.NetworkType);
+    method public androidx.work.Constraints.Builder setRequiresBatteryNotLow(boolean);
+    method public androidx.work.Constraints.Builder setRequiresCharging(boolean);
+    method @RequiresApi(23) public androidx.work.Constraints.Builder setRequiresDeviceIdle(boolean);
+    method public androidx.work.Constraints.Builder setRequiresStorageNotLow(boolean);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(java.time.Duration!);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(java.time.Duration!);
+  }
+
+  public final class Data {
+    ctor public Data(androidx.work.Data);
+    method @androidx.room.TypeConverter public static androidx.work.Data fromByteArray(byte[]);
+    method public boolean getBoolean(String, boolean);
+    method public boolean[]? getBooleanArray(String);
+    method public byte getByte(String, byte);
+    method public byte[]? getByteArray(String);
+    method public double getDouble(String, double);
+    method public double[]? getDoubleArray(String);
+    method public float getFloat(String, float);
+    method public float[]? getFloatArray(String);
+    method public int getInt(String, int);
+    method public int[]? getIntArray(String);
+    method public java.util.Map<java.lang.String!,java.lang.Object!> getKeyValueMap();
+    method public long getLong(String, long);
+    method public long[]? getLongArray(String);
+    method public String? getString(String);
+    method public String![]? getStringArray(String);
+    method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
+    method public byte[] toByteArray();
+    field public static final androidx.work.Data EMPTY;
+    field public static final int MAX_DATA_BYTES = 10240; // 0x2800
+  }
+
+  public static final class Data.Builder {
+    ctor public Data.Builder();
+    method public androidx.work.Data build();
+    method public androidx.work.Data.Builder putAll(androidx.work.Data);
+    method public androidx.work.Data.Builder putAll(java.util.Map<java.lang.String!,java.lang.Object!>);
+    method public androidx.work.Data.Builder putBoolean(String, boolean);
+    method public androidx.work.Data.Builder putBooleanArray(String, boolean[]);
+    method public androidx.work.Data.Builder putByte(String, byte);
+    method public androidx.work.Data.Builder putByteArray(String, byte[]);
+    method public androidx.work.Data.Builder putDouble(String, double);
+    method public androidx.work.Data.Builder putDoubleArray(String, double[]);
+    method public androidx.work.Data.Builder putFloat(String, float);
+    method public androidx.work.Data.Builder putFloatArray(String, float[]);
+    method public androidx.work.Data.Builder putInt(String, int);
+    method public androidx.work.Data.Builder putIntArray(String, int[]);
+    method public androidx.work.Data.Builder putLong(String, long);
+    method public androidx.work.Data.Builder putLongArray(String, long[]);
+    method public androidx.work.Data.Builder putString(String, String?);
+    method public androidx.work.Data.Builder putStringArray(String, String![]);
+  }
+
+  public class DelegatingWorkerFactory extends androidx.work.WorkerFactory {
+    ctor public DelegatingWorkerFactory();
+    method public final void addFactory(androidx.work.WorkerFactory);
+    method public final androidx.work.ListenableWorker? createWorker(android.content.Context, String, androidx.work.WorkerParameters);
+  }
+
+  public enum ExistingPeriodicWorkPolicy {
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy KEEP;
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy REPLACE;
+  }
+
+  public enum ExistingWorkPolicy {
+    enum_constant public static final androidx.work.ExistingWorkPolicy APPEND;
+    enum_constant public static final androidx.work.ExistingWorkPolicy APPEND_OR_REPLACE;
+    enum_constant public static final androidx.work.ExistingWorkPolicy KEEP;
+    enum_constant public static final androidx.work.ExistingWorkPolicy REPLACE;
+  }
+
+  public final class ForegroundInfo {
+    ctor public ForegroundInfo(int, android.app.Notification);
+    ctor public ForegroundInfo(int, android.app.Notification, int);
+    method public int getForegroundServiceType();
+    method public android.app.Notification getNotification();
+    method public int getNotificationId();
+  }
+
+  public interface ForegroundUpdater {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setForegroundAsync(android.content.Context, java.util.UUID, androidx.work.ForegroundInfo);
+  }
+
+  public abstract class InputMerger {
+    ctor public InputMerger();
+    method public abstract androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public abstract class InputMergerFactory {
+    ctor public InputMergerFactory();
+    method public abstract androidx.work.InputMerger? createInputMerger(String);
+  }
+
+  public abstract class ListenableWorker {
+    ctor @Keep public ListenableWorker(android.content.Context, androidx.work.WorkerParameters);
+    method public final android.content.Context getApplicationContext();
+    method public final java.util.UUID getId();
+    method public final androidx.work.Data getInputData();
+    method @RequiresApi(28) public final android.net.Network? getNetwork();
+    method @IntRange(from=0) public final int getRunAttemptCount();
+    method public final java.util.Set<java.lang.String!> getTags();
+    method @RequiresApi(24) public final java.util.List<java.lang.String!> getTriggeredContentAuthorities();
+    method @RequiresApi(24) public final java.util.List<android.net.Uri!> getTriggeredContentUris();
+    method public final boolean isStopped();
+    method public void onStopped();
+    method public final com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setForegroundAsync(androidx.work.ForegroundInfo);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setProgressAsync(androidx.work.Data);
+    method @MainThread public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+  public abstract static class ListenableWorker.Result {
+    method public static androidx.work.ListenableWorker.Result failure();
+    method public static androidx.work.ListenableWorker.Result failure(androidx.work.Data);
+    method public abstract androidx.work.Data getOutputData();
+    method public static androidx.work.ListenableWorker.Result retry();
+    method public static androidx.work.ListenableWorker.Result success();
+    method public static androidx.work.ListenableWorker.Result success(androidx.work.Data);
+  }
+
+  public enum NetworkType {
+    enum_constant public static final androidx.work.NetworkType CONNECTED;
+    enum_constant public static final androidx.work.NetworkType METERED;
+    enum_constant public static final androidx.work.NetworkType NOT_REQUIRED;
+    enum_constant public static final androidx.work.NetworkType NOT_ROAMING;
+    enum_constant @RequiresApi(30) public static final androidx.work.NetworkType TEMPORARILY_UNMETERED;
+    enum_constant public static final androidx.work.NetworkType UNMETERED;
+  }
+
+  public final class OneTimeWorkRequest extends androidx.work.WorkRequest {
+    method public static androidx.work.OneTimeWorkRequest from(Class<? extends androidx.work.ListenableWorker>);
+    method public static java.util.List<androidx.work.OneTimeWorkRequest!> from(java.util.List<java.lang.Class<? extends androidx.work.ListenableWorker>!>);
+  }
+
+  public static final class OneTimeWorkRequest.Builder extends androidx.work.WorkRequest.Builder<androidx.work.OneTimeWorkRequest.Builder,androidx.work.OneTimeWorkRequest> {
+    ctor public OneTimeWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>);
+    method public androidx.work.OneTimeWorkRequest.Builder setInputMerger(Class<? extends androidx.work.InputMerger>);
+  }
+
+  public interface Operation {
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.Operation.State.SUCCESS!> getResult();
+    method public androidx.lifecycle.LiveData<androidx.work.Operation.State!> getState();
+  }
+
+  public abstract static class Operation.State {
+  }
+
+  public static final class Operation.State.FAILURE extends androidx.work.Operation.State {
+    ctor public Operation.State.FAILURE(Throwable);
+    method public Throwable getThrowable();
+  }
+
+  public static final class Operation.State.IN_PROGRESS extends androidx.work.Operation.State {
+  }
+
+  public static final class Operation.State.SUCCESS extends androidx.work.Operation.State {
+  }
+
+  public final class OverwritingInputMerger extends androidx.work.InputMerger {
+    ctor public OverwritingInputMerger();
+    method public androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public final class PeriodicWorkRequest extends androidx.work.WorkRequest {
+    field public static final long MIN_PERIODIC_FLEX_MILLIS = 300000L; // 0x493e0L
+    field public static final long MIN_PERIODIC_INTERVAL_MILLIS = 900000L; // 0xdbba0L
+  }
+
+  public static final class PeriodicWorkRequest.Builder extends androidx.work.WorkRequest.Builder<androidx.work.PeriodicWorkRequest.Builder,androidx.work.PeriodicWorkRequest> {
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>, long, java.util.concurrent.TimeUnit);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>, java.time.Duration);
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>, long, java.util.concurrent.TimeUnit, long, java.util.concurrent.TimeUnit);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker>, java.time.Duration, java.time.Duration);
+  }
+
+  public interface ProgressUpdater {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> updateProgress(android.content.Context, java.util.UUID, androidx.work.Data);
+  }
+
+  public interface RunnableScheduler {
+    method public void cancel(Runnable);
+    method public void scheduleWithDelay(@IntRange(from=0) long, Runnable);
+  }
+
+  public abstract class WorkContinuation {
+    ctor public WorkContinuation();
+    method public static androidx.work.WorkContinuation combine(java.util.List<androidx.work.WorkContinuation!>);
+    method public abstract androidx.work.Operation enqueue();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos();
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosLiveData();
+    method public final androidx.work.WorkContinuation then(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation then(java.util.List<androidx.work.OneTimeWorkRequest!>);
+  }
+
+  public final class WorkInfo {
+    method public java.util.UUID getId();
+    method public androidx.work.Data getOutputData();
+    method public androidx.work.Data getProgress();
+    method @IntRange(from=0) public int getRunAttemptCount();
+    method public androidx.work.WorkInfo.State getState();
+    method public java.util.Set<java.lang.String!> getTags();
+  }
+
+  public enum WorkInfo.State {
+    method public boolean isFinished();
+    enum_constant public static final androidx.work.WorkInfo.State BLOCKED;
+    enum_constant public static final androidx.work.WorkInfo.State CANCELLED;
+    enum_constant public static final androidx.work.WorkInfo.State ENQUEUED;
+    enum_constant public static final androidx.work.WorkInfo.State FAILED;
+    enum_constant public static final androidx.work.WorkInfo.State RUNNING;
+    enum_constant public static final androidx.work.WorkInfo.State SUCCEEDED;
+  }
+
+  public abstract class WorkManager {
+    method public final androidx.work.WorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public final androidx.work.WorkContinuation beginWith(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation beginWith(java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract androidx.work.Operation cancelAllWork();
+    method public abstract androidx.work.Operation cancelAllWorkByTag(String);
+    method public abstract androidx.work.Operation cancelUniqueWork(String);
+    method public abstract androidx.work.Operation cancelWorkById(java.util.UUID);
+    method public abstract android.app.PendingIntent createCancelPendingIntent(java.util.UUID);
+    method public final androidx.work.Operation enqueue(androidx.work.WorkRequest);
+    method public abstract androidx.work.Operation enqueue(java.util.List<? extends androidx.work.WorkRequest>);
+    method public abstract androidx.work.Operation enqueueUniquePeriodicWork(String, androidx.work.ExistingPeriodicWorkPolicy, androidx.work.PeriodicWorkRequest);
+    method public androidx.work.Operation enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.Operation enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method @Deprecated public static androidx.work.WorkManager getInstance();
+    method public static androidx.work.WorkManager getInstance(android.content.Context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Long!> getLastCancelAllTimeMillis();
+    method public abstract androidx.lifecycle.LiveData<java.lang.Long!> getLastCancelAllTimeMillisLiveData();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.WorkInfo!> getWorkInfoById(java.util.UUID);
+    method public abstract androidx.lifecycle.LiveData<androidx.work.WorkInfo!> getWorkInfoByIdLiveData(java.util.UUID);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos(androidx.work.WorkQuery);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTag(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTagLiveData(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWork(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWorkLiveData(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosLiveData(androidx.work.WorkQuery);
+    method public static void initialize(android.content.Context, androidx.work.Configuration);
+    method public abstract androidx.work.Operation pruneWork();
+  }
+
+  public final class WorkManagerInitializer implements androidx.startup.Initializer<androidx.work.WorkManager> {
+    ctor public WorkManagerInitializer();
+    method public androidx.work.WorkManager create(android.content.Context);
+    method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<?>>!> dependencies();
+  }
+
+  public final class WorkQuery {
+    method public java.util.List<java.util.UUID!> getIds();
+    method public java.util.List<androidx.work.WorkInfo.State!> getStates();
+    method public java.util.List<java.lang.String!> getTags();
+    method public java.util.List<java.lang.String!> getUniqueWorkNames();
+  }
+
+  public static final class WorkQuery.Builder {
+    method public androidx.work.WorkQuery.Builder addIds(java.util.List<java.util.UUID!>);
+    method public androidx.work.WorkQuery.Builder addStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public androidx.work.WorkQuery.Builder addTags(java.util.List<java.lang.String!>);
+    method public androidx.work.WorkQuery.Builder addUniqueWorkNames(java.util.List<java.lang.String!>);
+    method public androidx.work.WorkQuery build();
+    method public static androidx.work.WorkQuery.Builder fromIds(java.util.List<java.util.UUID!>);
+    method public static androidx.work.WorkQuery.Builder fromStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public static androidx.work.WorkQuery.Builder fromTags(java.util.List<java.lang.String!>);
+    method public static androidx.work.WorkQuery.Builder fromUniqueWorkNames(java.util.List<java.lang.String!>);
+  }
+
+  public abstract class WorkRequest {
+    method public java.util.UUID getId();
+    field public static final long DEFAULT_BACKOFF_DELAY_MILLIS = 30000L; // 0x7530L
+    field public static final long MAX_BACKOFF_MILLIS = 18000000L; // 0x112a880L
+    field public static final long MIN_BACKOFF_MILLIS = 10000L; // 0x2710L
+  }
+
+  public abstract static class WorkRequest.Builder<B extends androidx.work.WorkRequest.Builder<?, ?>, W extends androidx.work.WorkRequest> {
+    method public final B addTag(String);
+    method public final W build();
+    method public final B keepResultsForAtLeast(long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public final B keepResultsForAtLeast(java.time.Duration);
+    method public final B setBackoffCriteria(androidx.work.BackoffPolicy, long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public final B setBackoffCriteria(androidx.work.BackoffPolicy, java.time.Duration);
+    method public final B setConstraints(androidx.work.Constraints);
+    method public B setInitialDelay(long, java.util.concurrent.TimeUnit);
+    method @RequiresApi(26) public B setInitialDelay(java.time.Duration);
+    method public final B setInputData(androidx.work.Data);
+  }
+
+  public abstract class Worker extends androidx.work.ListenableWorker {
+    ctor @Keep public Worker(android.content.Context, androidx.work.WorkerParameters);
+    method @WorkerThread public abstract androidx.work.ListenableWorker.Result doWork();
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+  public abstract class WorkerFactory {
+    ctor public WorkerFactory();
+    method public abstract androidx.work.ListenableWorker? createWorker(android.content.Context, String, androidx.work.WorkerParameters);
+  }
+
+  public final class WorkerParameters {
+    method public java.util.UUID getId();
+    method public androidx.work.Data getInputData();
+    method @RequiresApi(28) public android.net.Network? getNetwork();
+    method @IntRange(from=0) public int getRunAttemptCount();
+    method public java.util.Set<java.lang.String!> getTags();
+    method @RequiresApi(24) public java.util.List<java.lang.String!> getTriggeredContentAuthorities();
+    method @RequiresApi(24) public java.util.List<android.net.Uri!> getTriggeredContentUris();
+  }
+
+}
+
+package androidx.work.multiprocess {
+
+  public abstract class RemoteWorkContinuation {
+    method public static androidx.work.multiprocess.RemoteWorkContinuation combine(java.util.List<androidx.work.multiprocess.RemoteWorkContinuation!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue();
+    method public final androidx.work.multiprocess.RemoteWorkContinuation then(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation then(java.util.List<androidx.work.OneTimeWorkRequest!>);
+  }
+
+  public abstract class RemoteWorkManager {
+    method public final androidx.work.multiprocess.RemoteWorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public final androidx.work.multiprocess.RemoteWorkContinuation beginWith(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation beginWith(java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelAllWork();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelAllWorkByTag(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelUniqueWork(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelWorkById(java.util.UUID);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue(androidx.work.WorkRequest);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue(java.util.List<androidx.work.WorkRequest!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniquePeriodicWork(String, androidx.work.ExistingPeriodicWorkPolicy, androidx.work.PeriodicWorkRequest);
+    method public final com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public static androidx.work.multiprocess.RemoteWorkManager getInstance(android.content.Context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos(androidx.work.WorkQuery);
+  }
+
+}
+