[go: nahoru, domu]

Merge "Moving startWork call in WorkerWrapper into coroutine" into androidx-main
diff --git a/benchmark/benchmark-common/lint-baseline.xml b/benchmark/benchmark-common/lint-baseline.xml
index 96cf036..4dba6aa 100644
--- a/benchmark/benchmark-common/lint-baseline.xml
+++ b/benchmark/benchmark-common/lint-baseline.xml
@@ -1,77 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 23 (current min is 19): `stopAllPerfettoProcesses`"
-        errorLine1="        PerfettoHelper.stopAllPerfettoProcesses()"
-        errorLine2="                       ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 21 (current min is 19): `getPidsForProcess`"
-        errorLine1="        fun getPerfettoPids() = Shell.getPidsForProcess(if (unbundled) &quot;tracebox&quot; else &quot;perfetto&quot;)"
-        errorLine2="                                      ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 23 (current min is 19): `PerfettoCapture`"
-        errorLine1="        val capture = PerfettoCapture(unbundled)"
-        errorLine2="                      ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 23 (current min is 19): `start`"
-        errorLine1="        capture.start("
-        errorLine2="                ~~~~~">
-        <location
-            file="src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 23 (current min is 19): `isRunning`"
-        errorLine1="        assertTrue(capture.isRunning())"
-        errorLine2="                           ~~~~~~~~~">
-        <location
-            file="src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 23 (current min is 19): `stopAllPerfettoProcesses`"
-        errorLine1="        PerfettoHelper.stopAllPerfettoProcesses()"
-        errorLine2="                       ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 23 (current min is 19): `isRunning`"
-        errorLine1="        assertFalse(capture.isRunning())"
-        errorLine2="                            ~~~~~~~~~">
-        <location
-            file="src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 23 (current min is 19): `isAbiSupported`"
-        errorLine1="        Assume.assumeTrue(PerfettoHelper.isAbiSupported())"
-        errorLine2="                                         ~~~~~~~~~~~~~~">
-        <location
-            file="src/androidTest/java/androidx/benchmark/PerfettoHelperTest.kt"/>
-    </issue>
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="UnsafeOptInUsageError"
diff --git a/benchmark/benchmark-macro/lint-baseline.xml b/benchmark/benchmark-macro/lint-baseline.xml
index 3743177..5309e22 100644
--- a/benchmark/benchmark-macro/lint-baseline.xml
+++ b/benchmark/benchmark-macro/lint-baseline.xml
@@ -1,23 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
-
-    <issue
-        id="NewApi"
-        message="Class requires API level 29 (current min is 23): `Power`"
-        errorLine1="            return if (type is PowerMetric.Type.Power) powerUw else energyUws"
-        errorLine2="                               ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/benchmark/macro/perfetto/PowerQuery.kt"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Class requires API level 29 (current min is 23): `Power`"
-        errorLine1="            return if (type is PowerMetric.Type.Power) powerUw else energyUws"
-        errorLine2="                               ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/benchmark/macro/perfetto/PowerQuery.kt"/>
-    </issue>
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="BanThreadSleep"
diff --git a/buildSrc-tests/lint-baseline.xml b/buildSrc-tests/lint-baseline.xml
index 7bd6c6b..8f0a5db 100644
--- a/buildSrc-tests/lint-baseline.xml
+++ b/buildSrc-tests/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="EagerGradleConfiguration"
@@ -202,51 +202,6 @@
     <issue
         id="EagerGradleConfiguration"
         message="Avoid using eager method findByName"
-        errorLine1="        testExtension.sourceSets.findByName(&quot;main&quot;)?.let { sourceSet ->"
-        errorLine2="                                 ~~~~~~~~~~">
-        <location
-            file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/AndroidXImplPlugin.kt"/>
-    </issue>
-
-    <issue
-        id="EagerGradleConfiguration"
-        message="Avoid using eager method findByName"
-        errorLine1="            ?.findByName(&quot;main&quot;)"
-        errorLine2="              ~~~~~~~~~~">
-        <location
-            file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/AndroidXImplPlugin.kt"/>
-    </issue>
-
-    <issue
-        id="EagerGradleConfiguration"
-        message="Avoid using eager method findByName"
-        errorLine1="        ?.findByName(&quot;androidTest&quot;)"
-        errorLine2="          ~~~~~~~~~~">
-        <location
-            file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/AndroidXImplPlugin.kt"/>
-    </issue>
-
-    <issue
-        id="EagerGradleConfiguration"
-        message="Avoid using eager method findByName"
-        errorLine1="        ?.findByName(&quot;androidTest&quot;)"
-        errorLine2="          ~~~~~~~~~~">
-        <location
-            file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/AndroidXImplPlugin.kt"/>
-    </issue>
-
-    <issue
-        id="EagerGradleConfiguration"
-        message="Avoid using eager method findByName"
-        errorLine1="                target -> target.compilations.findByName(&quot;debugAndroidTest&quot;)"
-        errorLine2="                                              ~~~~~~~~~~">
-        <location
-            file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/AndroidXImplPlugin.kt"/>
-    </issue>
-
-    <issue
-        id="EagerGradleConfiguration"
-        message="Avoid using eager method findByName"
         errorLine1="            val androidConfiguration = project.configurations.findByName(&quot;implementation&quot;)"
         errorLine2="                                                              ~~~~~~~~~~">
         <location
diff --git a/buildSrc/apply/applyAndroidXPaparazziImplPlugin.gradle b/buildSrc/apply/applyAndroidXPaparazziImplPlugin.gradle
deleted file mode 100644
index ece0f79..0000000
--- a/buildSrc/apply/applyAndroidXPaparazziImplPlugin.gradle
+++ /dev/null
@@ -1,9 +0,0 @@
-import androidx.build.paparazzi.AndroidXPaparazziImplPlugin
-
-buildscript {
-    dependencies {
-        classpath(project.files("${project.rootProject.ext["buildSrcOut"]}/private/build/libs/private.jar"))
-    }
-}
-
-apply plugin: AndroidXPaparazziImplPlugin
diff --git a/buildSrc/plugins/src/main/kotlin/androidx/build/AndroidXPaparazziPlugin.kt b/buildSrc/plugins/src/main/kotlin/androidx/build/AndroidXPaparazziPlugin.kt
deleted file mode 100644
index 090d9b6..0000000
--- a/buildSrc/plugins/src/main/kotlin/androidx/build/AndroidXPaparazziPlugin.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.build
-
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-
-/**
- * Configures screenshot testing using Paparazzi for AndroidX projects.
- *
- * The actual implementation is in AndroidXPaparazziImplPlugin.
- */
-class AndroidXPaparazziPlugin : Plugin<Project> {
-    override fun apply(project: Project) {
-        val supportRoot = project.getSupportRootFolder()
-        project.apply(
-            mapOf("from" to "$supportRoot/buildSrc/apply/applyAndroidXPaparazziImplPlugin.gradle")
-        )
-    }
-}
diff --git a/buildSrc/plugins/src/main/resources/META-INF/gradle-plugins/AndroidXPaparazziPlugin.properties b/buildSrc/plugins/src/main/resources/META-INF/gradle-plugins/AndroidXPaparazziPlugin.properties
deleted file mode 100644
index 872551c..0000000
--- a/buildSrc/plugins/src/main/resources/META-INF/gradle-plugins/AndroidXPaparazziPlugin.properties
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Copyright 2022 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-implementation-class=androidx.build.AndroidXPaparazziPlugin
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
index 0c2315e..a67c3d3 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
@@ -733,7 +733,11 @@
 private val hiddenAnnotationsJava: List<String> = emptyList()
 
 // Annotations which mean the elements they are applied to should be hidden from the docs
-private val annotationsToHideApis: List<String> = listOf("androidx.annotation.RestrictTo")
+private val annotationsToHideApis: List<String> = listOf(
+    "androidx.annotation.RestrictTo",
+    // Appears in androidx.test sources
+    "dagger.internal.DaggerGenerated",
+)
 
 /** Data class that matches JSON structure of kotlin source set metadata */
 data class ProjectStructureMetadata(var sourceSets: List<SourceSetMetadata>)
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/paparazzi/AndroidXPaparazziImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/paparazzi/AndroidXPaparazziImplPlugin.kt
deleted file mode 100644
index 6c3b775..0000000
--- a/buildSrc/private/src/main/kotlin/androidx/build/paparazzi/AndroidXPaparazziImplPlugin.kt
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.build.paparazzi
-
-import androidx.build.OperatingSystem
-import androidx.build.defaultAndroidConfig
-import androidx.build.getLibraryByName
-import androidx.build.getOperatingSystem
-import androidx.build.getSdkPath
-import androidx.build.getSupportRootFolder
-import com.android.build.gradle.BaseExtension
-import javax.inject.Inject
-import org.gradle.api.Plugin
-import org.gradle.api.Project
-import org.gradle.api.artifacts.type.ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE
-import org.gradle.api.artifacts.type.ArtifactTypeDefinition.JAR_TYPE
-import org.gradle.api.file.Directory
-import org.gradle.api.file.FileCollection
-import org.gradle.api.file.FileSystemOperations
-import org.gradle.api.provider.Provider
-import org.gradle.api.tasks.Copy
-import org.gradle.api.tasks.PathSensitivity
-import org.gradle.api.tasks.testing.Test
-import org.gradle.kotlin.dsl.get
-import org.gradle.kotlin.dsl.register
-import org.gradle.kotlin.dsl.the
-import org.gradle.kotlin.dsl.withType
-import org.gradle.process.JavaForkOptions
-
-/** Configures screenshot testing using Paparazzi for AndroidX projects. */
-class AndroidXPaparazziImplPlugin
-@Inject
-constructor(private val fileSystemOperations: FileSystemOperations) : Plugin<Project> {
-    override fun apply(project: Project) {
-        val paparazziNative = project.createUnzippedPaparazziNativeDependency()
-        project.afterEvaluate { it.addTestUtilsDependency() }
-        project.tasks.register("updateGolden")
-        project.afterEvaluate {
-            // need to be inside of afterEvaluate because we read android.namespace
-            // ideally, we refactor to use a lazy API
-            project.tasks.withType<Test>().configureEach { it.configureTestTask(paparazziNative) }
-        }
-        project.tasks.withType<Test>().whenTaskAdded { project.registerUpdateGoldenTask(it) }
-    }
-
-    /**
-     * Add project's golden directory and the unzipped native Paparazzi location as task inputs, and
-     * set system properties for the test library to consume at runtime.
-     */
-    private fun Test.configureTestTask(paparazziNative: FileCollection) {
-        val compileSdkVersion = project.defaultAndroidConfig.compileSdk
-        val platformDirectory = project.getSdkPath().resolve("platforms/$compileSdkVersion")
-        val cachedGoldenRootDirectory = project.goldenRootDirectory
-        val cachedReportDirectory = reportDirectory
-        val android = project.the<BaseExtension>()
-        val packageName =
-            requireNotNull(android.namespace) { "android.namespace must be set for Paparazzi" }
-
-        // Attach unzipped Paparazzi native directory as a task input
-        inputs
-            .files(paparazziNative)
-            .withPathSensitivity(PathSensitivity.NONE)
-            .withPropertyName("paparazziNative")
-
-        // Attach golden directory to task inputs to invalidate tests when updating goldens
-        inputs
-            .dir(project.goldenDirectory)
-            .withPathSensitivity(PathSensitivity.RELATIVE)
-            .withPropertyName("goldenDirectory")
-
-        // Mark report directory as an output directory
-        outputs.dir(reportDirectory).withPropertyName("paparazziReportDir")
-
-        // Clean the contents of the report directory before each test run
-        doFirst {
-            fileSystemOperations.delete {
-                it.delete(cachedReportDirectory.get().asFile.listFiles())
-            }
-        }
-
-        // Set non-path system properties at configuration time, so that changes invalidate caching
-        prefixedSystemProperties(
-            "gradlePluginApplied" to "true",
-            "compileSdkVersion" to project.defaultAndroidConfig.targetSdk,
-            "resourcePackageNames" to packageName, // TODO: Transitive resource packages?
-            "modulePath" to project.modulePath,
-            "updateGoldenTask" to "${project.path}:${updateGoldenTaskName()}"
-        )
-
-        // Set the remaining system properties at execution time, after the snapshotting, so that
-        // the absolute paths don't affect caching
-        doFirst {
-            systemProperty("paparazzi.platform.data.root", paparazziNative.singleFile.canonicalPath)
-            prefixedSystemProperties(
-                "platformDir" to platformDirectory.canonicalPath,
-                "assetsDir" to ".", // TODO: Merged assets dirs? (needed for compose?)
-                "resDir" to ".", // TODO: Merged resource dirs? (needed for compose?)
-                "reportDir" to cachedReportDirectory.get().asFile.canonicalPath,
-                "goldenRootDir" to cachedGoldenRootDirectory.canonicalPath,
-            )
-        }
-    }
-
-    /** Register a copy task for moving new images to the golden directory. */
-    private fun Project.registerUpdateGoldenTask(testTask: Test) {
-        tasks.register<Copy>(testTask.updateGoldenTaskName()) {
-            dependsOn(testTask)
-
-            from(testTask.reportDirectory) {
-                include("**/*_actual.png")
-                into(goldenDirectory)
-                rename { it.removeSuffix("_actual.png") + "_paparazzi.png" }
-            }
-        }
-
-        tasks["updateGolden"].dependsOn(testTask.updateGoldenTaskName())
-    }
-
-    /** Derive updateGolden task name from a test task name. */
-    private fun Test.updateGoldenTaskName(): String {
-        return "updateGolden" + name.removePrefix("test").replaceFirstChar { it.titlecase() }
-    }
-
-    /**
-     * Configure [UnzipPaparazziNativeTransform] for the project, and add the platform-specific
-     * Paparazzi native layoutlib dependency, using the version in `libs.versions.toml`.
-     */
-    private fun Project.createUnzippedPaparazziNativeDependency(): FileCollection {
-        val platformSuffix =
-            when (val os = getOperatingSystem()) {
-                OperatingSystem.LINUX -> "LinuxX64"
-                OperatingSystem.MAC -> {
-                    val arch = System.getProperty("os.arch")
-                    if (arch.startsWith("x86", ignoreCase = true)) "MacOsX64" else "MacOsArm64"
-                }
-                else -> error("Unsupported operating system $os for Paparazzi")
-            }
-
-        dependencies.registerTransform(UnzipPaparazziNativeTransform::class.java) { spec ->
-            spec.from.attribute(ARTIFACT_TYPE_ATTRIBUTE, JAR_TYPE)
-            spec.to.attribute(ARTIFACT_TYPE_ATTRIBUTE, UNZIPPED_PAPARAZZI_NATIVE)
-        }
-
-        val configuration = configurations.create("paparazziNative")
-        configuration.isCanBeConsumed = false
-        configuration.dependencies.add(
-            dependencies.create(getLibraryByName("paparazziNative$platformSuffix"))
-        )
-
-        return configuration.incoming
-            .artifactView {
-                it.attributes.attribute(ARTIFACT_TYPE_ATTRIBUTE, UNZIPPED_PAPARAZZI_NATIVE)
-            }
-            .files
-    }
-
-    /** The golden image directory for this project. */
-    private val Project.goldenDirectory
-        get() = goldenRootDirectory.resolve(modulePath)
-
-    /** The root of the golden image directory in a standard AndroidX checkout. */
-    private val Project.goldenRootDirectory
-        get() = getSupportRootFolder().resolve("../../golden")
-
-    /** Filesystem path for this module derived from Gradle project path. */
-    private val Project.modulePath
-        get() = path.replace(':', '/').trim('/')
-
-    /** Output directory for storing reports and images. */
-    private val Test.reportDirectory: Provider<Directory>
-        get() = project.layout.buildDirectory.dir("paparazzi/$name")
-
-    /** Add a testImplementation dependency on the wrapper test utils library. */
-    private fun Project.addTestUtilsDependency() {
-        configurations["testImplementation"]
-            .dependencies
-            .add(dependencies.create(project(TEST_UTILS_PROJECT)))
-    }
-
-    private companion object {
-        /** Package name of the test library, used to namespace system properties */
-        const val PACKAGE_NAME = "androidx.testutils.paparazzi"
-
-        /** Project path to the wrapper test utils project. */
-        const val TEST_UTILS_PROJECT = ":internal-testutils-paparazzi"
-
-        /** Artifact type attribute for unzipped Paparazzi layoutlib unzipped artifacts */
-        const val UNZIPPED_PAPARAZZI_NATIVE = "unzipped-paparazzi-native"
-
-        /** Set system properties with keys prefixed with [PACKAGE_NAME] */
-        fun JavaForkOptions.prefixedSystemProperties(vararg properties: Pair<String, Any>) {
-            properties.forEach { (name, value) -> systemProperty("$PACKAGE_NAME.$name", value) }
-        }
-    }
-}
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/paparazzi/UnzipPaparazziNativeTransform.kt b/buildSrc/private/src/main/kotlin/androidx/build/paparazzi/UnzipPaparazziNativeTransform.kt
deleted file mode 100644
index 2d2c09a..0000000
--- a/buildSrc/private/src/main/kotlin/androidx/build/paparazzi/UnzipPaparazziNativeTransform.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.build.paparazzi
-
-import java.util.zip.ZipInputStream
-import org.gradle.api.artifacts.transform.InputArtifact
-import org.gradle.api.artifacts.transform.TransformAction
-import org.gradle.api.artifacts.transform.TransformOutputs
-import org.gradle.api.artifacts.transform.TransformParameters.None
-import org.gradle.api.file.FileSystemLocation
-import org.gradle.api.provider.Provider
-import org.gradle.api.tasks.PathSensitive
-import org.gradle.api.tasks.PathSensitivity
-import org.gradle.work.DisableCachingByDefault
-
-/**
- * Unzips one of Paparazzi's platform-specific layoutlib JAR artifacts so that Paparazzi can read
- * its contents at run time. These contain a native dynamic library and supporting resources
- * including ICU and fonts.
- */
-@DisableCachingByDefault(because = "Just an unzip task, faster to rerun locally")
-abstract class UnzipPaparazziNativeTransform : TransformAction<None> {
-    @get:PathSensitive(PathSensitivity.NAME_ONLY)
-    @get:InputArtifact
-    abstract val primaryInput: Provider<FileSystemLocation>
-
-    override fun transform(outputs: TransformOutputs) {
-        val inputFile = primaryInput.get().asFile
-        val outputDir = outputs.dir(inputFile.nameWithoutExtension).also { it.mkdirs() }
-
-        ZipInputStream(inputFile.inputStream().buffered()).use { zipInputStream ->
-            while (true) {
-                val entry = zipInputStream.nextEntry ?: break
-                val outputFile = outputDir.resolve(entry.name)
-
-                if (entry.isDirectory) {
-                    outputFile.mkdir()
-                } else {
-                    // This works because ZipInputStream resizes itself to the contents of the
-                    // last-returned entry
-                    outputFile.outputStream().buffered().use { zipInputStream.copyTo(it) }
-                }
-            }
-        }
-    }
-}
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/transform/ConfigureAarAsJar.kt b/buildSrc/private/src/main/kotlin/androidx/build/transform/ConfigureAarAsJar.kt
index b6c9910..877109a 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/transform/ConfigureAarAsJar.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/transform/ConfigureAarAsJar.kt
@@ -63,8 +63,6 @@
         .dependencies
         .add(project.dependencies.create(aarAsJar))
 
-    // Added to allow the :external:paparazzi:paparazzi build to select the correct jar (not get
-    // confused by the mpp jars) when the mpp builds are enabled
     project.configurations
         .getByName(testAarsAsJars.name)
         .attributes
diff --git a/buildSrc/private/src/main/resources/META-INF/gradle-plugins/AndroidXPaparazziImplPlugin.properties b/buildSrc/private/src/main/resources/META-INF/gradle-plugins/AndroidXPaparazziImplPlugin.properties
deleted file mode 100644
index 0ea8b07..0000000
--- a/buildSrc/private/src/main/resources/META-INF/gradle-plugins/AndroidXPaparazziImplPlugin.properties
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Copyright 2022 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-implementation-class=androidx.build.paparazzi.AndroidXPaparazziImplPlugin
diff --git a/buildSrc/settingsScripts/project-dependency-graph.groovy b/buildSrc/settingsScripts/project-dependency-graph.groovy
index d74e0d8..34e95d3 100644
--- a/buildSrc/settingsScripts/project-dependency-graph.groovy
+++ b/buildSrc/settingsScripts/project-dependency-graph.groovy
@@ -239,10 +239,6 @@
                     links.add(":compose:compiler:compiler")
                     links.add(":compose:lint:internal-lint-checks")
                 }
-                if (paparazziPlugin.matcher(line).find()) {
-                    links.add(":test:screenshot:screenshot-proto")
-                    links.add(":internal-testutils-paparazzi")
-                }
                 if (iconGenerator.matcher(line).find()) {
                     links.add(":compose:material:material:icons:generator")
                 }
@@ -267,7 +263,6 @@
     private static Pattern multilineProjectReference = Pattern.compile("project\\(\$")
     private static Pattern inspection = Pattern.compile("packageInspector\\(project, \"(.*)\"\\)")
     private static Pattern composePlugin = Pattern.compile("id\\(\"AndroidXComposePlugin\"\\)")
-    private static Pattern paparazziPlugin = Pattern.compile("id\\(\"AndroidXPaparazziPlugin\"\\)")
     private static Pattern iconGenerator = Pattern.compile("IconGenerationTask\\.register")
 }
 
diff --git a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraBackend.kt b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraBackend.kt
index 52325db..433564a 100644
--- a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraBackend.kt
+++ b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraBackend.kt
@@ -86,6 +86,25 @@
         return cameraController
     }
 
+    override fun prewarm(cameraId: CameraId) {
+        _cameraControllers.find { it.cameraId == cameraId }?.simulateCameraStarted()
+    }
+
+    override fun disconnect(cameraId: CameraId) {
+        _cameraControllers.find { it.cameraId == cameraId }?.simulateCameraStopped()
+    }
+
+    override fun disconnectAsync(cameraId: CameraId): Deferred<Unit> {
+        _cameraControllers.find { it.cameraId == cameraId }?.simulateCameraStopped()
+        return CompletableDeferred(Unit)
+    }
+
+    override fun disconnectAll() {
+        _cameraControllers.forEach {
+            it.simulateCameraStopped()
+        }
+    }
+
     companion object {
         val FAKE_CAMERA_BACKEND_ID =
             CameraBackendId("androidx.camera.camera2.pipe.testing.FakeCameraBackend")
diff --git a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraDevices.kt b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraDevices.kt
index 171f072..224a224 100644
--- a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraDevices.kt
+++ b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeCameraDevices.kt
@@ -17,10 +17,12 @@
 package androidx.camera.camera2.pipe.testing
 
 import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraBackend
 import androidx.camera.camera2.pipe.CameraBackendId
 import androidx.camera.camera2.pipe.CameraDevices
 import androidx.camera.camera2.pipe.CameraId
 import androidx.camera.camera2.pipe.CameraMetadata
+import kotlinx.coroutines.Deferred
 
 /**
  * This provides a fake implementation of [CameraDevices] for tests with a fixed list of Cameras.
@@ -31,10 +33,16 @@
     private val concurrentCameraBackendIds: Set<Set<CameraBackendId>>,
     private val cameraMetadataMap: Map<CameraBackendId, List<CameraMetadata>>
 ) : CameraDevices {
+    private val cameraBackends: Map<CameraBackendId, CameraBackend>
+
     init {
         check(cameraMetadataMap.containsKey(defaultCameraBackendId)) {
             "FakeCameraDevices must include $defaultCameraBackendId"
         }
+
+        cameraBackends = cameraMetadataMap.mapValues { entry ->
+            FakeCameraBackend(entry.value.associateBy { it.camera })
+        }
     }
 
     override suspend fun getCameraIds(cameraBackendId: CameraBackendId?): List<CameraId>? =
@@ -51,8 +59,8 @@
 
     override fun awaitConcurrentCameraIds(cameraBackendId: CameraBackendId?): Set<Set<CameraId>> {
         return concurrentCameraBackendIds.map { concurrentCameraIds ->
-            concurrentCameraIds.map {
-                    cameraId -> CameraId.fromCamera2Id(cameraId.value)
+            concurrentCameraIds.map { cameraId ->
+                CameraId.fromCamera2Id(cameraId.value)
             }.toSet()
         }.toSet()
     }
@@ -70,6 +78,34 @@
         return cameraMetadataMap[backendId]?.firstOrNull { it.camera == cameraId }
     }
 
+    override fun prewarm(cameraId: CameraId, cameraBackendId: CameraBackendId?) {
+        val cameraBackend = getCameraBackend(cameraBackendId)
+        cameraBackend.prewarm(cameraId)
+    }
+
+    override fun disconnect(cameraId: CameraId, cameraBackendId: CameraBackendId?) {
+        val cameraBackend = getCameraBackend(cameraBackendId)
+        cameraBackend.disconnect(cameraId)
+    }
+
+    override fun disconnectAsync(
+        cameraId: CameraId,
+        cameraBackendId: CameraBackendId?
+    ): Deferred<Unit> {
+        val cameraBackend = getCameraBackend(cameraBackendId)
+        return cameraBackend.disconnectAsync(cameraId)
+    }
+
+    override fun disconnectAll(cameraBackendId: CameraBackendId?) {
+        val cameraBackend = getCameraBackend(cameraBackendId)
+        cameraBackend.disconnectAll()
+    }
+
+    override fun disconnectAllAsync(cameraBackendId: CameraBackendId?): Deferred<Unit> {
+        val cameraBackend = getCameraBackend(cameraBackendId)
+        return cameraBackend.disconnectAllAsync()
+    }
+
     @Deprecated(
         "findAll() is not able to specify a specific CameraBackendId to query.",
         replaceWith = ReplaceWith("awaitCameraIds"),
@@ -99,4 +135,9 @@
     )
     override fun awaitMetadata(camera: CameraId): CameraMetadata =
         checkNotNull(awaitCameraMetadata(camera))
+
+    private fun getCameraBackend(cameraBackendId: CameraBackendId?): CameraBackend {
+        val backendId = cameraBackendId ?: defaultCameraBackendId
+        return checkNotNull(cameraBackends[backendId]) { "Failed to load CameraBackend $backendId" }
+    }
 }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
index 699f614..997ad8f 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraBackend.kt
@@ -128,6 +128,23 @@
         graphListener: GraphListener,
         streamGraph: StreamGraph
     ): CameraController
+
+    /** Connects and starts the underlying camera */
+    fun prewarm(cameraId: CameraId)
+
+    /** Disconnects the underlying camera.*/
+    fun disconnect(cameraId: CameraId)
+
+    /**
+     * Disconnects the underlying camera. Once the connection is closed, the returned [Deferred]
+     * should be completed.
+     */
+    fun disconnectAsync(cameraId: CameraId): Deferred<Unit>
+
+    /**
+     * Disconnects all active Cameras.
+     */
+    fun disconnectAll()
 }
 
 /**
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraDevices.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraDevices.kt
index 59c1012..76c367db 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraDevices.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/CameraDevices.kt
@@ -21,6 +21,7 @@
 
 import androidx.annotation.RequiresApi
 import androidx.annotation.RestrictTo
+import kotlinx.coroutines.Deferred
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.flow
 
@@ -76,6 +77,39 @@
     ): CameraMetadata?
 
     /**
+     * Opens the camera device indicated by the cameraId, so that any subsequent open calls will
+     * potentially have a better latency.
+     */
+    fun prewarm(cameraId: CameraId, cameraBackendId: CameraBackendId? = null)
+
+    /**
+     * Non blocking operation that disconnects the underlying active Camera.
+     */
+    fun disconnect(cameraId: CameraId, cameraBackendId: CameraBackendId? = null)
+
+    /**
+     * Disconnects the underlying active Camera. Once fully closed,
+     * the returned [Deferred] should be completed. It is synchronous with the other operations
+     * within this class.
+     */
+    fun disconnectAsync(
+        cameraId: CameraId,
+        cameraBackendId: CameraBackendId? = null
+    ): Deferred<Unit>
+
+    /**
+     * Non blocking operation that disconnects all active Cameras.
+     */
+    fun disconnectAll(cameraBackendId: CameraBackendId? = null)
+
+    /**
+     * Non blocking operation that disconnects all active Cameras. Once all connections are fully
+     * closed, the returned [Deferred] should be completed. It is synchronous with the other
+     * operations within this class.
+     */
+    fun disconnectAllAsync(cameraBackendId: CameraBackendId? = null): Deferred<Unit>
+
+    /**
      * Iterate and return a list of CameraId's on the device that are capable of being opened. Some
      * camera devices may be hidden or un-openable if they are included as part of a logical camera
      * group.
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt
index 36d8450..34e1eaa 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2Backend.kt
@@ -39,8 +39,7 @@
 /** This is the default [CameraBackend] implementation for CameraPipe based on Camera2. */
 @RequiresApi(21)
 internal class Camera2Backend
-@Inject
-constructor(
+@Inject constructor(
     private val threads: Threads,
     private val camera2DeviceCache: Camera2DeviceCache,
     private val camera2MetadataCache: Camera2MetadataCache,
@@ -65,11 +64,26 @@
     override fun awaitCameraMetadata(cameraId: CameraId): CameraMetadata =
         camera2MetadataCache.awaitCameraMetadata(cameraId)
 
+    override fun disconnect(cameraId: CameraId) {
+        virtualCameraManager.close(cameraId)
+    }
+
+    override fun disconnectAsync(cameraId: CameraId): Deferred<Unit> {
+        TODO(
+            "b/324142928 - Add support in VirtualCameraManager for closing a camera " +
+                "with a deferred result."
+        )
+    }
+
+    override fun disconnectAll() {
+        return virtualCameraManager.closeAll()
+    }
+
     override fun disconnectAllAsync(): Deferred<Unit> {
-        // TODO: VirtualCameraManager needs to be extended to support a suspendable future that can
-        //   be used to wait until close has been called on all camera devices.
-        virtualCameraManager.closeAll()
-        return CompletableDeferred(Unit)
+        TODO(
+            "b/324142928 - Add support in VirtualCameraManager for closing a camera " +
+                "with a deferred result."
+        )
     }
 
     override fun shutdownAsync(): Deferred<Unit> {
@@ -86,16 +100,17 @@
         streamGraph: StreamGraph
     ): CameraController {
         // Use Dagger to create the camera2 controller component, then create the CameraController.
-        val cameraControllerComponent =
-            camera2CameraControllerComponent
-                .camera2ControllerConfig(
-                    Camera2ControllerConfig(
-                        this, graphConfig, graphListener, streamGraph as StreamGraphImpl
-                    )
-                )
-                .build()
+        val cameraControllerComponent = camera2CameraControllerComponent.camera2ControllerConfig(
+            Camera2ControllerConfig(
+                this, graphConfig, graphListener, streamGraph as StreamGraphImpl
+            )
+        ).build()
 
         // Create and return a Camera2 CameraController object.
         return cameraControllerComponent.cameraController()
     }
+
+    override fun prewarm(cameraId: CameraId) {
+        virtualCameraManager.prewarm(cameraId)
+    }
 }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/VirtualCameraManager.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/VirtualCameraManager.kt
index 14dc332..8cf4b52 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/VirtualCameraManager.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/VirtualCameraManager.kt
@@ -27,6 +27,7 @@
 import androidx.camera.camera2.pipe.core.Threads
 import androidx.camera.camera2.pipe.core.WakeLock
 import androidx.camera.camera2.pipe.graph.GraphListener
+import androidx.camera.camera2.pipe.graph.GraphRequestProcessor
 import javax.inject.Inject
 import javax.inject.Singleton
 import kotlinx.coroutines.CoroutineName
@@ -47,11 +48,29 @@
     val isForegroundObserver: (Unit) -> Boolean,
 ) : CameraRequest()
 
+/**
+ * Sends a request to close an active camera.
+ * Note: RequestOpen() & RequestClose() may not be executed sequentially,
+ * as the camera may take a while to be fully opened, and RequestClose() might execute in parallel.
+ */
 internal data class RequestClose(val activeCamera: VirtualCameraManager.ActiveCamera) :
     CameraRequest()
 
+internal data class RequestCloseById(val activeCameraId: CameraId) :
+    CameraRequest()
+
 internal object RequestCloseAll : CameraRequest()
 
+internal object NoOpGraphListener : GraphListener {
+    override fun onGraphStarted(requestProcessor: GraphRequestProcessor) {}
+
+    override fun onGraphStopped(requestProcessor: GraphRequestProcessor) {}
+
+    override fun onGraphModified(requestProcessor: GraphRequestProcessor) {}
+
+    override fun onGraphError(graphStateError: GraphState.GraphStateError) {}
+}
+
 // A queue depth of 32 was deemed necessary in b/276051078 where a flood of requests can cause the
 // queue depth to go over 8. In the long run, we can perhaps look into refactoring and
 // reimplementing the request queue in a more robust way.
@@ -98,6 +117,16 @@
         return result
     }
 
+    /** Connects and starts the underlying camera.*/
+    internal fun prewarm(cameraId: CameraId) {
+        open(cameraId, emptyList(), NoOpGraphListener) { _ -> false }
+    }
+
+    /** Submits a request to close the underlying camera */
+    internal fun close(cameraId: CameraId) {
+        offerChecked(RequestCloseById(cameraId))
+    }
+
     internal fun closeAll() {
         if (!offerChecked(RequestCloseAll)) {
             Log.warn { "Failed to close all cameras: Close request submission failed" }
@@ -133,6 +162,23 @@
                 continue
             }
 
+            // Ensures the closure of a camera device happens after any preceding RequestOpen().
+            val closeRequestById = requests.firstOrNull()
+            if (closeRequestById != null && closeRequestById is RequestCloseById) {
+                requests.remove(closeRequestById)
+                pendingRequestOpens.removeAll {
+                    it.virtualCamera.cameraId == closeRequestById.activeCameraId
+                }
+                val activeCamera =
+                    activeCameras.firstOrNull { it.cameraId == closeRequestById.activeCameraId }
+                if (activeCamera != null) {
+                    activeCameras.remove(activeCamera)
+                    launch { activeCamera.close() }
+                    activeCamera.awaitClosed()
+                }
+                continue
+            }
+
             // If we received a closeAll request, then close every request leading up to it.
             val closeAll = requests.indexOfLast { it is RequestCloseAll }
             if (closeAll >= 0) {
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
index 0759f3e..2a143f3 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/config/ExternalCameraGraphComponent.kt
@@ -97,6 +97,22 @@
             throwUnsupportedOperationException()
         }
 
+        override fun prewarm(cameraId: CameraId) {
+            throwUnsupportedOperationException()
+        }
+
+        override fun disconnect(cameraId: CameraId) {
+            throwUnsupportedOperationException()
+        }
+
+        override fun disconnectAsync(cameraId: CameraId): Deferred<Unit> {
+            throwUnsupportedOperationException()
+        }
+
+        override fun disconnectAll() {
+            throwUnsupportedOperationException()
+        }
+
         private fun throwUnsupportedOperationException(): Nothing =
             throw UnsupportedOperationException("External CameraPipe should not use backends")
     }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraDevicesImpl.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraDevicesImpl.kt
index 6f0b2bd..d2798d6 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraDevicesImpl.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/CameraDevicesImpl.kt
@@ -27,6 +27,7 @@
 import androidx.camera.camera2.pipe.core.Log
 import javax.inject.Inject
 import javax.inject.Singleton
+import kotlinx.coroutines.Deferred
 
 /** Provides utilities for querying cameras and accessing metadata about those cameras. */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
@@ -118,6 +119,34 @@
         return metadata
     }
 
+    override fun prewarm(cameraId: CameraId, cameraBackendId: CameraBackendId?) {
+        val cameraBackend = getCameraBackend(cameraBackendId)
+        cameraBackend.prewarm(cameraId)
+    }
+
+    override fun disconnect(cameraId: CameraId, cameraBackendId: CameraBackendId?) {
+        val cameraBackend = getCameraBackend(cameraBackendId)
+        cameraBackend.disconnect(cameraId)
+    }
+
+    override fun disconnectAsync(
+        cameraId: CameraId,
+        cameraBackendId: CameraBackendId?
+    ): Deferred<Unit> {
+        val cameraBackend = getCameraBackend(cameraBackendId)
+        return cameraBackend.disconnectAsync(cameraId)
+    }
+
+    override fun disconnectAll(cameraBackendId: CameraBackendId?) {
+        val cameraBackend = getCameraBackend(cameraBackendId)
+        cameraBackend.disconnectAll()
+    }
+
+    override fun disconnectAllAsync(cameraBackendId: CameraBackendId?): Deferred<Unit> {
+        val cameraBackend = getCameraBackend(cameraBackendId)
+        return cameraBackend.disconnectAllAsync()
+    }
+
     private fun getCameraBackend(cameraBackendId: CameraBackendId?): CameraBackend =
         Debug.trace("getCameraBackend") {
             val actualBackendId = cameraBackendId ?: cameraBackends.default.id
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/OutputDistributor.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/OutputDistributor.kt
index 91c4338..4d24319 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/OutputDistributor.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/internal/OutputDistributor.kt
@@ -148,14 +148,9 @@
             val isOutOfOrder = isFrameNumberOutOfOrder || isOutputNumberOutOfOrder
 
             // onOutputStarted should only be invoked once. Check to see that there are no other
-            // duplicate events.
-            check(
-                !startedOutputs.any {
-                    it.cameraFrameNumber == cameraFrameNumber ||
-                        it.cameraTimestamp == cameraTimestamp ||
-                        it.outputNumber == outputNumber
-                }
-            ) {
+            // duplicate events. Note that on some platforms, non-compliant camera HALs may return
+            // frames with identical frame numbers and output numbers. See b/324320062 for context.
+            check(!startedOutputs.any { it.cameraFrameNumber == cameraFrameNumber }) {
                 "onOutputStarted was invoked multiple times with a previously started output!" +
                     "onOutputStarted with $cameraFrameNumber, $cameraTimestamp, $outputNumber. " +
                     "Previously started outputs: $startedOutputs"
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/internal/OutputDistributorTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/internal/OutputDistributorTest.kt
index 42bf6cc..3386f26 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/internal/OutputDistributorTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/internal/OutputDistributorTest.kt
@@ -22,7 +22,10 @@
 import androidx.camera.camera2.pipe.OutputStatus
 import androidx.camera.camera2.pipe.internal.OutputDistributor.OutputListener
 import androidx.camera.camera2.pipe.media.Finalizer
+import androidx.testutils.assertThrows
 import com.google.common.truth.Truth.assertThat
+import junit.framework.TestCase.assertFalse
+import junit.framework.TestCase.assertTrue
 import kotlinx.atomicfu.atomic
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -447,6 +450,57 @@
         assertThat(pendingOutput1.outputStatus).isEqualTo(OutputStatus.ERROR_OUTPUT_FAILED)
     }
 
+    @Test
+    fun outputDistributorThrowsOnIdenticalFrameNumber() {
+        val pendingOutput1 =
+            PendingOutput(FrameNumber(1), CameraTimestamp(11), outputNumber = 101)
+        val pendingOutput2 =
+            PendingOutput(FrameNumber(1), CameraTimestamp(12), outputNumber = 102)
+        outputDistributor.startWith(pendingOutput1)
+
+        assertThrows<IllegalStateException> {
+            outputDistributor.startWith(pendingOutput2)
+        }
+    }
+
+    @Test
+    fun pendingOutputCompletesOnIdenticalTimestamps() {
+        val pendingOutput1 =
+            PendingOutput(FrameNumber(1), CameraTimestamp(11), outputNumber = 101)
+        val pendingOutput2 =
+            PendingOutput(FrameNumber(2), CameraTimestamp(11), outputNumber = 102)
+        outputDistributor.startWith(pendingOutput1)
+        outputDistributor.startWith(pendingOutput2)
+
+        outputDistributor.onOutputResult(fakeOutput1.outputNumber, OutputResult.from(fakeOutput1))
+        assertTrue(pendingOutput1.isComplete)
+        assertFalse(pendingOutput2.isComplete)
+
+        outputDistributor.onOutputResult(fakeOutput2.outputNumber, OutputResult.from(fakeOutput2))
+        assertTrue(pendingOutput1.isComplete)
+        assertTrue(pendingOutput2.isComplete)
+    }
+
+    @Test
+    fun pendingOutputCompletesOnIdenticalOutputNumbers() {
+        val pendingOutput1 =
+            PendingOutput(FrameNumber(1), CameraTimestamp(11), outputNumber = 101)
+        val pendingOutput2 =
+            PendingOutput(FrameNumber(2), CameraTimestamp(12), outputNumber = 101)
+        outputDistributor.startWith(pendingOutput1)
+        outputDistributor.startWith(pendingOutput2)
+
+        val fakeOutput1 = FakeOutput(101)
+        outputDistributor.onOutputResult(fakeOutput1.outputNumber, OutputResult.from(fakeOutput1))
+        assertTrue(pendingOutput1.isComplete)
+        assertFalse(pendingOutput2.isComplete)
+
+        val fakeOutput2 = FakeOutput(101)
+        outputDistributor.onOutputResult(fakeOutput2.outputNumber, OutputResult.from(fakeOutput2))
+        assertTrue(pendingOutput1.isComplete)
+        assertTrue(pendingOutput2.isComplete)
+    }
+
     /**
      * Utility class that implements [OutputListener] and can be used to observe when an
      * output is complete and the callback is invoked.
diff --git a/camera/integration-tests/uiwidgetstestapp/build.gradle b/camera/integration-tests/uiwidgetstestapp/build.gradle
index 98a7d6a..1e7bafb5 100644
--- a/camera/integration-tests/uiwidgetstestapp/build.gradle
+++ b/camera/integration-tests/uiwidgetstestapp/build.gradle
@@ -60,7 +60,6 @@
 }
 
 dependencies {
-
     // Internal library
     implementation(libs.kotlinStdlib)
     implementation(project(":camera:camera-core"))
@@ -70,7 +69,7 @@
     implementation(project(":camera:camera-view"))
     implementation(project(":camera:camera-video"))
     implementation(project(":camera:camera-mlkit-vision"))
-    implementation 'com.google.mlkit:barcode-scanning:17.0.2'
+    implementation("com.google.mlkit:barcode-scanning:17.0.2")
 
     // Android Support Library
     implementation("androidx.appcompat:appcompat:1.2.0")
@@ -88,15 +87,14 @@
     implementation(libs.guavaAndroid)
 
     // Compose
-    implementation 'androidx.activity:activity-compose:1.4.0'
-    implementation project(':compose:material:material')
-    implementation 'androidx.compose.animation:animation:1.4.0'
-    implementation 'androidx.compose.runtime:runtime:1.4.0'
-    implementation 'androidx.compose.ui:ui-tooling:1.4.0'
-    implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.4.1'
-    implementation 'androidx.navigation:navigation-compose:2.4.2'
-    implementation 'androidx.compose.material:material-icons-extended:1.4.0'
-    androidTestImplementation 'androidx.compose.ui:ui-test-junit4:1.1.1'
+    implementation("androidx.activity:activity-compose:1.4.0")
+    implementation(project(":compose:material:material"))
+    implementation("androidx.compose.animation:animation:1.4.0")
+    implementation("androidx.compose.runtime:runtime:1.4.0")
+    implementation("androidx.compose.ui:ui-tooling:1.4.0")
+    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.4.1")
+    implementation("androidx.navigation:navigation-compose:2.4.2")
+    implementation("androidx.compose.material:material-icons-extended:1.4.0")
 
     // Align dependencies in debugRuntimeClasspath and debugAndroidTestRuntimeClasspath.
     androidTestImplementation("androidx.annotation:annotation-experimental:1.4.0")
@@ -125,16 +123,14 @@
 
     // Testing for Compose
     // Test rules and transitive dependencies:
-    androidTestImplementation(project(":compose:ui:ui-test-junit4"))
-    androidTestImplementation(project(":compose:runtime:runtime"))
     androidTestImplementation(project(":compose:ui:ui"))
-    androidTestImplementation(project(":compose:runtime:runtime-saveable"))
     androidTestImplementation(project(":compose:ui:ui-geometry"))
     androidTestImplementation(project(":compose:ui:ui-util"))
     androidTestImplementation(project(":compose:ui:ui-graphics"))
     androidTestImplementation(project(":compose:ui:ui-unit"))
     androidTestImplementation(project(":compose:ui:ui-text"))
+    androidTestImplementation(project(":compose:ui:ui-test-junit4"))
     androidTestImplementation("androidx.collection:collection:1.4.0")
     // Needed for createComposeRule, but not createAndroidComposeRule:
-    debugImplementation(project(":compose:ui:ui-test-manifest"))
+    debugImplementation("androidx.compose.ui:ui-test-manifest:1.6.0")
 }
diff --git a/cardview/cardview/lint-baseline.xml b/cardview/cardview/lint-baseline.xml
deleted file mode 100644
index cc40871..0000000
--- a/cardview/cardview/lint-baseline.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-alpha10" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-alpha10)" variant="all" version="8.3.0-alpha10">
-
-    <issue
-        id="NewApi"
-        message="Class requires API level 21 (current min is 19): `CardViewApi21Impl`"
-        errorLine1="        if (!(IMPL instanceof CardViewApi21Impl)) {"
-        errorLine2="                              ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/cardview/widget/CardView.java"/>
-    </issue>
-
-</issues>
diff --git a/compose/animation/animation-core/build.gradle b/compose/animation/animation-core/build.gradle
index c175361..fbc84ec 100644
--- a/compose/animation/animation-core/build.gradle
+++ b/compose/animation/animation-core/build.gradle
@@ -40,9 +40,10 @@
     sourceSets {
         commonMain {
             dependencies {
-                implementation(project(":compose:runtime:runtime"))
-                implementation(project(":compose:ui:ui"))
-                implementation(project(":compose:ui:ui-unit"))
+                implementation("androidx.compose.runtime:runtime:1.6.0")
+                implementation("androidx.compose.ui:ui:1.6.0")
+                implementation("androidx.compose.ui:ui-unit:1.6.0")
+                implementation(project(":compose:ui:ui-graphics"))
                 implementation(project(":compose:ui:ui-util"))
                 implementation("androidx.collection:collection:1.4.0")
                 implementation(libs.kotlinStdlibCommon)
@@ -75,11 +76,6 @@
         desktopMain {
             dependsOn(jvmMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
-                implementation(project(":compose:runtime:runtime"))
-                implementation(project(":compose:ui:ui"))
-                implementation(project(":compose:ui:ui-unit"))
-                implementation(project(":compose:ui:ui-util"))
             }
         }
 
diff --git a/compose/animation/animation-core/lint-baseline.xml b/compose/animation/animation-core/lint-baseline.xml
index f95935a..9b328d7 100644
--- a/compose/animation/animation-core/lint-baseline.xml
+++ b/compose/animation/animation-core/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="BanSuppressTag"
@@ -76,17 +76,8 @@
     <issue
         id="PrimitiveInCollection"
         message="constructor VectorizedKeyframesSpec has parameter keyframes with type Map&lt;Integer, ? extends Pair&lt;? extends V, ? extends Easing>>: replace with IntObjectMap"
-        errorLine1="    private val keyframes: Map&lt;Int, Pair&lt;V, Easing>>,"
-        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/animation/core/VectorizedAnimationSpec.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="field keyframes with type Map&lt;Integer, Pair&lt;V, Easing>>: replace with IntObjectMap"
-        errorLine1="    private val keyframes: Map&lt;Int, Pair&lt;V, Easing>>,"
-        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="        keyframes: Map&lt;Int, Pair&lt;V, Easing>>,"
+        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="src/commonMain/kotlin/androidx/compose/animation/core/VectorizedAnimationSpec.kt"/>
     </issue>
diff --git a/compose/animation/animation-core/samples/build.gradle b/compose/animation/animation-core/samples/build.gradle
index dc3cfcbd..f566a97 100644
--- a/compose/animation/animation-core/samples/build.gradle
+++ b/compose/animation/animation-core/samples/build.gradle
@@ -36,7 +36,7 @@
     implementation(project(":compose:animation:animation"))
     implementation(project(":compose:animation:animation-core"))
     implementation(project(":compose:runtime:runtime"))
-    implementation("androidx.compose.ui:ui:1.2.1")
+    implementation(project(":compose:ui:ui"))
     implementation("androidx.compose.ui:ui-unit:1.2.1")
     implementation("androidx.compose.foundation:foundation:1.2.1")
     implementation("androidx.compose.foundation:foundation-layout:1.2.1")
diff --git a/compose/animation/animation-graphics/build.gradle b/compose/animation/animation-graphics/build.gradle
index 582509b..150d58b 100644
--- a/compose/animation/animation-graphics/build.gradle
+++ b/compose/animation/animation-graphics/build.gradle
@@ -42,13 +42,12 @@
                 implementation(libs.kotlinStdlibCommon)
 
                 api(project(":compose:animation:animation"))
-                api(project(":compose:foundation:foundation-layout"))
-                api(project(":compose:runtime:runtime"))
-                api(project(":compose:ui:ui"))
-                api(project(":compose:ui:ui-geometry"))
+                api("androidx.compose.foundation:foundation-layout:1.6.0")
+                api("androidx.compose.runtime:runtime:1.6.0")
+                api("androidx.compose.ui:ui:1.6.0")
+                api("androidx.compose.ui:ui-geometry:1.6.0")
 
                 implementation(project(":compose:ui:ui-util"))
-
                 implementation("androidx.collection:collection:1.4.0")
             }
         }
@@ -69,7 +68,6 @@
             }
         }
 
-
         androidMain {
             dependsOn(jvmMain)
             dependencies {
@@ -80,11 +78,6 @@
             dependsOn(jvmMain)
             dependencies {
                 implementation(libs.kotlinStdlib)
-                api(project(":compose:foundation:foundation-layout"))
-                api(project(":compose:runtime:runtime"))
-                api(project(":compose:ui:ui"))
-                api(project(":compose:ui:ui-geometry"))
-                implementation(project(":compose:ui:ui-util"))
             }
         }
 
diff --git a/compose/animation/animation/build.gradle b/compose/animation/animation/build.gradle
index 6a28b1d..f8204bf 100644
--- a/compose/animation/animation/build.gradle
+++ b/compose/animation/animation/build.gradle
@@ -42,10 +42,10 @@
                 implementation(libs.kotlinStdlibCommon)
 
                 api(project(":compose:animation:animation-core"))
-                api(project(":compose:foundation:foundation-layout"))
-                api(project(":compose:runtime:runtime"))
-                api(project(":compose:ui:ui"))
-                api(project(":compose:ui:ui-geometry"))
+                api("androidx.compose.foundation:foundation-layout:1.6.0")
+                api("androidx.compose.runtime:runtime:1.6.0")
+                api("androidx.compose.ui:ui:1.6.0")
+                api("androidx.compose.ui:ui-geometry:1.6.0")
 
                 implementation(project(":compose:ui:ui-util"))
 
@@ -77,13 +77,6 @@
             dependsOn(jvmMain)
             dependencies {
                 implementation(libs.kotlinStdlib)
-
-                api(project(":compose:foundation:foundation-layout"))
-                api(project(":compose:runtime:runtime"))
-                api(project(":compose:ui:ui"))
-                api(project(":compose:ui:ui-geometry"))
-
-                implementation(project(":compose:ui:ui-util"))
             }
         }
 
diff --git a/compose/animation/animation/integration-tests/animation-demos/lint-baseline.xml b/compose/animation/animation/integration-tests/animation-demos/lint-baseline.xml
index b3839ca..c1d1294 100644
--- a/compose/animation/animation/integration-tests/animation-demos/lint-baseline.xml
+++ b/compose/animation/animation/integration-tests/animation-demos/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="PrimitiveInCollection"
@@ -39,24 +39,6 @@
 
     <issue
         id="PrimitiveInCollection"
-        message="variable sizeMap with type Map&lt;T, IntSize>: replace with ObjectLongMap"
-        errorLine1="    val sizeMap = remember { mutableMapOf&lt;T, IntSize>() }"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/animation/demos/lookahead/CraneDemo.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="variable offsetMap with type Map&lt;T, Offset>: replace with ObjectLongMap"
-        errorLine1="    val offsetMap = remember { mutableMapOf&lt;T, Offset>() }"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/animation/demos/lookahead/CraneDemo.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
         message="field colors with type List&lt;Color>: replace with LongList"
         errorLine1="private val colors = listOf("
         errorLine2="^">
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/jvmTest/kotlin/androidx/compose/compiler/plugins/kotlin/AbstractIrTransformTest.kt b/compose/compiler/compiler-hosted/integration-tests/src/jvmTest/kotlin/androidx/compose/compiler/plugins/kotlin/AbstractIrTransformTest.kt
index 7e19a0f..3ba1cac 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/jvmTest/kotlin/androidx/compose/compiler/plugins/kotlin/AbstractIrTransformTest.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/jvmTest/kotlin/androidx/compose/compiler/plugins/kotlin/AbstractIrTransformTest.kt
@@ -123,7 +123,8 @@
             // replace source keys for start group calls
             .replace(
                 Regex(
-                    "(%composer\\.start(Restart|Movable|Replaceable)Group\\()-?((0b)?[-\\d]+)"
+                    "(%composer\\.start(Restart|Movable|Replaceable|Replace)" +
+                        "Group\\()-?((0b)?[-\\d]+)"
                 )
             ) {
                 val stringKey = it.groupValues[3]
@@ -162,7 +163,7 @@
             // replace source information with source it references
             .replace(
                 Regex(
-                    "(%composer\\.start(Restart|Movable|Replaceable)Group\\" +
+                    "(%composer\\.start(Restart|Movable|Replaceable|Replace)Group\\" +
                         "([^\"\\n]*)\"(.*)\"\\)"
                 )
             ) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/composableLocalFunctionInsideLocalClass\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/composableLocalFunctionInsideLocalClass\133useFir = false\135.txt"
index a1a28e8..07aa131 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/composableLocalFunctionInsideLocalClass\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/composableLocalFunctionInsideLocalClass\133useFir = false\135.txt"
@@ -26,7 +26,7 @@
   object : C {
     @Composable
     override fun Render(%composer: Composer?, %changed: Int) {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C(Render)<B()>:Test.kt")
       if (isTraceInProgress()) {
         traceEventStart(<>, %changed, -1, <>)
@@ -48,7 +48,7 @@
       if (isTraceInProgress()) {
         traceEventEnd()
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
   }
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/composableLocalFunctionInsideLocalClass\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/composableLocalFunctionInsideLocalClass\133useFir = true\135.txt"
index a1a28e8..07aa131 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/composableLocalFunctionInsideLocalClass\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/composableLocalFunctionInsideLocalClass\133useFir = true\135.txt"
@@ -26,7 +26,7 @@
   object : C {
     @Composable
     override fun Render(%composer: Composer?, %changed: Int) {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C(Render)<B()>:Test.kt")
       if (isTraceInProgress()) {
         traceEventStart(<>, %changed, -1, <>)
@@ -48,7 +48,7 @@
       if (isTraceInProgress()) {
         traceEventEnd()
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
   }
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/testAbstractComposable\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/testAbstractComposable\133useFir = false\135.txt"
index c95de31..3975f63 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/testAbstractComposable\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/testAbstractComposable\133useFir = false\135.txt"
@@ -41,7 +41,7 @@
   @NonRestartableComposable
   @Composable
   override fun bar(%composer: Composer?, %changed: Int) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "C(bar):Test.kt#2487m")
     if (isTraceInProgress()) {
       traceEventStart(<>, %changed, -1, <>)
@@ -49,7 +49,7 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
   static val %stable: Int = 0
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/testAbstractComposable\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/testAbstractComposable\133useFir = true\135.txt"
index c95de31..3975f63 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/testAbstractComposable\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ComposerParamTransformTests/testAbstractComposable\133useFir = true\135.txt"
@@ -41,7 +41,7 @@
   @NonRestartableComposable
   @Composable
   override fun bar(%composer: Composer?, %changed: Int) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "C(bar):Test.kt#2487m")
     if (isTraceInProgress()) {
       traceEventStart(<>, %changed, -1, <>)
@@ -49,7 +49,7 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
   static val %stable: Int = 0
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ContextReceiversTransformTests/testContextReceiversNestedWith\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ContextReceiversTransformTests/testContextReceiversNestedWith\133useFir = false\135.txt"
index 65f9106..a65bb12 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ContextReceiversTransformTests/testContextReceiversNestedWith\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ContextReceiversTransformTests/testContextReceiversNestedWith\133useFir = false\135.txt"
@@ -33,12 +33,12 @@
     }
     with(foo) {
       A(%this%with, %composer, 0)
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "*<B()>")
       with(Bar()) {
         B(%this%with, %this%with, %composer, 0)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     if (isTraceInProgress()) {
       traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ContextReceiversTransformTests/testContextReceiversNestedWith\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ContextReceiversTransformTests/testContextReceiversNestedWith\133useFir = true\135.txt"
index 65f9106..a65bb12 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ContextReceiversTransformTests/testContextReceiversNestedWith\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ContextReceiversTransformTests/testContextReceiversNestedWith\133useFir = true\135.txt"
@@ -33,12 +33,12 @@
     }
     with(foo) {
       A(%this%with, %composer, 0)
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "*<B()>")
       with(Bar()) {
         B(%this%with, %this%with, %composer, 0)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     if (isTraceInProgress()) {
       traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testAND\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testAND\133useFir = false\135.txt"
index f051992..87b3736 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testAND\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testAND\133useFir = false\135.txt"
@@ -25,10 +25,10 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<B()>,<B()>")
   val tmp0_group = B(%composer, 0) && B(%composer, 0)
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   tmp0_group
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testAND\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testAND\133useFir = true\135.txt"
index f051992..87b3736 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testAND\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testAND\133useFir = true\135.txt"
@@ -25,10 +25,10 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<B()>,<B()>")
   val tmp0_group = B(%composer, 0) && B(%composer, 0)
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   tmp0_group
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsAfter\133useFir = false\135.txt"
index d400019..b3459ca 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsAfter\133useFir = false\135.txt"
@@ -30,7 +30,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(i)>")
   while (items.hasNext()) {
     val i = items.next()
@@ -39,7 +39,7 @@
     }
     P(i, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsAfter\133useFir = true\135.txt"
index d400019..b3459ca 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsAfter\133useFir = true\135.txt"
@@ -30,7 +30,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(i)>")
   while (items.hasNext()) {
     val i = items.next()
@@ -39,7 +39,7 @@
     }
     P(i, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfterAndCallAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfterAndCallAfter\133useFir = false\135.txt"
index 0945fc9..2547f95 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfterAndCallAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfterAndCallAfter\133useFir = false\135.txt"
@@ -33,7 +33,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(i)>,<P(i)>")
   while (items.hasNext()) {
     val i = items.next()
@@ -43,7 +43,7 @@
     }
     P(i, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfterAndCallAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfterAndCallAfter\133useFir = true\135.txt"
index 0945fc9..2547f95 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfterAndCallAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfterAndCallAfter\133useFir = true\135.txt"
@@ -33,7 +33,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(i)>,<P(i)>")
   while (items.hasNext()) {
     val i = items.next()
@@ -43,7 +43,7 @@
     }
     P(i, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfter\133useFir = false\135.txt"
index bc9a8a3..3b2d8d9 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfter\133useFir = false\135.txt"
@@ -33,7 +33,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(i)>,<P(j)>")
   while (items.hasNext()) {
     val i = items.next()
@@ -44,7 +44,7 @@
     }
     P(j, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfter\133useFir = true\135.txt"
index bc9a8a3..3b2d8d9 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBeforeAndAfter\133useFir = true\135.txt"
@@ -33,7 +33,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(i)>,<P(j)>")
   while (items.hasNext()) {
     val i = items.next()
@@ -44,7 +44,7 @@
     }
     P(j, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBefore\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBefore\133useFir = false\135.txt"
index 3efd13f..b2d254e 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBefore\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBefore\133useFir = false\135.txt"
@@ -30,7 +30,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(i)>")
   while (items.hasNext()) {
     val i = items.next()
@@ -39,7 +39,7 @@
       break
     }
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBefore\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBefore\133useFir = true\135.txt"
index 3efd13f..b2d254e 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBefore\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testBreakWithCallsBefore\133useFir = true\135.txt"
@@ -30,7 +30,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(i)>")
   while (items.hasNext()) {
     val i = items.next()
@@ -39,7 +39,7 @@
       break
     }
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testComposableInAnonymousObjectDelegate\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testComposableInAnonymousObjectDelegate\133useFir = false\135.txt"
index 99f3e5e..aee5bdf 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testComposableInAnonymousObjectDelegate\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testComposableInAnonymousObjectDelegate\133useFir = false\135.txt"
@@ -24,7 +24,7 @@
   val property: A
     @Composable @JvmName(name = "getProperty")
     get() {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C:Test.kt")
       if (isTraceInProgress()) {
         traceEventStart(<>, %changed, -1, <>)
@@ -33,7 +33,7 @@
       if (isTraceInProgress()) {
         traceEventEnd()
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
 }
 @Composable
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testComposableInAnonymousObjectDelegate\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testComposableInAnonymousObjectDelegate\133useFir = true\135.txt"
index 99f3e5e..aee5bdf 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testComposableInAnonymousObjectDelegate\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testComposableInAnonymousObjectDelegate\133useFir = true\135.txt"
@@ -24,7 +24,7 @@
   val property: A
     @Composable @JvmName(name = "getProperty")
     get() {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C:Test.kt")
       if (isTraceInProgress()) {
         traceEventStart(<>, %changed, -1, <>)
@@ -33,7 +33,7 @@
       if (isTraceInProgress()) {
         traceEventEnd()
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
 }
 @Composable
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsAfter\133useFir = false\135.txt"
index aca099e..7f0f74b 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsAfter\133useFir = false\135.txt"
@@ -30,20 +30,20 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   while (items.hasNext()) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<P(i)>")
     val i = items.next()
     if (i == 0) {
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       continue
     }
     P(i, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsAfter\133useFir = true\135.txt"
index aca099e..7f0f74b 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsAfter\133useFir = true\135.txt"
@@ -30,20 +30,20 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   while (items.hasNext()) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<P(i)>")
     val i = items.next()
     if (i == 0) {
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       continue
     }
     P(i, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBeforeAndAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBeforeAndAfter\133useFir = false\135.txt"
index ee4b2ed..a679ce7 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBeforeAndAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBeforeAndAfter\133useFir = false\135.txt"
@@ -31,21 +31,21 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   while (items.hasNext()) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<P(i)>,<P(i)>")
     val i = items.next()
     P(i, %composer, 0)
     if (i == 0) {
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       continue
     }
     P(i, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBeforeAndAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBeforeAndAfter\133useFir = true\135.txt"
index ee4b2ed..a679ce7 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBeforeAndAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBeforeAndAfter\133useFir = true\135.txt"
@@ -31,21 +31,21 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   while (items.hasNext()) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<P(i)>,<P(i)>")
     val i = items.next()
     P(i, %composer, 0)
     if (i == 0) {
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       continue
     }
     P(i, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBefore\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBefore\133useFir = false\135.txt"
index 867c78d..2525fd7 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBefore\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBefore\133useFir = false\135.txt"
@@ -31,21 +31,21 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   while (items.hasNext()) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<P(i)>")
     val i = items.next()
     P(i, %composer, 0)
     if (i == 0) {
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       continue
     }
     print(i)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBefore\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBefore\133useFir = true\135.txt"
index 867c78d..2525fd7 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBefore\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testContinueWithCallsBefore\133useFir = true\135.txt"
@@ -31,21 +31,21 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   while (items.hasNext()) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<P(i)>")
     val i = items.next()
     P(i, %composer, 0)
     if (i == 0) {
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       continue
     }
     print(i)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testDynamicWrappingGroupWithReturnValue\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testDynamicWrappingGroupWithReturnValue\133useFir = false\135.txt"
index 335a543..8f91499 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testDynamicWrappingGroupWithReturnValue\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testDynamicWrappingGroupWithReturnValue\133useFir = false\135.txt"
@@ -29,23 +29,23 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   val tmp0 = <block>{
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "")
     val tmp4_group = if (x > 0) {
-      val tmp3_group = if (%composer.startReplaceableGroup(<>)
+      val tmp3_group = if (%composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<B()>")
       val tmp1_group = B(%composer, 0)
-      %composer.endReplaceableGroup()
-      tmp1_group) 1 else if (%composer.startReplaceableGroup(<>)
+      %composer.endReplaceGroup()
+      tmp1_group) 1 else if (%composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<B()>")
       val tmp2_group = B(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       tmp2_group) 2 else 3
       tmp3_group
     } else {
       4
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp4_group
   }
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testDynamicWrappingGroupWithReturnValue\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testDynamicWrappingGroupWithReturnValue\133useFir = true\135.txt"
index 335a543..8f91499 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testDynamicWrappingGroupWithReturnValue\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testDynamicWrappingGroupWithReturnValue\133useFir = true\135.txt"
@@ -29,23 +29,23 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   val tmp0 = <block>{
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "")
     val tmp4_group = if (x > 0) {
-      val tmp3_group = if (%composer.startReplaceableGroup(<>)
+      val tmp3_group = if (%composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<B()>")
       val tmp1_group = B(%composer, 0)
-      %composer.endReplaceableGroup()
-      tmp1_group) 1 else if (%composer.startReplaceableGroup(<>)
+      %composer.endReplaceGroup()
+      tmp1_group) 1 else if (%composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<B()>")
       val tmp2_group = B(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       tmp2_group) 2 else 3
       tmp3_group
     } else {
       4
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp4_group
   }
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnCallValue\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnCallValue\133useFir = false\135.txt"
index a8106b9..78cdf3e 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnCallValue\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnCallValue\133useFir = false\135.txt"
@@ -23,27 +23,27 @@
 @NonRestartableComposable
 @Composable
 fun Example(x: Int, %composer: Composer?, %changed: Int): Int {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)<R()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<R()>")
   if (x > 0) {
     val tmp1_return = R(%composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp1_return
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   val tmp0 = R(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   return tmp0
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnCallValue\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnCallValue\133useFir = true\135.txt"
index a8106b9..78cdf3e 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnCallValue\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnCallValue\133useFir = true\135.txt"
@@ -23,27 +23,27 @@
 @NonRestartableComposable
 @Composable
 fun Example(x: Int, %composer: Composer?, %changed: Int): Int {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)<R()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<R()>")
   if (x > 0) {
     val tmp1_return = R(%composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp1_return
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   val tmp0 = R(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   return tmp0
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromCrossInlinedLambda\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromCrossInlinedLambda\133useFir = false\135.txt"
index 6eb97a7..9874dcf 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromCrossInlinedLambda\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromCrossInlinedLambda\133useFir = false\135.txt"
@@ -29,12 +29,12 @@
     }
     Dialog({ %composer: Composer?, %changed: Int ->
       sourceInformationMarkerStart(%composer, <>, "C:Test.kt")
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<Test(p...>")
       if (false) {
         Test(param, %composer, 0b1110 and %dirty)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       sourceInformationMarkerEnd(%composer)
     }, %composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromCrossInlinedLambda\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromCrossInlinedLambda\133useFir = true\135.txt"
index 6eb97a7..9874dcf 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromCrossInlinedLambda\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromCrossInlinedLambda\133useFir = true\135.txt"
@@ -29,12 +29,12 @@
     }
     Dialog({ %composer: Composer?, %changed: Int ->
       sourceInformationMarkerStart(%composer, <>, "C:Test.kt")
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<Test(p...>")
       if (false) {
         Test(param, %composer, 0b1110 and %dirty)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       sourceInformationMarkerEnd(%composer)
     }, %composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromWhenStatement\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromWhenStatement\133useFir = false\135.txt"
index af9595d..2711f11 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromWhenStatement\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromWhenStatement\133useFir = false\135.txt"
@@ -38,10 +38,10 @@
     val tmp0_subject = state.value
     when {
       tmp0_subject == true -> {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<Text(t...>")
         val tmp1_return = Text("true", %composer, 0b0110)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         if (isTraceInProgress()) {
           traceEventEnd()
         }
@@ -51,10 +51,10 @@
         return tmp1_return
       }
       else -> {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<Text(t...>")
         Text("false", %composer, 0b0110)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
       }
     }
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromWhenStatement\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromWhenStatement\133useFir = true\135.txt"
index af9595d..2711f11 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromWhenStatement\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnFromWhenStatement\133useFir = true\135.txt"
@@ -38,10 +38,10 @@
     val tmp0_subject = state.value
     when {
       tmp0_subject == true -> {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<Text(t...>")
         val tmp1_return = Text("true", %composer, 0b0110)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         if (isTraceInProgress()) {
           traceEventEnd()
         }
@@ -51,10 +51,10 @@
         return tmp1_return
       }
       else -> {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<Text(t...>")
         Text("false", %composer, 0b0110)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
       }
     }
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValueWithCallsAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValueWithCallsAfter\133useFir = false\135.txt"
index 6d045c2..3466566 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValueWithCallsAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValueWithCallsAfter\133useFir = false\135.txt"
@@ -24,7 +24,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(x: Int, %composer: Composer?, %changed: Int): Int {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -34,7 +34,7 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp1_return
   }
   A(%composer, 0)
@@ -42,6 +42,6 @@
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   return tmp0
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValueWithCallsAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValueWithCallsAfter\133useFir = true\135.txt"
index 6d045c2..3466566 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValueWithCallsAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValueWithCallsAfter\133useFir = true\135.txt"
@@ -24,7 +24,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(x: Int, %composer: Composer?, %changed: Int): Int {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -34,7 +34,7 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp1_return
   }
   A(%composer, 0)
@@ -42,6 +42,6 @@
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   return tmp0
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValue\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValue\133useFir = false\135.txt"
index 904ae2a..06474c2 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValue\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValue\133useFir = false\135.txt"
@@ -24,7 +24,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(x: Int, %composer: Composer?, %changed: Int): Int {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -35,13 +35,13 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp1_return
   }
   val tmp0 = 2
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   return tmp0
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValue\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValue\133useFir = true\135.txt"
index 904ae2a..06474c2 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValue\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnValue\133useFir = true\135.txt"
@@ -24,7 +24,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(x: Int, %composer: Composer?, %changed: Int): Int {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -35,13 +35,13 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp1_return
   }
   val tmp0 = 2
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   return tmp0
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsAfterButNotBefore\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsAfterButNotBefore\133useFir = false\135.txt"
index 66cec40..aa2146c 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsAfterButNotBefore\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsAfterButNotBefore\133useFir = false\135.txt"
@@ -24,7 +24,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(x: Int, %composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -33,12 +33,12 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return
   }
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsAfterButNotBefore\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsAfterButNotBefore\133useFir = true\135.txt"
index 66cec40..aa2146c 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsAfterButNotBefore\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsAfterButNotBefore\133useFir = true\135.txt"
@@ -24,7 +24,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(x: Int, %composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -33,12 +33,12 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return
   }
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsBeforeButNotAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsBeforeButNotAfter\133useFir = false\135.txt"
index e698b4b..4d0b5f4 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsBeforeButNotAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsBeforeButNotAfter\133useFir = false\135.txt"
@@ -25,7 +25,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(x: Int, %composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -35,12 +35,12 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return
   }
   print("hello")
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsBeforeButNotAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsBeforeButNotAfter\133useFir = true\135.txt"
index e698b4b..4d0b5f4 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsBeforeButNotAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEarlyReturnWithCallsBeforeButNotAfter\133useFir = true\135.txt"
@@ -25,7 +25,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(x: Int, %composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -35,12 +35,12 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return
   }
   print("hello")
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testElvis\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testElvis\133useFir = false\135.txt"
index 6b3b281..da5c0d3 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testElvis\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testElvis\133useFir = false\135.txt"
@@ -29,7 +29,7 @@
   }
   val y = <block>{
     val <elvis> = x
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<R()>")
     val tmp0_group = when {
       <elvis> == null -> {
@@ -39,7 +39,7 @@
         <elvis>
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp0_group
   }
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testElvis\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testElvis\133useFir = true\135.txt"
index 6b3b281..da5c0d3 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testElvis\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testElvis\133useFir = true\135.txt"
@@ -29,7 +29,7 @@
   }
   val y = <block>{
     val <elvis> = x
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<R()>")
     val tmp0_group = when {
       <elvis> == null -> {
@@ -39,7 +39,7 @@
         <elvis>
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp0_group
   }
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureEarlyExitInInline_Labeled\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureEarlyExitInInline_Labeled\133useFir = false\135.txt"
index abf76e6..33fa453 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureEarlyExitInInline_Labeled\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureEarlyExitInInline_Labeled\133useFir = false\135.txt"
@@ -33,14 +33,14 @@
       traceEventStart(<>, %dirty, -1, <>)
     }
     IW({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>:Test.kt")
       if (condition) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@IW
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     if (isTraceInProgress()) {
       traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureEarlyExitInInline_Labeled\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureEarlyExitInInline_Labeled\133useFir = true\135.txt"
index abf76e6..33fa453 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureEarlyExitInInline_Labeled\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureEarlyExitInInline_Labeled\133useFir = true\135.txt"
@@ -33,14 +33,14 @@
       traceEventStart(<>, %dirty, -1, <>)
     }
     IW({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>:Test.kt")
       if (condition) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@IW
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     if (isTraceInProgress()) {
       traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureRuntimeTestWillCompile_CG\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureRuntimeTestWillCompile_CG\133useFir = false\135.txt"
index ac7376c..0dc5b33 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureRuntimeTestWillCompile_CG\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureRuntimeTestWillCompile_CG\133useFir = false\135.txt"
@@ -34,7 +34,7 @@
     }
     Text("Root - before", %composer, 0b0110)
     M1({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<Text("...>,<Text("...>:Test.kt")
       Text("M1 - before", %composer, 0b0110)
       if (condition) {
@@ -48,7 +48,7 @@
         return
       }
       Text("M1 - after", %composer, 0b0110)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("Root - after", %composer, 0b0110)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureRuntimeTestWillCompile_CG\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureRuntimeTestWillCompile_CG\133useFir = true\135.txt"
index ac7376c..0dc5b33 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureRuntimeTestWillCompile_CG\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testEnsureRuntimeTestWillCompile_CG\133useFir = true\135.txt"
@@ -34,7 +34,7 @@
     }
     Text("Root - before", %composer, 0b0110)
     M1({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<Text("...>,<Text("...>:Test.kt")
       Text("M1 - before", %composer, 0b0110)
       if (condition) {
@@ -48,7 +48,7 @@
         return
       }
       Text("M1 - after", %composer, 0b0110)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("Root - after", %composer, 0b0110)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBodyAndCallsAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBodyAndCallsAfter\133useFir = false\135.txt"
index ac862b1..e200d6a 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBodyAndCallsAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBodyAndCallsAfter\133useFir = false\135.txt"
@@ -29,14 +29,14 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(i)>")
   val <iterator> = items.iterator()
   while (<iterator>.hasNext()) {
     val i = <iterator>.next()
     P(i, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBodyAndCallsAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBodyAndCallsAfter\133useFir = true\135.txt"
index ac862b1..e200d6a 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBodyAndCallsAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBodyAndCallsAfter\133useFir = true\135.txt"
@@ -29,14 +29,14 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(i)>")
   val <iterator> = items.iterator()
   while (<iterator>.hasNext()) {
     val i = <iterator>.next()
     P(i, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBody\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBody\133useFir = false\135.txt"
index 4155895..720eec5 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBody\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBody\133useFir = false\135.txt"
@@ -29,14 +29,14 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(i)>")
   val <iterator> = items.iterator()
   while (<iterator>.hasNext()) {
     val i = <iterator>.next()
     P(i, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBody\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBody\133useFir = true\135.txt"
index 4155895..720eec5 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBody\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testForLoopWithCallsInBody\133useFir = true\135.txt"
@@ -29,14 +29,14 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(i)>")
   val <iterator> = items.iterator()
   while (<iterator>.hasNext()) {
     val i = <iterator>.next()
     P(i, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupAroundExtensionFunctions\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupAroundExtensionFunctions\133useFir = false\135.txt"
index 359608f..5799185 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupAroundExtensionFunctions\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupAroundExtensionFunctions\133useFir = false\135.txt"
@@ -46,12 +46,12 @@
     while (<iterator>.hasNext()) {
       val i = <iterator>.next()
       val b = a.get(bKey, %composer, 0b00110110)
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<get(cK...>")
       if (i == 0b0010) {
         a.get(cKey, %composer, 0b00110110)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     if (isTraceInProgress()) {
       traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupAroundExtensionFunctions\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupAroundExtensionFunctions\133useFir = true\135.txt"
index 359608f..5799185 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupAroundExtensionFunctions\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupAroundExtensionFunctions\133useFir = true\135.txt"
@@ -46,12 +46,12 @@
     while (<iterator>.hasNext()) {
       val i = <iterator>.next()
       val b = a.get(bKey, %composer, 0b00110110)
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<get(cK...>")
       if (i == 0b0010) {
         a.get(cKey, %composer, 0b00110110)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     if (isTraceInProgress()) {
       traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupsInLoops\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupsInLoops\133useFir = false\135.txt"
index 70e51b9..2cc1338 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupsInLoops\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupsInLoops\133useFir = false\135.txt"
@@ -47,7 +47,7 @@
       traceEventStart(<>, %dirty, -1, <>)
     }
     items.forEach { item: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "")
       if (item > -1) {
         %composer.startMovableGroup(<>, item)
@@ -63,7 +63,7 @@
         %composer.endMovableGroup()
         tmp0
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     if (isTraceInProgress()) {
       traceEventEnd()
@@ -90,7 +90,7 @@
     val <iterator> = items.iterator()
     while (<iterator>.hasNext()) {
       val item = <iterator>.next()
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "")
       if (item > -1) {
         %composer.startMovableGroup(<>, item)
@@ -106,7 +106,7 @@
         %composer.endMovableGroup()
         tmp0
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     if (isTraceInProgress()) {
       traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupsInLoops\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupsInLoops\133useFir = true\135.txt"
index 5fbcf02..57e0568 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupsInLoops\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testGroupsInLoops\133useFir = true\135.txt"
@@ -47,7 +47,7 @@
       traceEventStart(<>, %dirty, -1, <>)
     }
     items.forEach { item: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "")
       if (item > -1) {
         %composer.startMovableGroup(<>, item)
@@ -59,7 +59,7 @@
         sourceInformationMarkerEnd(%composer)
         %composer.endMovableGroup()
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     if (isTraceInProgress()) {
       traceEventEnd()
@@ -86,7 +86,7 @@
     val <iterator> = items.iterator()
     while (<iterator>.hasNext()) {
       val item = <iterator>.next()
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "")
       if (item > -1) {
         %composer.startMovableGroup(<>, item)
@@ -102,7 +102,7 @@
         %composer.endMovableGroup()
         tmp0
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     if (isTraceInProgress()) {
       traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInBranch\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInBranch\133useFir = false\135.txt"
index 8b48bc4..d3cb440 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInBranch\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInBranch\133useFir = false\135.txt"
@@ -32,15 +32,15 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   if (x > 0) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<A(a)>")
     A(a, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   } else {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<A(b)>")
     A(b, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInBranch\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInBranch\133useFir = true\135.txt"
index 8b48bc4..d3cb440 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInBranch\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInBranch\133useFir = true\135.txt"
@@ -32,15 +32,15 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   if (x > 0) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<A(a)>")
     A(a, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   } else {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<A(b)>")
     A(b, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInConditions\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInConditions\133useFir = false\135.txt"
index 44a9f0a..93b4d57 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInConditions\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInConditions\133useFir = false\135.txt"
@@ -35,24 +35,24 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
-  if (%composer.startReplaceableGroup(<>)
+  if (%composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<B(a)>")
   val tmp0_group = B(a, %composer, 0)
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   tmp0_group) {
     NA()
-  } else if (%composer.startReplaceableGroup(<>)
+  } else if (%composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<B(b)>")
   val tmp1_group = B(b, %composer, 0)
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   tmp1_group) {
     NA()
   } else {
     NA()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInConditions\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInConditions\133useFir = true\135.txt"
index 44a9f0a..93b4d57 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInConditions\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfElseWithCallsInConditions\133useFir = true\135.txt"
@@ -35,24 +35,24 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
-  if (%composer.startReplaceableGroup(<>)
+  if (%composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<B(a)>")
   val tmp0_group = B(a, %composer, 0)
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   tmp0_group) {
     NA()
-  } else if (%composer.startReplaceableGroup(<>)
+  } else if (%composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<B(b)>")
   val tmp1_group = B(b, %composer, 0)
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   tmp1_group) {
     NA()
   } else {
     NA()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithCallsInBranch\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithCallsInBranch\133useFir = false\135.txt"
index 4673898..59f08b0 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithCallsInBranch\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithCallsInBranch\133useFir = false\135.txt"
@@ -28,12 +28,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<A()>")
   if (x > 0) {
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithCallsInBranch\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithCallsInBranch\133useFir = true\135.txt"
index 4673898..59f08b0 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithCallsInBranch\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithCallsInBranch\133useFir = true\135.txt"
@@ -28,12 +28,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<A()>")
   if (x > 0) {
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithEarlyReturnInsideInlineLambda\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithEarlyReturnInsideInlineLambda\133useFir = false\135.txt"
index 40a50be..fe1b30e 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithEarlyReturnInsideInlineLambda\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithEarlyReturnInsideInlineLambda\133useFir = false\135.txt"
@@ -28,17 +28,17 @@
       traceEventStart(<>, %changed, -1, <>)
     }
     run {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<Test()>")
       if (true) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@run
       } else {
         Test(%composer, 0)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@run
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     if (isTraceInProgress()) {
       traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithEarlyReturnInsideInlineLambda\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithEarlyReturnInsideInlineLambda\133useFir = true\135.txt"
index 40a50be..fe1b30e 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithEarlyReturnInsideInlineLambda\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testIfWithEarlyReturnInsideInlineLambda\133useFir = true\135.txt"
@@ -28,17 +28,17 @@
       traceEventStart(<>, %changed, -1, <>)
     }
     run {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<Test()>")
       if (true) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@run
       } else {
         Test(%composer, 0)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@run
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     if (isTraceInProgress()) {
       traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambdaBeforeACall\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambdaBeforeACall\133useFir = false\135.txt"
index 1813dd9..5872e2c 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambdaBeforeACall\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambdaBeforeACall\133useFir = false\135.txt"
@@ -24,17 +24,17 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   InlineNonComposable {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<Test("...>")
     repeat(10) { it: Int ->
       Test("InsideInline", %composer, 0b0110)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   val tmp0 = Test("AfterInline", %composer, 0b0110)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambdaBeforeACall\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambdaBeforeACall\133useFir = true\135.txt"
index 1813dd9..5872e2c 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambdaBeforeACall\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambdaBeforeACall\133useFir = true\135.txt"
@@ -24,17 +24,17 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   InlineNonComposable {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<Test("...>")
     repeat(10) { it: Int ->
       Test("InsideInline", %composer, 0b0110)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   val tmp0 = Test("AfterInline", %composer, 0b0110)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambda_nonLocalReturn\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambda_nonLocalReturn\133useFir = false\135.txt"
index b5e8b9d..12bf825 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambda_nonLocalReturn\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambda_nonLocalReturn\133useFir = false\135.txt"
@@ -27,18 +27,18 @@
     }
     Inline1({ %composer: Composer?, %changed: Int ->
       val tmp0_marker = %composer.currentMarker
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<Inline...>:Test.kt")
       Inline2({ %composer: Composer?, %changed: Int ->
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "C:Test.kt")
         if (true) {
           %composer.endToMarker(tmp0_marker)
           return@Inline1
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
       }, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     if (isTraceInProgress()) {
       traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambda_nonLocalReturn\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambda_nonLocalReturn\133useFir = true\135.txt"
index b5e8b9d..12bf825 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambda_nonLocalReturn\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineLambda_nonLocalReturn\133useFir = true\135.txt"
@@ -27,18 +27,18 @@
     }
     Inline1({ %composer: Composer?, %changed: Int ->
       val tmp0_marker = %composer.currentMarker
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<Inline...>:Test.kt")
       Inline2({ %composer: Composer?, %changed: Int ->
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "C:Test.kt")
         if (true) {
           %composer.endToMarker(tmp0_marker)
           return@Inline1
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
       }, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     if (isTraceInProgress()) {
       traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineReturnLabel\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineReturnLabel\133useFir = false\135.txt"
index 75bd69e..5024195 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineReturnLabel\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineReturnLabel\133useFir = false\135.txt"
@@ -35,14 +35,14 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   FakeBox({ %composer: Composer?, %changed: Int ->
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "C<A()>:Test.kt")
     if (condition) {
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       return@FakeBox
     }
     A(%composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }, %composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineReturnLabel\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineReturnLabel\133useFir = true\135.txt"
index 75bd69e..5024195 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineReturnLabel\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInlineReturnLabel\133useFir = true\135.txt"
@@ -35,14 +35,14 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   FakeBox({ %composer: Composer?, %changed: Int ->
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "C<A()>:Test.kt")
     if (condition) {
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       return@FakeBox
     }
     A(%composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }, %composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun\133useFir = false\135.txt"
index f4a59d1..97e6e7f 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun\133useFir = false\135.txt"
@@ -36,7 +36,7 @@
     }
     A(%composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (condition) {
@@ -50,7 +50,7 @@
         return
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun\133useFir = true\135.txt"
index f4a59d1..97e6e7f 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun\133useFir = true\135.txt"
@@ -36,7 +36,7 @@
     }
     A(%composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (condition) {
@@ -50,7 +50,7 @@
         return
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun_CM3_RFun\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun_CM3_RFun\133useFir = false\135.txt"
index 039aae7..3a2c802 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun_CM3_RFun\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun_CM3_RFun\133useFir = false\135.txt"
@@ -46,7 +46,7 @@
     }
     A(%composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (a) {
@@ -60,10 +60,10 @@
         return
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (b) {
@@ -77,7 +77,7 @@
         return
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun_CM3_RFun\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun_CM3_RFun\133useFir = true\135.txt"
index 039aae7..3a2c802 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun_CM3_RFun\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RFun_CM3_RFun\133useFir = true\135.txt"
@@ -46,7 +46,7 @@
     }
     A(%composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (a) {
@@ -60,10 +60,10 @@
         return
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (b) {
@@ -77,7 +77,7 @@
         return
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RM3\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RM3\133useFir = false\135.txt"
index 5861274..8e9c30d 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RM3\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RM3\133useFir = false\135.txt"
@@ -35,15 +35,15 @@
     }
     A(%composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (condition) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@M3
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RM3\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RM3\133useFir = true\135.txt"
index 5861274..8e9c30d 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RM3\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_RM3\133useFir = true\135.txt"
@@ -35,15 +35,15 @@
     }
     A(%composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (condition) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@M3
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_Return_M3_CM3_Return_M3\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_Return_M3_CM3_Return_M3\133useFir = false\135.txt"
index 93faaff..3a855da 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_Return_M3_CM3_Return_M3\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_Return_M3_CM3_Return_M3\133useFir = false\135.txt"
@@ -42,26 +42,26 @@
     }
     A(%composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (condition) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@M3
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (condition) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@M3
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_Return_M3_CM3_Return_M3\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_Return_M3_CM3_Return_M3\133useFir = true\135.txt"
index 93faaff..3a855da 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_Return_M3_CM3_Return_M3\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_CM3_Return_M3_CM3_Return_M3\133useFir = true\135.txt"
@@ -42,26 +42,26 @@
     }
     A(%composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (condition) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@M3
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (condition) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@M3
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_Lambda\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_Lambda\133useFir = false\135.txt"
index ec150c6..66014f8 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_Lambda\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_Lambda\133useFir = false\135.txt"
@@ -26,7 +26,7 @@
           traceEventStart(<>, %changed, -1, <>)
         }
         M1({ %composer: Composer?, %changed: Int ->
-          %composer.startReplaceableGroup(<>)
+          %composer.startReplaceGroup(<>)
           sourceInformation(%composer, "C:Test.kt")
           if (condition) {
             %composer.endToMarker(tmp0_marker)
@@ -35,7 +35,7 @@
             }
             return@composableLambdaInstance
           }
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
         }, %composer, 0)
         if (isTraceInProgress()) {
           traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_Lambda\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_Lambda\133useFir = true\135.txt"
index ec150c6..66014f8 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_Lambda\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_Lambda\133useFir = true\135.txt"
@@ -26,7 +26,7 @@
           traceEventStart(<>, %changed, -1, <>)
         }
         M1({ %composer: Composer?, %changed: Int ->
-          %composer.startReplaceableGroup(<>)
+          %composer.startReplaceGroup(<>)
           sourceInformation(%composer, "C:Test.kt")
           if (condition) {
             %composer.endToMarker(tmp0_marker)
@@ -35,7 +35,7 @@
             }
             return@composableLambdaInstance
           }
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
         }, %composer, 0)
         if (isTraceInProgress()) {
           traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M1_W_Return_Func\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M1_W_Return_Func\133useFir = false\135.txt"
index 0ae15bf..ba1e034 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M1_W_Return_Func\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M1_W_Return_Func\133useFir = false\135.txt"
@@ -40,10 +40,10 @@
     }
     A(%composer, 0)
     M1({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "*<A()>,<A()>")
       while (true) {
         A(%composer, 0)
@@ -59,9 +59,9 @@
         }
         A(%composer, 0)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M1_W_Return_Func\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M1_W_Return_Func\133useFir = true\135.txt"
index 0ae15bf..ba1e034 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M1_W_Return_Func\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M1_W_Return_Func\133useFir = true\135.txt"
@@ -40,10 +40,10 @@
     }
     A(%composer, 0)
     M1({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "*<A()>,<A()>")
       while (true) {
         A(%composer, 0)
@@ -59,9 +59,9 @@
         }
         A(%composer, 0)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M1\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M1\133useFir = false\135.txt"
index 4e5850e..906de43 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M1\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M1\133useFir = false\135.txt"
@@ -40,13 +40,13 @@
       sourceInformationMarkerStart(%composer, <>, "C<A()>,<M1>,<A()>:Test.kt")
       A(%composer, 0)
       M1({ %composer: Composer?, %changed: Int ->
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "C:Test.kt")
         if (condition) {
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
           return@M1
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
       }, %composer, 0)
       A(%composer, 0)
       sourceInformationMarkerEnd(%composer)
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M1\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M1\133useFir = true\135.txt"
index 4e5850e..906de43 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M1\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M1\133useFir = true\135.txt"
@@ -40,13 +40,13 @@
       sourceInformationMarkerStart(%composer, <>, "C<A()>,<M1>,<A()>:Test.kt")
       A(%composer, 0)
       M1({ %composer: Composer?, %changed: Int ->
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "C:Test.kt")
         if (condition) {
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
           return@M1
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
       }, %composer, 0)
       A(%composer, 0)
       sourceInformationMarkerEnd(%composer)
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M3\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M3\133useFir = false\135.txt"
index 3fd2128..76d72b5 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M3\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M3\133useFir = false\135.txt"
@@ -38,20 +38,20 @@
     A(%composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
       val tmp0_marker = %composer.currentMarker
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<M1>,<A()>:Test.kt")
       A(%composer, 0)
       M1({ %composer: Composer?, %changed: Int ->
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "C:Test.kt")
         if (condition) {
           %composer.endToMarker(tmp0_marker)
           return@M3
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
       }, %composer, 0)
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M3\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M3\133useFir = true\135.txt"
index 3fd2128..76d72b5 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M3\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testInline_M3_M1_Return_M3\133useFir = true\135.txt"
@@ -38,20 +38,20 @@
     A(%composer, 0)
     M3({ %composer: Composer?, %changed: Int ->
       val tmp0_marker = %composer.currentMarker
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<M1>,<A()>:Test.kt")
       A(%composer, 0)
       M1({ %composer: Composer?, %changed: Int ->
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "C:Test.kt")
         if (condition) {
           %composer.endToMarker(tmp0_marker)
           return@M3
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
       }, %composer, 0)
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsAfter\133useFir = false\135.txt"
index 5c95f9f..0141b32 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsAfter\133useFir = false\135.txt"
@@ -29,7 +29,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<A(b)>")
   if (x > 0) {
     %composer.startMovableGroup(<>, x)
@@ -38,7 +38,7 @@
     %composer.endMovableGroup()
     A(b, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsAfter\133useFir = true\135.txt"
index 5c95f9f..0141b32 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsAfter\133useFir = true\135.txt"
@@ -29,7 +29,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<A(b)>")
   if (x > 0) {
     %composer.startMovableGroup(<>, x)
@@ -38,7 +38,7 @@
     %composer.endMovableGroup()
     A(b, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsBefore\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsBefore\133useFir = false\135.txt"
index 4152631e..0f63c6b 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsBefore\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsBefore\133useFir = false\135.txt"
@@ -29,7 +29,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<A(a)>")
   if (x > 0) {
     A(a, %composer, 0)
@@ -38,7 +38,7 @@
     A(b, %composer, 0)
     %composer.endMovableGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsBefore\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsBefore\133useFir = true\135.txt"
index 4152631e..0f63c6b 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsBefore\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIfAndCallsBefore\133useFir = true\135.txt"
@@ -29,7 +29,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<A(a)>")
   if (x > 0) {
     A(a, %composer, 0)
@@ -38,7 +38,7 @@
     A(b, %composer, 0)
     %composer.endMovableGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIf\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIf\133useFir = false\135.txt"
index 03e5b2f..ccfb16c 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIf\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIf\133useFir = false\135.txt"
@@ -28,7 +28,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   if (x > 0) {
     %composer.startMovableGroup(<>, x)
@@ -36,7 +36,7 @@
     A(%composer, 0)
     %composer.endMovableGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIf\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIf\133useFir = true\135.txt"
index 03e5b2f..ccfb16c 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIf\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyInIf\133useFir = true\135.txt"
@@ -28,7 +28,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   if (x > 0) {
     %composer.startMovableGroup(<>, x)
@@ -36,7 +36,7 @@
     A(%composer, 0)
     %composer.endMovableGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyWithComposableValue\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyWithComposableValue\133useFir = false\135.txt"
index 91509c0..37f70fb 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyWithComposableValue\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyWithComposableValue\133useFir = false\135.txt"
@@ -28,7 +28,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<R()>")
   while (x > 0) {
     %composer.startMovableGroup(<>, R(%composer, 0))
@@ -36,7 +36,7 @@
     A(%composer, 0)
     %composer.endMovableGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyWithComposableValue\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyWithComposableValue\133useFir = true\135.txt"
index 91509c0..37f70fb 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyWithComposableValue\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testKeyWithComposableValue\133useFir = true\135.txt"
@@ -28,7 +28,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<R()>")
   while (x > 0) {
     %composer.startMovableGroup(<>, R(%composer, 0))
@@ -36,7 +36,7 @@
     A(%composer, 0)
     %composer.endMovableGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLambdaWithNonUnitResult\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLambdaWithNonUnitResult\133useFir = false\135.txt"
index 65deee7..9e1a7a6 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLambdaWithNonUnitResult\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLambdaWithNonUnitResult\133useFir = false\135.txt"
@@ -25,7 +25,7 @@
       traceEventStart(<>, %changed, -1, <>)
     }
     val factory = createFactory { %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       if (isTraceInProgress()) {
         traceEventStart(<>, %changed, -1, <>)
       }
@@ -33,7 +33,7 @@
       if (isTraceInProgress()) {
         traceEventEnd()
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       tmp0
     }
     factory(%composer, 0)
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLambdaWithNonUnitResult\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLambdaWithNonUnitResult\133useFir = true\135.txt"
index 65deee7..9e1a7a6 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLambdaWithNonUnitResult\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLambdaWithNonUnitResult\133useFir = true\135.txt"
@@ -25,7 +25,7 @@
       traceEventStart(<>, %changed, -1, <>)
     }
     val factory = createFactory { %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       if (isTraceInProgress()) {
         traceEventStart(<>, %changed, -1, <>)
       }
@@ -33,7 +33,7 @@
       if (isTraceInProgress()) {
         traceEventEnd()
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       tmp0
     }
     factory(%composer, 0)
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLetWithComposableCalls\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLetWithComposableCalls\133useFir = false\135.txt"
index 7471158..5c540b6 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLetWithComposableCalls\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLetWithComposableCalls\133useFir = false\135.txt"
@@ -36,7 +36,7 @@
       traceEventStart(<>, %dirty, -1, <>)
     }
     val tmp0_safe_receiver = x
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<A(b)>")
     val tmp0_group = when {
       tmp0_safe_receiver == null -> {
@@ -44,17 +44,17 @@
       }
       else -> {
         tmp0_safe_receiver.let { it: Int ->
-          %composer.startReplaceableGroup(<>)
+          %composer.startReplaceGroup(<>)
           sourceInformation(%composer, "<A(a)>")
           if (it > 0) {
             A(a, %composer, 0)
           }
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
           A(b, %composer, 0)
         }
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp0_group
     A(c, %composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLetWithComposableCalls\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLetWithComposableCalls\133useFir = true\135.txt"
index 7471158..5c540b6 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLetWithComposableCalls\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLetWithComposableCalls\133useFir = true\135.txt"
@@ -36,7 +36,7 @@
       traceEventStart(<>, %dirty, -1, <>)
     }
     val tmp0_safe_receiver = x
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<A(b)>")
     val tmp0_group = when {
       tmp0_safe_receiver == null -> {
@@ -44,17 +44,17 @@
       }
       else -> {
         tmp0_safe_receiver.let { it: Int ->
-          %composer.startReplaceableGroup(<>)
+          %composer.startReplaceGroup(<>)
           sourceInformation(%composer, "<A(a)>")
           if (it > 0) {
             A(a, %composer, 0)
           }
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
           A(b, %composer, 0)
         }
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp0_group
     A(c, %composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithBreak\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithBreak\133useFir = false\135.txt"
index be60c3e..7556d53 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithBreak\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithBreak\133useFir = false\135.txt"
@@ -34,24 +34,24 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A()>")
   a@while (a.hasNext()) {
     val x = a.next()
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<A()>")
     b@while (b.hasNext()) {
       val y = b.next()
       if (y == x) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         break@a
       }
       A(%composer, 0)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithBreak\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithBreak\133useFir = true\135.txt"
index be60c3e..7556d53 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithBreak\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithBreak\133useFir = true\135.txt"
@@ -34,24 +34,24 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A()>")
   a@while (a.hasNext()) {
     val x = a.next()
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<A()>")
     b@while (b.hasNext()) {
       val y = b.next()
       if (y == x) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         break@a
       }
       A(%composer, 0)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithReturn\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithReturn\133useFir = false\135.txt"
index 1d82d7b..aecf15c 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithReturn\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithReturn\133useFir = false\135.txt"
@@ -26,7 +26,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(a: Iterator<Int>, b: Iterator<Int>, %composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)*<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -37,7 +37,7 @@
       if (isTraceInProgress()) {
         traceEventEnd()
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       return
     }
     A(%composer, 0)
@@ -45,5 +45,5 @@
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithReturn\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithReturn\133useFir = true\135.txt"
index 1d82d7b..aecf15c 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithReturn\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testLoopWithReturn\133useFir = true\135.txt"
@@ -26,7 +26,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(a: Iterator<Int>, b: Iterator<Int>, %composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)*<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -37,7 +37,7 @@
       if (isTraceInProgress()) {
         traceEventEnd()
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       return
     }
     A(%composer, 0)
@@ -45,5 +45,5 @@
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testMultipleNestedInlines\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testMultipleNestedInlines\133useFir = false\135.txt"
index b048ac1..9b7a7fe 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testMultipleNestedInlines\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testMultipleNestedInlines\133useFir = false\135.txt"
@@ -30,18 +30,18 @@
     }
     Wrapper({ %composer: Composer?, %changed: Int ->
       sourceInformationMarkerStart(%composer, <>, "C:Test.kt")
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "*<Leaf(0...>")
       repeat(1) { it: Int ->
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "*<Leaf(0...>")
         repeat(1) { it: Int ->
           Leaf(0, %composer, 0b0110, 0)
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         Leaf(0, %composer, 0b0110, 0)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       sourceInformationMarkerEnd(%composer)
     }, %composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testMultipleNestedInlines\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testMultipleNestedInlines\133useFir = true\135.txt"
index b048ac1..9b7a7fe 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testMultipleNestedInlines\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testMultipleNestedInlines\133useFir = true\135.txt"
@@ -30,18 +30,18 @@
     }
     Wrapper({ %composer: Composer?, %changed: Int ->
       sourceInformationMarkerStart(%composer, <>, "C:Test.kt")
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "*<Leaf(0...>")
       repeat(1) { it: Int ->
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "*<Leaf(0...>")
         repeat(1) { it: Int ->
           Leaf(0, %composer, 0b0110, 0)
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         Leaf(0, %composer, 0b0110, 0)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       sourceInformationMarkerEnd(%composer)
     }, %composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoopsAndBreak\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoopsAndBreak\133useFir = false\135.txt"
index 728f598..5713e7dc 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoopsAndBreak\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoopsAndBreak\133useFir = false\135.txt"
@@ -39,7 +39,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(a: Iterator<Int>, b: Iterator<Int>, %composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)*<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -49,7 +49,7 @@
     if (x == 0) {
       break
     }
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<A()>")
     b@while (b.hasNext()) {
       val y = b.next()
@@ -57,24 +57,24 @@
         break
       }
       if (y == x) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         break@a
       }
       if (y > 100) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         if (isTraceInProgress()) {
           traceEventEnd()
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return
       }
       A(%composer, 0)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     A(%composer, 0)
   }
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoopsAndBreak\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoopsAndBreak\133useFir = true\135.txt"
index 9f4feab..9d3b5de 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoopsAndBreak\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoopsAndBreak\133useFir = true\135.txt"
@@ -39,7 +39,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(a: Iterator<Int>, b: Iterator<Int>, %composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)*<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -49,7 +49,7 @@
     if (x == 0) {
       break@a
     }
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<A()>")
     b@while (b.hasNext()) {
       val y = b.next()
@@ -57,24 +57,24 @@
         break@b
       }
       if (y == x) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         break@a
       }
       if (y > 100) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         if (isTraceInProgress()) {
           traceEventEnd()
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return
       }
       A(%composer, 0)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     A(%composer, 0)
   }
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoops\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoops\133useFir = false\135.txt"
index 7cedd68..8532169 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoops\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoops\133useFir = false\135.txt"
@@ -30,18 +30,18 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A()>")
   a@while (a.hasNext()) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<A()>")
     b@while (b.hasNext()) {
       A(%composer, 0)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoops\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoops\133useFir = true\135.txt"
index 7cedd68..8532169 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoops\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testNestedLoops\133useFir = true\135.txt"
@@ -30,18 +30,18 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A()>")
   a@while (a.hasNext()) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<A()>")
     b@while (b.hasNext()) {
       A(%composer, 0)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOR\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOR\133useFir = false\135.txt"
index 0ee3819..0355a3b 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOR\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOR\133useFir = false\135.txt"
@@ -25,10 +25,10 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<B()>,<B()>")
   val tmp0_group = B(%composer, 0) || B(%composer, 0)
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   tmp0_group
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOR\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOR\133useFir = true\135.txt"
index 0ee3819..0355a3b 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOR\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOR\133useFir = true\135.txt"
@@ -25,10 +25,10 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<B()>,<B()>")
   val tmp0_group = B(%composer, 0) || B(%composer, 0)
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   tmp0_group
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOrderingOfPushedEndCallsWithEarlyReturns\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOrderingOfPushedEndCallsWithEarlyReturns\133useFir = false\135.txt"
index c4a2bf9..dbf6574 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOrderingOfPushedEndCallsWithEarlyReturns\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOrderingOfPushedEndCallsWithEarlyReturns\133useFir = false\135.txt"
@@ -49,10 +49,10 @@
       val l = i
       P(i, %composer, 0)
       if (i == 0) {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<P(j)>")
         P(j, %composer, 0)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         if (isTraceInProgress()) {
           traceEventEnd()
         }
@@ -61,10 +61,10 @@
         }
         return
       } else {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<P(k)>")
         P(k, %composer, 0)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
       }
       P(l, %composer, 0)
     }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOrderingOfPushedEndCallsWithEarlyReturns\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOrderingOfPushedEndCallsWithEarlyReturns\133useFir = true\135.txt"
index c4a2bf9..dbf6574 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOrderingOfPushedEndCallsWithEarlyReturns\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOrderingOfPushedEndCallsWithEarlyReturns\133useFir = true\135.txt"
@@ -49,10 +49,10 @@
       val l = i
       P(i, %composer, 0)
       if (i == 0) {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<P(j)>")
         P(j, %composer, 0)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         if (isTraceInProgress()) {
           traceEventEnd()
         }
@@ -61,10 +61,10 @@
         }
         return
       } else {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<P(k)>")
         P(k, %composer, 0)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
       }
       P(l, %composer, 0)
     }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOverrideWithNonUnitResult\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOverrideWithNonUnitResult\133useFir = false\135.txt"
index 2458288..25a0cbd 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOverrideWithNonUnitResult\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOverrideWithNonUnitResult\133useFir = false\135.txt"
@@ -17,7 +17,7 @@
 class SomeClassImpl : SomeClass {
   @Composable
   override fun SomeFunction(%composer: Composer?, %changed: Int): Int {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "C(SomeFunction):Test.kt")
     if (isTraceInProgress()) {
       traceEventStart(<>, %changed, -1, <>)
@@ -26,7 +26,7 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp0
   }
   static val %stable: Int = 0
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOverrideWithNonUnitResult\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOverrideWithNonUnitResult\133useFir = true\135.txt"
index 2458288..25a0cbd 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOverrideWithNonUnitResult\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testOverrideWithNonUnitResult\133useFir = true\135.txt"
@@ -17,7 +17,7 @@
 class SomeClassImpl : SomeClass {
   @Composable
   override fun SomeFunction(%composer: Composer?, %changed: Int): Int {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "C(SomeFunction):Test.kt")
     if (isTraceInProgress()) {
       traceEventStart(<>, %changed, -1, <>)
@@ -26,7 +26,7 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp0
   }
   static val %stable: Int = 0
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInConditionalCallArgument\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInConditionalCallArgument\133useFir = false\135.txt"
index 31ea2f2..936c9e6 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInConditionalCallArgument\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInConditionalCallArgument\133useFir = false\135.txt"
@@ -32,7 +32,7 @@
       traceEventStart(<>, %dirty, -1, <>)
     }
     Test(<block>{
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<rememb...>")
       val tmp1_group = if (param == null) {
         sourceInformationMarkerStart(%composer, <>, "CC(remember):Test.kt#9igjgp")
@@ -44,7 +44,7 @@
       } else {
         null
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       tmp1_group
     }, %composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInConditionalCallArgument\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInConditionalCallArgument\133useFir = true\135.txt"
index 31ea2f2..936c9e6 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInConditionalCallArgument\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInConditionalCallArgument\133useFir = true\135.txt"
@@ -32,7 +32,7 @@
       traceEventStart(<>, %dirty, -1, <>)
     }
     Test(<block>{
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<rememb...>")
       val tmp1_group = if (param == null) {
         sourceInformationMarkerStart(%composer, <>, "CC(remember):Test.kt#9igjgp")
@@ -44,7 +44,7 @@
       } else {
         null
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       tmp1_group
     }, %composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInNestedConditionalCallArgument\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInNestedConditionalCallArgument\133useFir = false\135.txt"
index 4d48d88..f07fc50 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInNestedConditionalCallArgument\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInNestedConditionalCallArgument\133useFir = false\135.txt"
@@ -32,11 +32,11 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   val tmp0 = Test(<block>{
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<Test(>")
     val tmp3_group = if (param == null) {
       Test(<block>{
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<rememb...>")
         val tmp2_group = if (param == null) {
           sourceInformationMarkerStart(%composer, <>, "CC(remember):Test.kt#9igjgp")
@@ -48,13 +48,13 @@
         } else {
           null
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         tmp2_group
       }, %composer, 0)
     } else {
       null
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp3_group
   }, %composer, 0)
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInNestedConditionalCallArgument\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInNestedConditionalCallArgument\133useFir = true\135.txt"
index 4d48d88..f07fc50 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInNestedConditionalCallArgument\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRememberInNestedConditionalCallArgument\133useFir = true\135.txt"
@@ -32,11 +32,11 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   val tmp0 = Test(<block>{
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<Test(>")
     val tmp3_group = if (param == null) {
       Test(<block>{
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<rememb...>")
         val tmp2_group = if (param == null) {
           sourceInformationMarkerStart(%composer, <>, "CC(remember):Test.kt#9igjgp")
@@ -48,13 +48,13 @@
         } else {
           null
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         tmp2_group
       }, %composer, 0)
     } else {
       null
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp3_group
   }, %composer, 0)
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRepeatedCallsToEffects\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRepeatedCallsToEffects\133useFir = false\135.txt"
index d6d5953..3dede05d 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRepeatedCallsToEffects\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRepeatedCallsToEffects\133useFir = false\135.txt"
@@ -44,14 +44,14 @@
       if (isTraceInProgress()) {
         traceEventStart(<>, %changed, -1, <>)
       }
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "*<effect>")
       repeat(number) { it: Int ->
         effects[it] = effect({
           0
         }, %composer, 0b0110)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       outside = effect({
         "0"
       }, %composer, 0b0110)
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRepeatedCallsToEffects\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRepeatedCallsToEffects\133useFir = true\135.txt"
index d6d5953..3dede05d 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRepeatedCallsToEffects\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testRepeatedCallsToEffects\133useFir = true\135.txt"
@@ -44,14 +44,14 @@
       if (isTraceInProgress()) {
         traceEventStart(<>, %changed, -1, <>)
       }
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "*<effect>")
       repeat(number) { it: Int ->
         effects[it] = effect({
           0
         }, %composer, 0b0110)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       outside = effect({
         "0"
       }, %composer, 0b0110)
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnFromLoop\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnFromLoop\133useFir = false\135.txt"
index 5219109..bd769f2 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnFromLoop\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnFromLoop\133useFir = false\135.txt"
@@ -33,7 +33,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(items: Iterator<Int>, %composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)*<P(i)>,<P(l)>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -45,25 +45,25 @@
     val l = i
     P(i, %composer, 0)
     if (i == 0) {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<P(j)>")
       P(j, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       if (isTraceInProgress()) {
         traceEventEnd()
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       return
     } else {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<P(k)>")
       P(k, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     P(l, %composer, 0)
   }
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnFromLoop\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnFromLoop\133useFir = true\135.txt"
index 5219109..bd769f2 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnFromLoop\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnFromLoop\133useFir = true\135.txt"
@@ -33,7 +33,7 @@
 @NonRestartableComposable
 @Composable
 fun Example(items: Iterator<Int>, %composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Example)*<P(i)>,<P(l)>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -45,25 +45,25 @@
     val l = i
     P(i, %composer, 0)
     if (i == 0) {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<P(j)>")
       P(j, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       if (isTraceInProgress()) {
         traceEventEnd()
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       return
     } else {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<P(k)>")
       P(k, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     P(l, %composer, 0)
   }
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnInlinedExpressionWithCall\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnInlinedExpressionWithCall\133useFir = false\135.txt"
index ed747d1..7d750cb 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnInlinedExpressionWithCall\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnInlinedExpressionWithCall\133useFir = false\135.txt"
@@ -31,14 +31,14 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   val tmp0 = <block>{
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<A()>")
     val tmp1_group = x.let { it: Int ->
       A(%composer, 0)
       val tmp0_return = 123
       tmp0_return
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp1_group
   }
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnInlinedExpressionWithCall\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnInlinedExpressionWithCall\133useFir = true\135.txt"
index ed747d1..7d750cb 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnInlinedExpressionWithCall\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnInlinedExpressionWithCall\133useFir = true\135.txt"
@@ -31,14 +31,14 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   val tmp0 = <block>{
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<A()>")
     val tmp1_group = x.let { it: Int ->
       A(%composer, 0)
       val tmp0_return = 123
       tmp0_return
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp1_group
   }
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnNull\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnNull\133useFir = false\135.txt"
index 406738b..c958359 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnNull\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnNull\133useFir = false\135.txt"
@@ -82,7 +82,7 @@
 }
 @Composable
 fun Test2(b: Boolean, %composer: Composer?, %changed: Int): String? {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Test2):Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -92,19 +92,19 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp1_return
   }
   val tmp0 = null
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   return tmp0
 }
 @Composable
 fun Test3(b: Boolean, %composer: Composer?, %changed: Int): String? {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Test3):Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -114,20 +114,20 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp0_return
   } else {
     val tmp1_return = null
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp1_return
   }
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
 @Composable
 fun Test4(b: Boolean, %composer: Composer?, %changed: Int): String? {
@@ -174,7 +174,7 @@
 }
 @Composable
 fun Test7(b: Boolean, %composer: Composer?, %changed: Int): String? {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Test7):Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -184,14 +184,14 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp1_return
   }
   val tmp0 = "false"
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   return tmp0
 }
 @Composable
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnNull\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnNull\133useFir = true\135.txt"
index 2ef96cd..e461327 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnNull\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testReturnNull\133useFir = true\135.txt"
@@ -82,7 +82,7 @@
 }
 @Composable
 fun Test2(b: Boolean, %composer: Composer?, %changed: Int): String? {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Test2):Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -92,19 +92,19 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp1_return
   }
   val tmp0 = null
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   return tmp0
 }
 @Composable
 fun Test3(b: Boolean, %composer: Composer?, %changed: Int): String? {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Test3):Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -114,20 +114,20 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp0_return
   } else {
     val tmp1_return = null
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp1_return
   }
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
 @Composable
 fun Test4(b: Boolean, %composer: Composer?, %changed: Int): String? {
@@ -170,7 +170,7 @@
 }
 @Composable
 fun Test7(b: Boolean, %composer: Composer?, %changed: Int): String? {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(Test7):Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
@@ -180,14 +180,14 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return tmp1_return
   }
   val tmp0 = "false"
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   return tmp0
 }
 @Composable
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSafeCall\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSafeCall\133useFir = false\135.txt"
index 33b11fc2..eed4dc6 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSafeCall\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSafeCall\133useFir = false\135.txt"
@@ -28,7 +28,7 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   val tmp0_safe_receiver = x
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<A()>")
   val tmp0_group = when {
     tmp0_safe_receiver == null -> {
@@ -38,7 +38,7 @@
       tmp0_safe_receiver.A(%composer, 0b1110 and %changed)
     }
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   tmp0_group
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSafeCall\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSafeCall\133useFir = true\135.txt"
index 33b11fc2..eed4dc6 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSafeCall\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSafeCall\133useFir = true\135.txt"
@@ -28,7 +28,7 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   val tmp0_safe_receiver = x
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<A()>")
   val tmp0_group = when {
     tmp0_safe_receiver == null -> {
@@ -38,7 +38,7 @@
       tmp0_safe_receiver.A(%composer, 0b1110 and %changed)
     }
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   tmp0_group
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSourceLineInformationForNormalInline\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSourceLineInformationForNormalInline\133useFir = false\135.txt"
index 4e5f7ed..a38afd2 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSourceLineInformationForNormalInline\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSourceLineInformationForNormalInline\133useFir = false\135.txt"
@@ -50,12 +50,12 @@
       IW({ %composer: Composer?, %changed: Int ->
         sourceInformationMarkerStart(%composer, <>, "C<T(2)>,<T(4)>:Test.kt")
         T(2, %composer, 0b0110)
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "*<T(3)>")
         repeat(3) { it: Int ->
           T(3, %composer, 0b0110)
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         T(4, %composer, 0b0110)
         sourceInformationMarkerEnd(%composer)
       }, %composer, 0)
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSourceLineInformationForNormalInline\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSourceLineInformationForNormalInline\133useFir = true\135.txt"
index 4e5f7ed..a38afd2 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSourceLineInformationForNormalInline\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testSourceLineInformationForNormalInline\133useFir = true\135.txt"
@@ -50,12 +50,12 @@
       IW({ %composer: Composer?, %changed: Int ->
         sourceInformationMarkerStart(%composer, <>, "C<T(2)>,<T(4)>:Test.kt")
         T(2, %composer, 0b0110)
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "*<T(3)>")
         repeat(3) { it: Int ->
           T(3, %composer, 0b0110)
         }
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         T(4, %composer, 0b0110)
         sourceInformationMarkerEnd(%composer)
       }, %composer, 0)
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testTheThing\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testTheThing\133useFir = false\135.txt"
index 619a9f7..4963e87 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testTheThing\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testTheThing\133useFir = false\135.txt"
@@ -61,12 +61,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A()>")
   run {
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
@@ -76,28 +76,28 @@
 @NonRestartableComposable
 @Composable
 fun WithReturn(%composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(WithReturn)<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A()>")
   run {
     A(%composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
 @NonRestartableComposable
 @Composable
@@ -122,12 +122,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A()>")
   run {
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testTheThing\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testTheThing\133useFir = true\135.txt"
index 619a9f7..4963e87 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testTheThing\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testTheThing\133useFir = true\135.txt"
@@ -61,12 +61,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A()>")
   run {
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
@@ -76,28 +76,28 @@
 @NonRestartableComposable
 @Composable
 fun WithReturn(%composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "C(WithReturn)<A()>:Test.kt")
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A()>")
   run {
     A(%composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     return
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
 @NonRestartableComposable
 @Composable
@@ -122,12 +122,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A()>")
   run {
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1\133useFir = false\135.txt"
index af46314..a6f29e1 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1\133useFir = false\135.txt"
@@ -34,7 +34,7 @@
     }
     Text("Some text", %composer, 0b0110)
     M1({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C:Test.kt")
       Identity {
         if (condition) {
@@ -48,7 +48,7 @@
           return
         }
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("Some more text", %composer, 0b0110)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1\133useFir = true\135.txt"
index af46314..a6f29e1 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1\133useFir = true\135.txt"
@@ -34,7 +34,7 @@
     }
     Text("Some text", %composer, 0b0110)
     M1({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C:Test.kt")
       Identity {
         if (condition) {
@@ -48,7 +48,7 @@
           return
         }
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("Some more text", %composer, 0b0110)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1_RM1\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1_RM1\133useFir = false\135.txt"
index d924718..042447b 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1_RM1\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1_RM1\133useFir = false\135.txt"
@@ -33,15 +33,15 @@
     }
     Text("Some text", %composer, 0b0110)
     M1({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C:Test.kt")
       Identity {
         if (condition) {
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
           return@M1
         }
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("Some more text", %composer, 0b0110)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1_RM1\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1_RM1\133useFir = true\135.txt"
index d924718..042447b 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1_RM1\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testVerifyEarlyExitFromNonComposable_M1_RM1\133useFir = true\135.txt"
@@ -33,15 +33,15 @@
     }
     Text("Some text", %composer, 0b0110)
     M1({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C:Test.kt")
       Identity {
         if (condition) {
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
           return@M1
         }
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("Some more text", %composer, 0b0110)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditionsAndCallAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditionsAndCallAfter\133useFir = false\135.txt"
index 9681ed7..abdb1fb 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditionsAndCallAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditionsAndCallAfter\133useFir = false\135.txt"
@@ -32,20 +32,20 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   when {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<R(a)>")
     val tmp0_group = x == R(a, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp0_group -> {
       NA()
     }
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<R(b)>")
     val tmp1_group = x > R(b, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp1_group -> {
       NA()
     }
@@ -53,7 +53,7 @@
       NA()
     }
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditionsAndCallAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditionsAndCallAfter\133useFir = true\135.txt"
index 9681ed7..abdb1fb 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditionsAndCallAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditionsAndCallAfter\133useFir = true\135.txt"
@@ -32,20 +32,20 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   when {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<R(a)>")
     val tmp0_group = x == R(a, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp0_group -> {
       NA()
     }
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<R(b)>")
     val tmp1_group = x > R(b, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp1_group -> {
       NA()
     }
@@ -53,7 +53,7 @@
       NA()
     }
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditions\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditions\133useFir = false\135.txt"
index 2458736..13e1ae3 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditions\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditions\133useFir = false\135.txt"
@@ -32,20 +32,20 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   when {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<R(a)>")
     val tmp0_group = x == R(a, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp0_group -> {
       NA()
     }
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<R(b)>")
     val tmp1_group = x > R(b, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp1_group -> {
       NA()
     }
@@ -53,7 +53,7 @@
       NA()
     }
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditions\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditions\133useFir = true\135.txt"
index 2458736..13e1ae3 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditions\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInConditions\133useFir = true\135.txt"
@@ -32,20 +32,20 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   when {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<R(a)>")
     val tmp0_group = x == R(a, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp0_group -> {
       NA()
     }
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<R(b)>")
     val tmp1_group = x > R(b, %composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp1_group -> {
       NA()
     }
@@ -53,7 +53,7 @@
       NA()
     }
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInSomeResults\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInSomeResults\133useFir = false\135.txt"
index 2cee4f4..bc3f736 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInSomeResults\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInSomeResults\133useFir = false\135.txt"
@@ -33,21 +33,21 @@
   }
   when {
     x < 0 -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(a)>")
       A(a, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     x > 30 -> {
-      %composer.startReplaceableGroup(<>)
-      %composer.endReplaceableGroup()
+      %composer.startReplaceGroup(<>)
+      %composer.endReplaceGroup()
       NA()
     }
     else -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(b)>")
       A(b, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
   }
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInSomeResults\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInSomeResults\133useFir = true\135.txt"
index 2cee4f4..bc3f736 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInSomeResults\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCallsInSomeResults\133useFir = true\135.txt"
@@ -33,21 +33,21 @@
   }
   when {
     x < 0 -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(a)>")
       A(a, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     x > 30 -> {
-      %composer.startReplaceableGroup(<>)
-      %composer.endReplaceableGroup()
+      %composer.startReplaceGroup(<>)
+      %composer.endReplaceGroup()
       NA()
     }
     else -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(b)>")
       A(b, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
   }
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCalls\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCalls\133useFir = false\135.txt"
index 6951232..5f0305a 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCalls\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCalls\133useFir = false\135.txt"
@@ -33,22 +33,22 @@
   }
   when {
     x < 0 -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(a)>")
       A(a, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     x > 30 -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(b)>")
       A(b, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     else -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(c)>")
       A(c, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
   }
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCalls\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCalls\133useFir = true\135.txt"
index 6951232..5f0305a 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCalls\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithCalls\133useFir = true\135.txt"
@@ -33,22 +33,22 @@
   }
   when {
     x < 0 -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(a)>")
       A(a, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     x > 30 -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(b)>")
       A(b, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     else -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(c)>")
       A(c, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
   }
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCallsWithResult\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCallsWithResult\133useFir = false\135.txt"
index ec19619..cfff1ad 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCallsWithResult\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCallsWithResult\133useFir = false\135.txt"
@@ -35,24 +35,24 @@
     val tmp0_subject = x
     when {
       tmp0_subject == 0 -> {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<R(a)>")
         val tmp0_group = R(a, %composer, 0)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         tmp0_group
       }
       tmp0_subject == 0b0001 -> {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<R(b)>")
         val tmp1_group = R(b, %composer, 0)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         tmp1_group
       }
       else -> {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<R(c)>")
         val tmp2_group = R(c, %composer, 0)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         tmp2_group
       }
     }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCallsWithResult\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCallsWithResult\133useFir = true\135.txt"
index ec19619..cfff1ad 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCallsWithResult\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCallsWithResult\133useFir = true\135.txt"
@@ -35,24 +35,24 @@
     val tmp0_subject = x
     when {
       tmp0_subject == 0 -> {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<R(a)>")
         val tmp0_group = R(a, %composer, 0)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         tmp0_group
       }
       tmp0_subject == 0b0001 -> {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<R(b)>")
         val tmp1_group = R(b, %composer, 0)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         tmp1_group
       }
       else -> {
-        %composer.startReplaceableGroup(<>)
+        %composer.startReplaceGroup(<>)
         sourceInformation(%composer, "<R(c)>")
         val tmp2_group = R(c, %composer, 0)
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         tmp2_group
       }
     }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCalls\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCalls\133useFir = false\135.txt"
index bad6af4..0a70d3e 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCalls\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCalls\133useFir = false\135.txt"
@@ -34,22 +34,22 @@
   val tmp0_subject = x
   when {
     tmp0_subject == 0 -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(a)>")
       A(a, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     tmp0_subject == 0b0001 -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(b)>")
       A(b, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     else -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(c)>")
       A(c, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
   }
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCalls\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCalls\133useFir = true\135.txt"
index bad6af4..0a70d3e 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCalls\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhenWithSubjectAndCalls\133useFir = true\135.txt"
@@ -34,22 +34,22 @@
   val tmp0_subject = x
   when {
     tmp0_subject == 0 -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(a)>")
       A(a, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     tmp0_subject == 0b0001 -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(b)>")
       A(b, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
     else -> {
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<A(c)>")
       A(c, %composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }
   }
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallAfter\133useFir = false\135.txt"
index b15c231..ff05c971 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallAfter\133useFir = false\135.txt"
@@ -29,18 +29,18 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<A()>")
   if (x > 0) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<A()>")
     while (x > 0) {
       A(%composer, 0)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallAfter\133useFir = true\135.txt"
index b15c231..ff05c971 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallAfter\133useFir = true\135.txt"
@@ -29,18 +29,18 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<A()>")
   if (x > 0) {
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<A()>")
     while (x > 0) {
       A(%composer, 0)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallBefore\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallBefore\133useFir = false\135.txt"
index 69b1c1a..7f98ae5 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallBefore\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallBefore\133useFir = false\135.txt"
@@ -29,7 +29,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<A()>,*<A()>")
   if (x > 0) {
     A(%composer, 0)
@@ -37,7 +37,7 @@
       A(%composer, 0)
     }
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallBefore\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallBefore\133useFir = true\135.txt"
index 69b1c1a..7f98ae5 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallBefore\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIfAndCallBefore\133useFir = true\135.txt"
@@ -29,7 +29,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "<A()>,*<A()>")
   if (x > 0) {
     A(%composer, 0)
@@ -37,7 +37,7 @@
       A(%composer, 0)
     }
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIf\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIf\133useFir = false\135.txt"
index 07965c2..4cf7057 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIf\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIf\133useFir = false\135.txt"
@@ -28,14 +28,14 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A()>")
   if (x > 0) {
     while (x > 0) {
       A(%composer, 0)
     }
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIf\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIf\133useFir = true\135.txt"
index 07965c2..4cf7057 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIf\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileInsideIf\133useFir = true\135.txt"
@@ -28,14 +28,14 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A()>")
   if (x > 0) {
     while (x > 0) {
       A(%composer, 0)
     }
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBodyAndCallsAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBodyAndCallsAfter\133useFir = false\135.txt"
index d5bd839..d44e03b 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBodyAndCallsAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBodyAndCallsAfter\133useFir = false\135.txt"
@@ -31,13 +31,13 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(item...>")
   while (items.isNotEmpty()) {
     val item = items.removeAt(items.size - 1)
     P(item, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBodyAndCallsAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBodyAndCallsAfter\133useFir = true\135.txt"
index d5bd839..d44e03b 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBodyAndCallsAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBodyAndCallsAfter\133useFir = true\135.txt"
@@ -31,13 +31,13 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(item...>")
   while (items.isNotEmpty()) {
     val item = items.removeAt(items.size - 1)
     P(item, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBody\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBody\133useFir = false\135.txt"
index 96a283c..6d5c7fc 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBody\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBody\133useFir = false\135.txt"
@@ -31,13 +31,13 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(item...>")
   while (items.isNotEmpty()) {
     val item = items.removeAt(items.size - 1)
     P(item, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBody\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBody\133useFir = true\135.txt"
index 96a283c..6d5c7fc 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBody\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInBody\133useFir = true\135.txt"
@@ -31,13 +31,13 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<P(item...>")
   while (items.isNotEmpty()) {
     val item = items.removeAt(items.size - 1)
     P(item, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBodyAndCallsAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBodyAndCallsAfter\133useFir = false\135.txt"
index 6d83f67..4719516 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBodyAndCallsAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBodyAndCallsAfter\133useFir = false\135.txt"
@@ -30,12 +30,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<B()>,<A(a)>")
   while (B(%composer, 0)) {
     A(a, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(b, %composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBodyAndCallsAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBodyAndCallsAfter\133useFir = true\135.txt"
index 6d83f67..4719516 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBodyAndCallsAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBodyAndCallsAfter\133useFir = true\135.txt"
@@ -30,12 +30,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<B()>,<A(a)>")
   while (B(%composer, 0)) {
     A(a, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(b, %composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBody\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBody\133useFir = false\135.txt"
index eb47a3d..0b7ffbc 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBody\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBody\133useFir = false\135.txt"
@@ -29,12 +29,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<B()>,<A()>")
   while (B(%composer, 0)) {
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBody\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBody\133useFir = true\135.txt"
index eb47a3d..0b7ffbc 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBody\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndBody\133useFir = true\135.txt"
@@ -29,12 +29,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<B()>,<A()>")
   while (B(%composer, 0)) {
     A(%composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndCallsAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndCallsAfter\133useFir = false\135.txt"
index 836920e..db5ea62 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndCallsAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndCallsAfter\133useFir = false\135.txt"
@@ -29,12 +29,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<B()>")
   while (B(%composer, 0)) {
     print("hello world")
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndCallsAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndCallsAfter\133useFir = true\135.txt"
index 836920e..db5ea62 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndCallsAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInConditionAndCallsAfter\133useFir = true\135.txt"
@@ -29,12 +29,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<B()>")
   while (B(%composer, 0)) {
     print("hello world")
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   A(%composer, 0)
   if (isTraceInProgress()) {
     traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInCondition\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInCondition\133useFir = false\135.txt"
index c84f9e7..116ac66 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInCondition\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInCondition\133useFir = false\135.txt"
@@ -29,12 +29,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<B()>")
   while (B(%composer, 0)) {
     print("hello world")
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInCondition\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInCondition\133useFir = true\135.txt"
index c84f9e7..116ac66 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInCondition\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileLoopWithCallsInCondition\133useFir = true\135.txt"
@@ -29,12 +29,12 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<B()>")
   while (B(%composer, 0)) {
     print("hello world")
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallAfter\133useFir = false\135.txt"
index 822c943..4061c76 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallAfter\133useFir = false\135.txt"
@@ -29,7 +29,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A(b)>")
   while (x > 0) {
     %composer.startMovableGroup(<>, x)
@@ -38,7 +38,7 @@
     %composer.endMovableGroup()
     A(b, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallAfter\133useFir = true\135.txt"
index 822c943..4061c76 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallAfter\133useFir = true\135.txt"
@@ -29,7 +29,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A(b)>")
   while (x > 0) {
     %composer.startMovableGroup(<>, x)
@@ -38,7 +38,7 @@
     %composer.endMovableGroup()
     A(b, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBeforeAndAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBeforeAndAfter\133useFir = false\135.txt"
index 8feac5a..37404e1 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBeforeAndAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBeforeAndAfter\133useFir = false\135.txt"
@@ -30,7 +30,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A(a)>,<A(c)>")
   while (x > 0) {
     A(a, %composer, 0)
@@ -40,7 +40,7 @@
     %composer.endMovableGroup()
     A(c, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBeforeAndAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBeforeAndAfter\133useFir = true\135.txt"
index 8feac5a..37404e1 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBeforeAndAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBeforeAndAfter\133useFir = true\135.txt"
@@ -30,7 +30,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A(a)>,<A(c)>")
   while (x > 0) {
     A(a, %composer, 0)
@@ -40,7 +40,7 @@
     %composer.endMovableGroup()
     A(c, %composer, 0)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBefore\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBefore\133useFir = false\135.txt"
index d2dae96..42cda15 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBefore\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBefore\133useFir = false\135.txt"
@@ -29,7 +29,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A(a)>")
   while (x > 0) {
     A(a, %composer, 0)
@@ -38,7 +38,7 @@
     A(b, %composer, 0)
     %composer.endMovableGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBefore\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBefore\133useFir = true\135.txt"
index d2dae96..42cda15 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBefore\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKeyAndCallBefore\133useFir = true\135.txt"
@@ -29,7 +29,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<A(a)>")
   while (x > 0) {
     A(a, %composer, 0)
@@ -38,7 +38,7 @@
     A(b, %composer, 0)
     %composer.endMovableGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKey\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKey\133useFir = false\135.txt"
index 6aa8167..2df0578 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKey\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKey\133useFir = false\135.txt"
@@ -28,7 +28,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   while (x > 0) {
     %composer.startMovableGroup(<>, x)
@@ -36,7 +36,7 @@
     A(%composer, 0)
     %composer.endMovableGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKey\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKey\133useFir = true\135.txt"
index 6aa8167..2df0578 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKey\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithKey\133useFir = true\135.txt"
@@ -28,7 +28,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   while (x > 0) {
     %composer.startMovableGroup(<>, x)
@@ -36,7 +36,7 @@
     A(%composer, 0)
     %composer.endMovableGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithTwoKeys\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithTwoKeys\133useFir = false\135.txt"
index 938e6cf..95fd7ed 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithTwoKeys\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithTwoKeys\133useFir = false\135.txt"
@@ -31,7 +31,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   while (x > 0) {
     %composer.startMovableGroup(<>, x)
@@ -43,7 +43,7 @@
     A(b, %composer, 0)
     %composer.endMovableGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithTwoKeys\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithTwoKeys\133useFir = true\135.txt"
index 938e6cf..95fd7ed 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithTwoKeys\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/testWhileWithTwoKeys\133useFir = true\135.txt"
@@ -31,7 +31,7 @@
   if (isTraceInProgress()) {
     traceEventStart(<>, %changed, -1, <>)
   }
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   while (x > 0) {
     %composer.startMovableGroup(<>, x)
@@ -43,7 +43,7 @@
     A(b, %composer, 0)
     %composer.endMovableGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/test_CM1_CCM1_RetFun\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/test_CM1_CCM1_RetFun\133useFir = false\135.txt"
index 468d6f3..f895e8b 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/test_CM1_CCM1_RetFun\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/test_CM1_CCM1_RetFun\133useFir = false\135.txt"
@@ -40,15 +40,15 @@
     }
     Text("Root - before", %composer, 0b0110)
     M1({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<Text("...>,<Text("...>:Test.kt")
       Text("M1 - begin", %composer, 0b0110)
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<Text("...>,<M1>")
       if (condition) {
         Text("if - begin", %composer, 0b0110)
         M1({ %composer: Composer?, %changed: Int ->
-          %composer.startReplaceableGroup(<>)
+          %composer.startReplaceGroup(<>)
           sourceInformation(%composer, "C<Text("...>:Test.kt")
           Text("In CCM1", %composer, 0b0110)
           %composer.endToMarker(tmp0_marker)
@@ -59,12 +59,12 @@
             test_CM1_CCM1_RetFun(condition, %composer, updateChangedFlags(%changed or 0b0001))
           }
           return
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
         }, %composer, 0)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       Text("M1 - end", %composer, 0b0110)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("Root - end", %composer, 0b0110)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/test_CM1_CCM1_RetFun\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/test_CM1_CCM1_RetFun\133useFir = true\135.txt"
index 468d6f3..f895e8b 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/test_CM1_CCM1_RetFun\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/test_CM1_CCM1_RetFun\133useFir = true\135.txt"
@@ -40,15 +40,15 @@
     }
     Text("Root - before", %composer, 0b0110)
     M1({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<Text("...>,<Text("...>:Test.kt")
       Text("M1 - begin", %composer, 0b0110)
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<Text("...>,<M1>")
       if (condition) {
         Text("if - begin", %composer, 0b0110)
         M1({ %composer: Composer?, %changed: Int ->
-          %composer.startReplaceableGroup(<>)
+          %composer.startReplaceGroup(<>)
           sourceInformation(%composer, "C<Text("...>:Test.kt")
           Text("In CCM1", %composer, 0b0110)
           %composer.endToMarker(tmp0_marker)
@@ -59,12 +59,12 @@
             test_CM1_CCM1_RetFun(condition, %composer, updateChangedFlags(%changed or 0b0001))
           }
           return
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
         }, %composer, 0)
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       Text("M1 - end", %composer, 0b0110)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("Root - end", %composer, 0b0110)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = false\135.txt"
index e3171f7..ee4e5ea 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = false\135.txt"
@@ -34,11 +34,11 @@
   Text("Before outer", %composer, 0b0110)
   InlineLinearA({ %composer: Composer?, %changed: Int ->
     val tmp0_marker = %composer.currentMarker
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "C<Text("...>,<Inline...>,<Text("...>:Test.kt")
     Text("Before inner", %composer, 0b0110)
     InlineLinearB({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<Text("...>,<Text("...>:Test.kt")
       Text("Before return", %composer, 0b0110)
       if (condition) {
@@ -46,10 +46,10 @@
         return@InlineLinearA
       }
       Text("After return", %composer, 0b0110)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("After inner", %composer, 0b0110)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }, %composer, 0)
   Text("Before outer", %composer, 0b0110)
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = true\135.txt"
index e3171f7..ee4e5ea 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = true\135.txt"
@@ -34,11 +34,11 @@
   Text("Before outer", %composer, 0b0110)
   InlineLinearA({ %composer: Composer?, %changed: Int ->
     val tmp0_marker = %composer.currentMarker
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "C<Text("...>,<Inline...>,<Text("...>:Test.kt")
     Text("Before inner", %composer, 0b0110)
     InlineLinearB({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<Text("...>,<Text("...>:Test.kt")
       Text("Before return", %composer, 0b0110)
       if (condition) {
@@ -46,10 +46,10 @@
         return@InlineLinearA
       }
       Text("After return", %composer, 0b0110)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("After inner", %composer, 0b0110)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }, %composer, 0)
   Text("Before outer", %composer, 0b0110)
   if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromNestedInlineFunction\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromNestedInlineFunction\133useFir = false\135.txt"
index c804418..f622ab0 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromNestedInlineFunction\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromNestedInlineFunction\133useFir = false\135.txt"
@@ -36,15 +36,15 @@
     sourceInformationMarkerStart(%composer, <>, "C<Text("...>,<Inline...>,<Text("...>:Test.kt")
     Text("Before inner", %composer, 0b0110)
     InlineLinearB({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<Text("...>,<Text("...>:Test.kt")
       Text("Before return", %composer, 0b0110)
       if (condition) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@InlineLinearB
       }
       Text("After return", %composer, 0b0110)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("After inner", %composer, 0b0110)
     sourceInformationMarkerEnd(%composer)
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromNestedInlineFunction\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromNestedInlineFunction\133useFir = true\135.txt"
index c804418..f622ab0 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromNestedInlineFunction\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTests/verifyEarlyExitFromNestedInlineFunction\133useFir = true\135.txt"
@@ -36,15 +36,15 @@
     sourceInformationMarkerStart(%composer, <>, "C<Text("...>,<Inline...>,<Text("...>:Test.kt")
     Text("Before inner", %composer, 0b0110)
     InlineLinearB({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<Text("...>,<Text("...>:Test.kt")
       Text("Before return", %composer, 0b0110)
       if (condition) {
-        %composer.endReplaceableGroup()
+        %composer.endReplaceGroup()
         return@InlineLinearB
       }
       Text("After return", %composer, 0b0110)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("After inner", %composer, 0b0110)
     sourceInformationMarkerEnd(%composer)
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTestsNoSource/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTestsNoSource/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = false\135.txt"
index 68a2b0f..c8788dd 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTestsNoSource/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTestsNoSource/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = false\135.txt"
@@ -30,20 +30,20 @@
   Text("Before outer", %composer, 0b0110)
   InlineLinearA({ %composer: Composer?, %changed: Int ->
     val tmp0_marker = %composer.currentMarker
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     Text("Before inner", %composer, 0b0110)
     InlineLinearB({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       Text("Before return", %composer, 0b0110)
       if (condition) {
         %composer.endToMarker(tmp0_marker)
         return@InlineLinearA
       }
       Text("After return", %composer, 0b0110)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("After inner", %composer, 0b0110)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }, %composer, 0)
   Text("Before outer", %composer, 0b0110)
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTestsNoSource/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTestsNoSource/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = true\135.txt"
index 68a2b0f..c8788dd 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTestsNoSource/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.ControlFlowTransformTestsNoSource/verifyEarlyExitFromMultiLevelNestedInlineFunction\133useFir = true\135.txt"
@@ -30,20 +30,20 @@
   Text("Before outer", %composer, 0b0110)
   InlineLinearA({ %composer: Composer?, %changed: Int ->
     val tmp0_marker = %composer.currentMarker
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     Text("Before inner", %composer, 0b0110)
     InlineLinearB({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       Text("Before return", %composer, 0b0110)
       if (condition) {
         %composer.endToMarker(tmp0_marker)
         return@InlineLinearA
       }
       Text("After return", %composer, 0b0110)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     Text("After inner", %composer, 0b0110)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }, %composer, 0)
   Text("Before outer", %composer, 0b0110)
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testComposableLambdasWithReturnGetGroups\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testComposableLambdasWithReturnGetGroups\133useFir = false\135.txt"
index 173da83..7ced598 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testComposableLambdasWithReturnGetGroups\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testComposableLambdasWithReturnGetGroups\133useFir = false\135.txt"
@@ -17,7 +17,7 @@
 fun A(factory: Function2<Composer, Int, Int>) { }
 fun B() {
   return A { %composer: Composer?, %changed: Int ->
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     if (isTraceInProgress()) {
       traceEventStart(<>, %changed, -1, <>)
     }
@@ -25,7 +25,7 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp0
   }
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testComposableLambdasWithReturnGetGroups\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testComposableLambdasWithReturnGetGroups\133useFir = true\135.txt"
index 173da83..7ced598 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testComposableLambdasWithReturnGetGroups\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testComposableLambdasWithReturnGetGroups\133useFir = true\135.txt"
@@ -17,7 +17,7 @@
 fun A(factory: Function2<Composer, Int, Int>) { }
 fun B() {
   return A { %composer: Composer?, %changed: Int ->
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     if (isTraceInProgress()) {
       traceEventStart(<>, %changed, -1, <>)
     }
@@ -25,7 +25,7 @@
     if (isTraceInProgress()) {
       traceEventEnd()
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp0
   }
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testFunInterfaces2\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testFunInterfaces2\133useFir = false\135.txt"
index 1e95edb..6de1c6d 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testFunInterfaces2\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testFunInterfaces2\133useFir = false\135.txt"
@@ -63,7 +63,7 @@
       class <no name provided> : ButtonColors {
         @Composable
         override fun getColor(%composer: Composer?, %changed: Int): Color {
-          %composer.startReplaceableGroup(<>)
+          %composer.startReplaceGroup(<>)
           sourceInformation(%composer, "C(getColor)<condit...>:Test.kt")
           if (isTraceInProgress()) {
             traceEventStart(<>, %changed, -1, <>)
@@ -76,7 +76,7 @@
           if (isTraceInProgress()) {
             traceEventEnd()
           }
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
           return tmp0
         }
       }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testFunInterfaces2\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testFunInterfaces2\133useFir = true\135.txt"
index 1e95edb..6de1c6d 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testFunInterfaces2\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testFunInterfaces2\133useFir = true\135.txt"
@@ -63,7 +63,7 @@
       class <no name provided> : ButtonColors {
         @Composable
         override fun getColor(%composer: Composer?, %changed: Int): Color {
-          %composer.startReplaceableGroup(<>)
+          %composer.startReplaceGroup(<>)
           sourceInformation(%composer, "C(getColor)<condit...>:Test.kt")
           if (isTraceInProgress()) {
             traceEventStart(<>, %changed, -1, <>)
@@ -76,7 +76,7 @@
           if (isTraceInProgress()) {
             traceEventEnd()
           }
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
           return tmp0
         }
       }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testIfInLambda\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testIfInLambda\133useFir = false\135.txt"
index 0d68784..3a0bc0c 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testIfInLambda\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testIfInLambda\133useFir = false\135.txt"
@@ -56,15 +56,15 @@
           traceEventStart(<>, %changed, -1, <>)
         }
         if (x > 0) {
-          %composer.startReplaceableGroup(<>)
+          %composer.startReplaceGroup(<>)
           sourceInformation(%composer, "<A(x)>")
           A(x, 0, %composer, 0, 0b0010)
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
         } else {
-          %composer.startReplaceableGroup(<>)
+          %composer.startReplaceGroup(<>)
           sourceInformation(%composer, "<A(x)>")
           A(x, 0, %composer, 0, 0b0010)
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
         }
         if (isTraceInProgress()) {
           traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testIfInLambda\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testIfInLambda\133useFir = true\135.txt"
index 0d68784..3a0bc0c 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testIfInLambda\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testIfInLambda\133useFir = true\135.txt"
@@ -56,15 +56,15 @@
           traceEventStart(<>, %changed, -1, <>)
         }
         if (x > 0) {
-          %composer.startReplaceableGroup(<>)
+          %composer.startReplaceGroup(<>)
           sourceInformation(%composer, "<A(x)>")
           A(x, 0, %composer, 0, 0b0010)
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
         } else {
-          %composer.startReplaceableGroup(<>)
+          %composer.startReplaceGroup(<>)
           sourceInformation(%composer, "<A(x)>")
           A(x, 0, %composer, 0, 0b0010)
-          %composer.endReplaceableGroup()
+          %composer.endReplaceGroup()
         }
         if (isTraceInProgress()) {
           traceEventEnd()
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testLoopWithContinueAndCallAfter\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testLoopWithContinueAndCallAfter\133useFir = false\135.txt"
index 18102ab..c976626 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testLoopWithContinueAndCallAfter\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testLoopWithContinueAndCallAfter\133useFir = false\135.txt"
@@ -31,22 +31,22 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   Call(%composer, 0)
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   val <iterator> = 0 .. 1.iterator()
   while (<iterator>.hasNext()) {
     val index = <iterator>.next()
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<Call()>,<Call()>")
     Call(%composer, 0)
     if (condition()) {
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       continue
     }
     Call(%composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testLoopWithContinueAndCallAfter\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testLoopWithContinueAndCallAfter\133useFir = true\135.txt"
index 18102ab..c976626 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testLoopWithContinueAndCallAfter\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testLoopWithContinueAndCallAfter\133useFir = true\135.txt"
@@ -31,22 +31,22 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   Call(%composer, 0)
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "")
   val <iterator> = 0 .. 1.iterator()
   while (<iterator>.hasNext()) {
     val index = <iterator>.next()
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<Call()>,<Call()>")
     Call(%composer, 0)
     if (condition()) {
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       continue
     }
     Call(%composer, 0)
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   if (isTraceInProgress()) {
     traceEventEnd()
   }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testSiblingIfsWithoutElseHaveUniqueKeys\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testSiblingIfsWithoutElseHaveUniqueKeys\133useFir = false\135.txt"
index f3a5067..0c0f571 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testSiblingIfsWithoutElseHaveUniqueKeys\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testSiblingIfsWithoutElseHaveUniqueKeys\133useFir = false\135.txt"
@@ -33,12 +33,12 @@
     if (isTraceInProgress()) {
       traceEventStart(<>, %dirty, -1, <>)
     }
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<A()>")
     if (cond) {
       A(%composer, 0)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     if (cond) {
       B(%composer, 0)
     }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testSiblingIfsWithoutElseHaveUniqueKeys\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testSiblingIfsWithoutElseHaveUniqueKeys\133useFir = true\135.txt"
index f3a5067..0c0f571 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testSiblingIfsWithoutElseHaveUniqueKeys\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/testSiblingIfsWithoutElseHaveUniqueKeys\133useFir = true\135.txt"
@@ -33,12 +33,12 @@
     if (isTraceInProgress()) {
       traceEventStart(<>, %dirty, -1, <>)
     }
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<A()>")
     if (cond) {
       A(%composer, 0)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     if (cond) {
       B(%composer, 0)
     }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/test_InlineForLoop\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/test_InlineForLoop\133useFir = false\135.txt"
index 8eedb86..3b8cb66 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/test_InlineForLoop\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/test_InlineForLoop\133useFir = false\135.txt"
@@ -47,13 +47,13 @@
 @ComposableInferredTarget(scheme = "[0[0]]")
 fun <T> Bug(items: List<T>, content: Function3<@[ParameterName(name = 'item')] T, Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
   sourceInformationMarkerStart(%composer, <>, "CC(Bug)P(1):Test.kt")
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<conten...>")
   val <iterator> = items.iterator()
   while (<iterator>.hasNext()) {
     val item = <iterator>.next()
     content(item, %composer, 0b01110000 and %changed)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   sourceInformationMarkerEnd(%composer)
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/test_InlineForLoop\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/test_InlineForLoop\133useFir = true\135.txt"
index 587adfa..2381eaa 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/test_InlineForLoop\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTests/test_InlineForLoop\133useFir = true\135.txt"
@@ -47,13 +47,13 @@
 @ComposableInferredTarget(scheme = "[0[0]]")
 fun <T> Bug(items: List<T>, content: Function3<@[ParameterName(name = 'item')] T, Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
   sourceInformationMarkerStart(%composer, <>, "CC(Bug)P(1):Test.kt")
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   sourceInformation(%composer, "*<conten...>")
   val <iterator> = items.iterator()
   while (<iterator>.hasNext()) {
     val item = <iterator>.next()
     content(item, %composer, 0b01110000 and %changed)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
   sourceInformationMarkerEnd(%composer)
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTestsNoSource/test_InlineForLoop_no_source_info\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTestsNoSource/test_InlineForLoop_no_source_info\133useFir = false\135.txt"
index ed7d170..0d63bde 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTestsNoSource/test_InlineForLoop_no_source_info\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTestsNoSource/test_InlineForLoop_no_source_info\133useFir = false\135.txt"
@@ -37,11 +37,11 @@
 @Composable
 @ComposableInferredTarget(scheme = "[0[0]]")
 private fun <T> Bug(items: List<T>, content: Function3<@[ParameterName(name = 'item')] T, Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   val <iterator> = items.iterator()
   while (<iterator>.hasNext()) {
     val item = <iterator>.next()
     content(item, %composer, 0b01110000 and %changed)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTestsNoSource/test_InlineForLoop_no_source_info\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTestsNoSource/test_InlineForLoop_no_source_info\133useFir = true\135.txt"
index 2076a4f..0d5f79d 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTestsNoSource/test_InlineForLoop_no_source_info\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.FunctionBodySkippingTransformTestsNoSource/test_InlineForLoop_no_source_info\133useFir = true\135.txt"
@@ -37,11 +37,11 @@
 @Composable
 @ComposableInferredTarget(scheme = "[0[0]]")
 private fun <T> Bug(items: List<T>, content: Function3<@[ParameterName(name = 'item')] T, Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
-  %composer.startReplaceableGroup(<>)
+  %composer.startReplaceGroup(<>)
   val <iterator> = items.iterator()
   while (<iterator>.hasNext()) {
     val item = <iterator>.next()
     content(item, %composer, 0b01110000 and %changed)
   }
-  %composer.endReplaceableGroup()
+  %composer.endReplaceGroup()
 }
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.LambdaMemoizationTransformTests/testMemoizingFunctionInIf\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.LambdaMemoizationTransformTests/testMemoizingFunctionInIf\133useFir = false\135.txt"
index 1f82a6f..2fa88ce 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.LambdaMemoizationTransformTests/testMemoizingFunctionInIf\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.LambdaMemoizationTransformTests/testMemoizingFunctionInIf\133useFir = false\135.txt"
@@ -32,7 +32,7 @@
       traceEventStart(<>, %dirty, -1, <>)
     }
     Something(<block>{
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<{>")
       val tmp1_group = if (param != null) {
         sourceInformationMarkerStart(%composer, <>, "CC(remember):Test.kt#9igjgp")
@@ -46,7 +46,7 @@
       } else {
         null
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       tmp1_group
     }, %composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.LambdaMemoizationTransformTests/testMemoizingFunctionInIf\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.LambdaMemoizationTransformTests/testMemoizingFunctionInIf\133useFir = true\135.txt"
index 1f82a6f..2fa88ce 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.LambdaMemoizationTransformTests/testMemoizingFunctionInIf\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.LambdaMemoizationTransformTests/testMemoizingFunctionInIf\133useFir = true\135.txt"
@@ -32,7 +32,7 @@
       traceEventStart(<>, %dirty, -1, <>)
     }
     Something(<block>{
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "<{>")
       val tmp1_group = if (param != null) {
         sourceInformationMarkerStart(%composer, <>, "CC(remember):Test.kt#9igjgp")
@@ -46,7 +46,7 @@
       } else {
         null
       }
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
       tmp1_group
     }, %composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testElidedRememberInsideIfDeoptsRememberAfterIf\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testElidedRememberInsideIfDeoptsRememberAfterIf\133useFir = false\135.txt"
index 5127fc0..4df31fb 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testElidedRememberInsideIfDeoptsRememberAfterIf\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testElidedRememberInsideIfDeoptsRememberAfterIf\133useFir = false\135.txt"
@@ -27,7 +27,7 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   val a = <block>{
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<rememb...>")
     val tmp1_group = if (x) {
       sourceInformationMarkerStart(%composer, <>, "CC(remember):Test.kt#9igjgp")
@@ -39,7 +39,7 @@
     } else {
       2
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp1_group
   }
   val b = <block>{
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testElidedRememberInsideIfDeoptsRememberAfterIf\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testElidedRememberInsideIfDeoptsRememberAfterIf\133useFir = true\135.txt"
index 5127fc0..4df31fb 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testElidedRememberInsideIfDeoptsRememberAfterIf\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testElidedRememberInsideIfDeoptsRememberAfterIf\133useFir = true\135.txt"
@@ -27,7 +27,7 @@
     traceEventStart(<>, %changed, -1, <>)
   }
   val a = <block>{
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<rememb...>")
     val tmp1_group = if (x) {
       sourceInformationMarkerStart(%composer, <>, "CC(remember):Test.kt#9igjgp")
@@ -39,7 +39,7 @@
     } else {
       2
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp1_group
   }
   val b = <block>{
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testRememberInALoop\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testRememberInALoop\133useFir = false\135.txt"
index ed9888e..50a53e1 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testRememberInALoop\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testRememberInALoop\133useFir = false\135.txt"
@@ -22,7 +22,7 @@
     if (isTraceInProgress()) {
       traceEventStart(<>, %changed, -1, <>)
     }
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<rememb...>")
     val <iterator> = 0 until count.iterator()
     while (<iterator>.hasNext()) {
@@ -36,7 +36,7 @@
         tmp0_group
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     val a = <block>{
       sourceInformationMarkerStart(%composer, <>, "CC(remember):Test.kt#9igjgp")
       val tmp1_group = %composer.cache(false) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testRememberInALoop\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testRememberInALoop\133useFir = true\135.txt"
index eeb8395..d2f0f67c 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testRememberInALoop\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.RememberIntrinsicTransformTests/testRememberInALoop\133useFir = true\135.txt"
@@ -22,7 +22,7 @@
     if (isTraceInProgress()) {
       traceEventStart(<>, %changed, -1, <>)
     }
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<rememb...>")
     val <iterator> = 0 until count.iterator()
     while (<iterator>.hasNext()) {
@@ -36,7 +36,7 @@
         tmp0_group
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     val a = <block>{
       sourceInformationMarkerStart(%composer, <>, "CC(remember):Test.kt#9igjgp")
       val tmp1_group = %composer.cache(false) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TargetAnnotationsTransformTests/testOptionalParameters\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TargetAnnotationsTransformTests/testOptionalParameters\133useFir = false\135.txt"
index fad6262..0f427c9 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TargetAnnotationsTransformTests/testOptionalParameters\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TargetAnnotationsTransformTests/testOptionalParameters\133useFir = false\135.txt"
@@ -161,7 +161,7 @@
     }
     one(%composer, 0b1110 and %dirty)
     val tmp0_safe_receiver = two
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<invoke...>")
     val tmp0_group = when {
       tmp0_safe_receiver == null -> {
@@ -171,10 +171,10 @@
         tmp0_safe_receiver(%composer, 0b1110 and %dirty shr 0b0011)
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp0_group
     val tmp1_safe_receiver = three
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<it()>")
     val tmp1_group = when {
       tmp1_safe_receiver == null -> {
@@ -186,10 +186,10 @@
         }
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp1_group
     val tmp2_safe_receiver = four
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<four()>")
     val tmp2_group = when {
       tmp2_safe_receiver == null -> {
@@ -201,16 +201,16 @@
         }
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp2_group
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<five()>")
     if (five != null) {
       five(%composer, 0b1110 and %dirty shr 0b1100)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     val tmp3_safe_receiver = six
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<Wrappe...>")
     val tmp3_group = when {
       tmp3_safe_receiver == null -> {
@@ -222,7 +222,7 @@
         }
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp3_group
     content(%composer, 0b1110 and %dirty shr 0b00010010)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TargetAnnotationsTransformTests/testOptionalParameters\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TargetAnnotationsTransformTests/testOptionalParameters\133useFir = true\135.txt"
index fad6262..0f427c9 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TargetAnnotationsTransformTests/testOptionalParameters\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TargetAnnotationsTransformTests/testOptionalParameters\133useFir = true\135.txt"
@@ -161,7 +161,7 @@
     }
     one(%composer, 0b1110 and %dirty)
     val tmp0_safe_receiver = two
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<invoke...>")
     val tmp0_group = when {
       tmp0_safe_receiver == null -> {
@@ -171,10 +171,10 @@
         tmp0_safe_receiver(%composer, 0b1110 and %dirty shr 0b0011)
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp0_group
     val tmp1_safe_receiver = three
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<it()>")
     val tmp1_group = when {
       tmp1_safe_receiver == null -> {
@@ -186,10 +186,10 @@
         }
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp1_group
     val tmp2_safe_receiver = four
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<four()>")
     val tmp2_group = when {
       tmp2_safe_receiver == null -> {
@@ -201,16 +201,16 @@
         }
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp2_group
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "<five()>")
     if (five != null) {
       five(%composer, 0b1110 and %dirty shr 0b1100)
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     val tmp3_safe_receiver = six
-    %composer.startReplaceableGroup(<>)
+    %composer.startReplaceGroup(<>)
     sourceInformation(%composer, "*<Wrappe...>")
     val tmp3_group = when {
       tmp3_safe_receiver == null -> {
@@ -222,7 +222,7 @@
         }
       }
     }
-    %composer.endReplaceableGroup()
+    %composer.endReplaceGroup()
     tmp3_group
     content(%composer, 0b1110 and %dirty shr 0b00010010)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TraceInformationTest/testInlineFunctionsDonotGenerateTraceMarkers\133useFir = false\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TraceInformationTest/testInlineFunctionsDonotGenerateTraceMarkers\133useFir = false\135.txt"
index 73bb99b..626f0e42 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TraceInformationTest/testInlineFunctionsDonotGenerateTraceMarkers\133useFir = false\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TraceInformationTest/testInlineFunctionsDonotGenerateTraceMarkers\133useFir = false\135.txt"
@@ -44,7 +44,7 @@
     }
     A(%composer, 0)
     Wrapper({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (!condition) {
@@ -58,7 +58,7 @@
         return
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TraceInformationTest/testInlineFunctionsDonotGenerateTraceMarkers\133useFir = true\135.txt" "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TraceInformationTest/testInlineFunctionsDonotGenerateTraceMarkers\133useFir = true\135.txt"
index 73bb99b..626f0e42 100644
--- "a/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TraceInformationTest/testInlineFunctionsDonotGenerateTraceMarkers\133useFir = true\135.txt"
+++ "b/compose/compiler/compiler-hosted/integration-tests/src/test/resources/golden/androidx.compose.compiler.plugins.kotlin.TraceInformationTest/testInlineFunctionsDonotGenerateTraceMarkers\133useFir = true\135.txt"
@@ -44,7 +44,7 @@
     }
     A(%composer, 0)
     Wrapper({ %composer: Composer?, %changed: Int ->
-      %composer.startReplaceableGroup(<>)
+      %composer.startReplaceGroup(<>)
       sourceInformation(%composer, "C<A()>,<A()>:Test.kt")
       A(%composer, 0)
       if (!condition) {
@@ -58,7 +58,7 @@
         return
       }
       A(%composer, 0)
-      %composer.endReplaceableGroup()
+      %composer.endReplaceGroup()
     }, %composer, 0)
     A(%composer, 0)
     if (isTraceInProgress()) {
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/AbstractComposeLowering.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/AbstractComposeLowering.kt
index 74d139b..acc6fd3 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/AbstractComposeLowering.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/AbstractComposeLowering.kt
@@ -1254,7 +1254,7 @@
         }
     }
 
-    fun irStartReplaceableGroup(
+    fun irStartReplaceGroup(
         currentComposer: IrExpression,
         key: IrExpression,
         startOffset: Int = UNDEFINED_OFFSET,
@@ -1262,7 +1262,7 @@
     ): IrExpression {
         return irMethodCall(
             currentComposer,
-            startReplaceableFunction,
+            startReplaceFunction,
             startOffset,
             endOffset
         ).also {
@@ -1270,14 +1270,14 @@
         }
     }
 
-    fun irEndReplaceableGroup(
+    fun irEndReplaceGroup(
         currentComposer: IrExpression,
         startOffset: Int = UNDEFINED_OFFSET,
         endOffset: Int = UNDEFINED_OFFSET,
     ): IrExpression {
         return irMethodCall(
             currentComposer,
-            endReplaceableFunction,
+            endReplaceFunction,
             startOffset,
             endOffset
         )
@@ -1310,17 +1310,21 @@
                 it.valueParameters.first().type.isNullableAny()
         } ?: changedFunction
 
-    val startReplaceableFunction by guardedLazy {
-        composerIrClass.functions
+    private val startReplaceFunction by guardedLazy {
+        composerIrClass.functions.firstOrNull {
+            it.name.identifier == "startReplaceGroup" && it.valueParameters.size == 1
+        } ?: composerIrClass.functions
             .first {
                 it.name.identifier == "startReplaceableGroup" && it.valueParameters.size == 1
             }
     }
 
-    val endReplaceableFunction by guardedLazy {
-        composerIrClass.functions
+    private val endReplaceFunction by guardedLazy {
+        composerIrClass.functions.firstOrNull {
+            it.name.identifier == "endReplaceGroup" && it.valueParameters.isEmpty()
+        } ?: composerIrClass.functions
             .first {
-                it.name.identifier == "endReplaceableGroup" && it.valueParameters.size == 0
+                it.name.identifier == "endReplaceableGroup" && it.valueParameters.isEmpty()
             }
     }
 
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt
index c960c63..4647e77 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposableFunctionBodyTransformer.kt
@@ -312,7 +312,7 @@
  *
  * There are 3 types of groups in Compose:
  *
- * 1. Replaceable Groups
+ * 1. Replace Groups
  * 2. Movable Groups
  * 3. Restart Groups
  *
@@ -322,7 +322,7 @@
  *
  * 1. If a block executes exactly 1 time always, no groups are needed
  * 2. If a set of blocks are such that exactly one of them is executed exactly once (for example,
- * the result blocks of a when clause), then we insert a replaceable group around each block.
+ * the result blocks of a when clause), then we insert a replace group around each block.
  * 3. A movable group is only needed if the immediate composable call in the group has a Pivotal
  * property.
  *
@@ -788,12 +788,12 @@
 
     // At a high level, without useNonSkippingGroupOptimization, a non-restartable composable
     // function
-    // 1. gets a replaceable group placed around the body
+    // 1. gets a replace group placed around the body
     // 2. never calls `$composer.changed(...)` with its parameters
     // 3. can have default parameters, so needs to add the defaults preamble if defaults present
     // 4. proper groups around control flow structures in the body
     // If supported by the runtime and useNonSkippingGroupOptimization is enabled then the
-    // replaceable group is not necessary so the above list is changed to,
+    // replace group is not necessary so the above list is changed to,
     // 1. never calls `$composer.changed(...)` with its parameters
     // 2. can have default parameters, so needs to add the defaults preamble if defaults present
     // 3. never elides groups around control flow structures in the body
@@ -860,7 +860,7 @@
             scope.realizeGroup {
                 irComposite(statements = listOfNotNull(
                     if (emitTraceMarkers) irTraceEventEnd() else null,
-                    irEndReplaceableGroup(scope = scope)
+                    irEndReplaceGroup(scope = scope)
                 ))
             }
         } else if (useNonSkippingGroupOptimization) {
@@ -874,7 +874,7 @@
             listOfNotNull(
                 when {
                     outerGroupRequired ->
-                        irStartReplaceableGroup(
+                        irStartReplaceGroup(
                             body,
                             scope,
                             irFunctionSourceKey()
@@ -891,7 +891,7 @@
                 *bodyPreamble.statements.toTypedArray(),
                 *transformed.statements.toTypedArray(),
                 when {
-                    outerGroupRequired -> irEndReplaceableGroup(scope = scope)
+                    outerGroupRequired -> irEndReplaceGroup(scope = scope)
                     collectSourceInformation && !hasExplicitGroups ->
                         irSourceInformationMarkerEnd(body, scope)
                     else -> null
@@ -2020,7 +2020,7 @@
             functionSourceKey()
         )
 
-    private fun irStartReplaceableGroup(
+    private fun irStartReplaceGroup(
         element: IrElement,
         scope: Scope.BlockScope,
         key: IrExpression = element.irSourceKey(),
@@ -2028,7 +2028,7 @@
         endOffset: Int = UNDEFINED_OFFSET
     ): IrExpression {
         return irWithSourceInformation(
-            irStartReplaceableGroup(
+            irStartReplaceGroup(
                 scope.irCurrentComposer(startOffset, endOffset),
                 key,
                 startOffset,
@@ -2199,12 +2199,12 @@
         )
     }
 
-    private fun irEndReplaceableGroup(
+    private fun irEndReplaceGroup(
         startOffset: Int = UNDEFINED_OFFSET,
         endOffset: Int = UNDEFINED_OFFSET,
         scope: Scope.BlockScope
     ): IrExpression {
-        return irEndReplaceableGroup(
+        return irEndReplaceGroup(
             scope.irCurrentComposer(startOffset, endOffset),
             startOffset,
             endOffset
@@ -2299,13 +2299,13 @@
         }
     }
 
-    private fun IrBlock.withReplaceableGroupStatements(
+    private fun IrBlock.withReplaceGroupStatements(
         scope: Scope.BlockScope,
         insertAt: Int = 0
     ): IrExpression {
         currentFunctionScope.metrics.recordGroup()
         scope.realizeGroup {
-            irEndReplaceableGroup(scope = scope)
+            irEndReplaceGroup(scope = scope)
         }
 
         val prefix = statements.subList(0, insertAt)
@@ -2319,7 +2319,7 @@
                 endOffset,
                 type,
                 origin,
-                prefix + listOf(irStartReplaceableGroup(this, scope)) + suffix
+                prefix + listOf(irStartReplaceGroup(this, scope)) + suffix
             )
             // otherwise, we want to push an end call for any early returns/jumps, but also add
             // an end call to the end of the group
@@ -2329,18 +2329,18 @@
                 type,
                 origin,
                 prefix + listOf(
-                    irStartReplaceableGroup(
+                    irStartReplaceGroup(
                         this,
                         scope,
                         startOffset = startOffset,
                         endOffset = endOffset
                     )
-                ) + suffix + listOf(irEndReplaceableGroup(startOffset, endOffset, scope))
+                ) + suffix + listOf(irEndReplaceGroup(startOffset, endOffset, scope))
             )
         }
     }
 
-    private fun IrExpression.asReplaceableGroup(scope: Scope.BlockScope): IrExpression {
+    private fun IrExpression.asReplaceGroup(scope: Scope.BlockScope): IrExpression {
         currentFunctionScope.metrics.recordGroup()
         // if the scope has no composable calls, then the only important thing is that a
         // start/end call gets executed. as a result, we can just put them both at the top of
@@ -2349,39 +2349,39 @@
         if (!scope.hasComposableCalls && !scope.hasReturn && !scope.hasJump) {
             return wrap(
                 before = listOf(
-                    irStartReplaceableGroup(
+                    irStartReplaceGroup(
                         this,
                         scope,
                         startOffset = startOffset,
                         endOffset = endOffset,
                     ),
-                    irEndReplaceableGroup(startOffset, endOffset, scope)
+                    irEndReplaceGroup(startOffset, endOffset, scope)
                 )
             )
         }
         scope.realizeGroup {
-            irEndReplaceableGroup(scope = scope)
+            irEndReplaceGroup(scope = scope)
         }
         return when {
             // if the scope ends with a return call, then it will get properly ended if we
             // just push the end call on the scope because of the way returns get transformed in
             // this class. As a result, here we can safely just "prepend" the start call
             endsWithReturnOrJump() -> {
-                wrap(before = listOf(irStartReplaceableGroup(this, scope)))
+                wrap(before = listOf(irStartReplaceGroup(this, scope)))
             }
             // otherwise, we want to push an end call for any early returns/jumps, but also add
             // an end call to the end of the group
             else -> {
                 wrap(
                     before = listOf(
-                        irStartReplaceableGroup(
+                        irStartReplaceGroup(
                             this,
                             scope,
                             startOffset = startOffset,
                             endOffset = endOffset
                         )
                     ),
-                    after = listOf(irEndReplaceableGroup(startOffset, endOffset, scope))
+                    after = listOf(irEndReplaceGroup(startOffset, endOffset, scope))
                 )
             }
         }
@@ -2427,12 +2427,12 @@
             realizeGroup = {
                 if (before.statements.isEmpty()) {
                     metrics.recordGroup()
-                    before.statements.add(irStartReplaceableGroup(this, scope))
-                    after.statements.add(irEndReplaceableGroup(scope = scope))
+                    before.statements.add(irStartReplaceGroup(this, scope))
+                    after.statements.add(irEndReplaceGroup(scope = scope))
                 }
             },
             makeEnd = {
-                irEndReplaceableGroup(scope = scope)
+                irEndReplaceGroup(scope = scope)
             }
         )
         return wrap(
@@ -2456,7 +2456,7 @@
         // the group, and we don't have to deal with any of the complicated jump logic that
         // could be inside of the block
         val makeStart = {
-            if (scope.hasInlineEarlyReturn) irStartReplaceableGroup(
+            if (scope.hasInlineEarlyReturn) irStartReplaceGroup(
                 this,
                 scope,
                 startOffset = startOffset,
@@ -2465,7 +2465,7 @@
             else irSourceInformationMarkerStart(this, scope)
         }
         val makeEnd = {
-            if (scope.hasInlineEarlyReturn) irEndReplaceableGroup(scope = scope)
+            if (scope.hasInlineEarlyReturn) irEndReplaceGroup(scope = scope)
             else irSourceInformationMarkerEnd(this, scope)
         }
         if (!scope.hasComposableCalls && !scope.hasReturn && !scope.hasJump) {
@@ -3237,9 +3237,9 @@
             else
                 cacheCall.wrap(
                     before = inputVals.filterNotNull() + listOf(
-                        irStartReplaceableGroup(expression, blockScope)
+                        irStartReplaceGroup(expression, blockScope)
                     ),
-                    after = listOf(irEndReplaceableGroup(scope = blockScope))
+                    after = listOf(irEndReplaceGroup(scope = blockScope))
                 )
         }.also { block ->
             if (
@@ -3701,7 +3701,7 @@
         withScope(loopScope) {
             loop.condition = loop.condition.transform(this, null)
             if (loopScope.needsGroupPerIteration && loopScope.hasComposableCalls) {
-                loop.condition = loop.condition.asReplaceableGroup(loopScope)
+                loop.condition = loop.condition.asReplaceGroup(loopScope)
             }
 
             loop.body = loop.body?.transform(this, null)
@@ -3725,12 +3725,12 @@
                     val forLoopVariableIndex = current.statements.indexOfFirst {
                         (it as? IrVariable)?.origin == IrDeclarationOrigin.FOR_LOOP_VARIABLE
                     }
-                    loop.body = current.withReplaceableGroupStatements(
+                    loop.body = current.withReplaceGroupStatements(
                         loopScope,
                         insertAt = forLoopVariableIndex + 1
                     )
                 } else {
-                    loop.body = current?.asReplaceableGroup(loopScope)
+                    loop.body = current?.asReplaceGroup(loopScope)
                 }
             }
         }
@@ -3759,7 +3759,7 @@
         // result branches of the when clause. This is because if we have N branches of a when
         // clause, we will always execute exactly 1 result branch, but we will execute 0-N of the
         // conditions. This means that if only the results have composable calls, we can use
-        // replaceable groups to represent the entire expression. If a condition has a composable
+        // replace groups to represent the entire expression. If a condition has a composable
         // call in it, we need to place the whole expression in a Container group, since a variable
         // number of them will be created. The exception here is the first branch's condition,
         // since it will *always* be executed. As a result, if only the first conditional has a
@@ -3863,7 +3863,7 @@
             // to generate a group around it because we will be generating one around the entire
             // if statement
             if (needsWrappingGroup && condScope.hasComposableCalls) {
-                it.condition = it.condition.asReplaceableGroup(condScope)
+                it.condition = it.condition.asReplaceGroup(condScope)
             }
             if (
                 // if no wrapping group but more than one result have calls, we have to have every
@@ -3873,7 +3873,7 @@
                 // the block has composable calls
                 (needsWrappingGroup && resultScope.hasComposableCalls)
             ) {
-                it.result = it.result.asReplaceableGroup(resultScope)
+                it.result = it.result.asReplaceGroup(resultScope)
             }
 
             if (resultsWithCalls == 1 && resultScope.hasComposableCalls) {
@@ -4396,21 +4396,6 @@
                     else -> super.sourceLocationOf(call)
                 }
         }
-
-        class ComposableLambdaScope : BlockScope("composableLambda") {
-            override fun calculateHasSourceInformation(sourceInformationEnabled: Boolean): Boolean {
-                return sourceInformationEnabled
-            }
-
-            override fun calculateSourceInfo(sourceInformationEnabled: Boolean): String? =
-                if (sourceInformationEnabled) {
-                    "C${
-                    super.calculateSourceInfo(sourceInformationEnabled) ?: ""
-                    }:${functionScope?.function?.sourceFileInformation() ?: ""}"
-                } else {
-                    null
-                }
-        }
     }
 
     inner class IrDefaultBitMaskValueImpl(
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerLambdaMemoization.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerLambdaMemoization.kt
index 1ecc29f..ef24c14 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerLambdaMemoization.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/lower/ComposerLambdaMemoization.kt
@@ -1035,9 +1035,9 @@
             val cacheTmpVar = irTemporary(cache, "tmpCache")
             cacheTmpVar.wrap(
                 type = expression.type,
-                before = listOf(irStartReplaceableGroup(irCurrentComposer(), irConst(key))),
+                before = listOf(irStartReplaceGroup(irCurrentComposer(), irConst(key))),
                 after = listOf(
-                    irEndReplaceableGroup(irCurrentComposer()),
+                    irEndReplaceGroup(irCurrentComposer()),
                     irGet(cacheTmpVar)
                 )
             )
diff --git a/compose/foundation/foundation-layout/build.gradle b/compose/foundation/foundation-layout/build.gradle
index 062412b..06cdd0c 100644
--- a/compose/foundation/foundation-layout/build.gradle
+++ b/compose/foundation/foundation-layout/build.gradle
@@ -41,9 +41,10 @@
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
 
-                api(project(":compose:ui:ui"))
-                implementation(project(":compose:runtime:runtime"))
+                api("androidx.compose.ui:ui:1.6.0")
+                implementation("androidx.compose.runtime:runtime:1.6.0")
                 implementation(project(":compose:ui:ui-util"))
+                implementation(project(":compose:ui:ui-unit"))
             }
         }
 
@@ -58,7 +59,6 @@
             }
         }
 
-
         androidMain {
             dependsOn(jvmMain)
             dependencies {
@@ -73,9 +73,6 @@
             dependsOn(jvmMain)
             dependencies {
                 implementation(libs.kotlinStdlib)
-
-                implementation(project(":compose:runtime:runtime"))
-                implementation(project(":compose:ui:ui-util"))
             }
         }
 
diff --git a/compose/foundation/foundation/api/current.txt b/compose/foundation/foundation/api/current.txt
index a7c0ace..6e67e8f 100644
--- a/compose/foundation/foundation/api/current.txt
+++ b/compose/foundation/foundation/api/current.txt
@@ -127,7 +127,7 @@
 
   public final class FocusableKt {
     method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier focusGroup(androidx.compose.ui.Modifier);
-    method public static androidx.compose.ui.Modifier focusable(androidx.compose.ui.Modifier, optional boolean enabled, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource);
+    method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier focusable(androidx.compose.ui.Modifier, optional boolean enabled, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource);
   }
 
   public final class FocusedBoundsKt {
@@ -135,7 +135,7 @@
   }
 
   public final class HoverableKt {
-    method public static androidx.compose.ui.Modifier hoverable(androidx.compose.ui.Modifier, androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional boolean enabled);
+    method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier hoverable(androidx.compose.ui.Modifier, androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional boolean enabled);
   }
 
   public final class ImageKt {
diff --git a/compose/foundation/foundation/api/restricted_current.txt b/compose/foundation/foundation/api/restricted_current.txt
index 078f45b..4be36a7 100644
--- a/compose/foundation/foundation/api/restricted_current.txt
+++ b/compose/foundation/foundation/api/restricted_current.txt
@@ -127,7 +127,7 @@
 
   public final class FocusableKt {
     method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier focusGroup(androidx.compose.ui.Modifier);
-    method public static androidx.compose.ui.Modifier focusable(androidx.compose.ui.Modifier, optional boolean enabled, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource);
+    method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier focusable(androidx.compose.ui.Modifier, optional boolean enabled, optional androidx.compose.foundation.interaction.MutableInteractionSource? interactionSource);
   }
 
   public final class FocusedBoundsKt {
@@ -135,7 +135,7 @@
   }
 
   public final class HoverableKt {
-    method public static androidx.compose.ui.Modifier hoverable(androidx.compose.ui.Modifier, androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional boolean enabled);
+    method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier hoverable(androidx.compose.ui.Modifier, androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional boolean enabled);
   }
 
   public final class ImageKt {
diff --git a/compose/foundation/foundation/build.gradle b/compose/foundation/foundation/build.gradle
index 8afc1b1..ab1f2c9 100644
--- a/compose/foundation/foundation/build.gradle
+++ b/compose/foundation/foundation/build.gradle
@@ -28,7 +28,6 @@
     id("AndroidXPlugin")
     id("com.android.library")
     id("AndroidXComposePlugin")
-    id("AndroidXPaparazziPlugin")
 }
 
 
@@ -43,11 +42,11 @@
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
                 api("androidx.collection:collection:1.4.0")
-                api(project(':compose:animation:animation'))
-                api(project(':compose:runtime:runtime'))
-                api(project(':compose:ui:ui'))
-                implementation(project(":compose:ui:ui-text"))
-                implementation(project(":compose:ui:ui-util"))
+                api(project(":compose:animation:animation"))
+                api("androidx.compose.runtime:runtime:1.6.0")
+                api(project(":compose:ui:ui"))
+                implementation("androidx.compose.ui:ui-text:1.6.0")
+                implementation("androidx.compose.ui:ui-util:1.6.0")
                 implementation(project(':compose:foundation:foundation-layout'))
             }
         }
@@ -79,8 +78,6 @@
             dependsOn(jvmMain)
             dependencies {
                 implementation(libs.kotlinStdlib)
-
-                implementation(project(":compose:ui:ui-util"))
             }
         }
 
@@ -124,8 +121,8 @@
                 implementation(libs.junit)
                 implementation(libs.truth)
                 implementation(libs.kotlinReflect)
-                implementation(libs.mockitoCore)
-                implementation(libs.mockitoKotlin)
+                implementation(libs.mockitoCore4)
+                implementation(libs.mockitoKotlin4)
                 implementation(project(":constraintlayout:constraintlayout-compose"))
             }
         }
diff --git a/compose/foundation/foundation/lint-baseline.xml b/compose/foundation/foundation/lint-baseline.xml
index 876590d..d6c663f 100644
--- a/compose/foundation/foundation/lint-baseline.xml
+++ b/compose/foundation/foundation/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="BanSuppressTag"
@@ -94,17 +94,8 @@
     <issue
         id="PrimitiveInCollection"
         message="field currentKeyPressInteractions with type Map&lt;Key, Press>: replace with LongObjectMap"
-        errorLine1="        val currentKeyPressInteractions = mutableMapOf&lt;Key, PressInteraction.Press>()"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="return type Map&lt;Key, Press> of getCurrentKeyPressInteractions: replace with LongObjectMap"
-        errorLine1="        val currentKeyPressInteractions = mutableMapOf&lt;Key, PressInteraction.Press>()"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="    private val currentKeyPressInteractions = mutableMapOf&lt;Key, PressInteraction.Press>()"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt"/>
     </issue>
@@ -616,15 +607,6 @@
     <issue
         id="PrimitiveInCollection"
         message="field baselineCache with type Map&lt;AlignmentLine, Integer>: replace with ObjectIntMap"
-        errorLine1="    private var baselineCache: Map&lt;AlignmentLine, Int>? = null"
-        errorLine2="                               ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/foundation/text/modifiers/TextAnnotatedStringNode.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="field baselineCache with type Map&lt;AlignmentLine, Integer>: replace with ObjectIntMap"
         errorLine1="    private var baselineCache: MutableMap&lt;AlignmentLine, Int>? = null"
         errorLine2="                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/ClickableTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/ClickableTest.kt
index 3143129..38b2b99 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/ClickableTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/ClickableTest.kt
@@ -40,6 +40,7 @@
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.setValue
+import androidx.compose.testutils.assertModifierIsPure
 import androidx.compose.testutils.first
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
@@ -2627,6 +2628,111 @@
             assertThat(interactions.first()).isInstanceOf(PressInteraction.Press::class.java)
         }
     }
+
+    @Test
+    fun composedOverload_nonEquality() {
+        val >
+        val modifier1 = Modifier.clickable(>
+        val modifier2 = Modifier.clickable(>
+
+        // The composed overload can never compare equal
+        assertThat(modifier1).isNotEqualTo(modifier2)
+    }
+
+    @Test
+    fun nullInteractionSourceNullIndication_equality() {
+        val >
+        assertModifierIsPure { toggleInput ->
+            Modifier.clickable(
+                interactionSource = null,
+                indication = null,
+                enabled = toggleInput,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun nonNullInteractionSourceNullIndication_equality() {
+        val >
+        val interactionSource = MutableInteractionSource()
+        assertModifierIsPure { toggleInput ->
+            Modifier.clickable(
+                interactionSource = interactionSource,
+                indication = null,
+                enabled = toggleInput,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun nullInteractionSourceNonNullIndicationNodeFactory_equality() {
+        val >
+        val indication = TestIndicationNodeFactory({}, { _, _ -> })
+        assertModifierIsPure { toggleInput ->
+            Modifier.clickable(
+                interactionSource = null,
+                indication = indication,
+                enabled = toggleInput,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun nullInteractionSourceNonNullIndication_nonEquality() {
+        val >
+        val indication = TestIndication {}
+        val modifier1 = Modifier.clickable(
+            interactionSource = null,
+            indication = indication,
+            >
+        )
+        val modifier2 = Modifier.clickable(
+            interactionSource = null,
+            indication = indication,
+            >
+        )
+
+        // Indication requires composed, so cannot compare equal
+        assertThat(modifier1).isNotEqualTo(modifier2)
+    }
+
+    @Test
+    fun nonNullInteractionSourceNonNullIndicationNodeFactory_equality() {
+        val >
+        val interactionSource = MutableInteractionSource()
+        val indication = TestIndicationNodeFactory({}, { _, _ -> })
+        assertModifierIsPure { toggleInput ->
+            Modifier.clickable(
+                interactionSource = interactionSource,
+                indication = indication,
+                enabled = toggleInput,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun nonNullInteractionSourceNonNullIndication_nonEquality() {
+        val >
+        val interactionSource = MutableInteractionSource()
+        val indication = TestIndication {}
+        val modifier1 = Modifier.clickable(
+            interactionSource = interactionSource,
+            indication = indication,
+            >
+        )
+        val modifier2 = Modifier.clickable(
+            interactionSource = interactionSource,
+            indication = indication,
+            >
+        )
+
+        // Indication requires composed, so cannot compare equal
+        assertThat(modifier1).isNotEqualTo(modifier2)
+    }
 }
 
 /**
@@ -2635,7 +2741,7 @@
  * @param onCreate lambda executed when the instance is created with [rememberUpdatedInstance]
  */
 @Suppress("DEPRECATION_ERROR")
-private class TestIndication(val onCreate: (InteractionSource) -> Unit) : Indication {
+internal class TestIndication(val onCreate: (InteractionSource) -> Unit) : Indication {
     @Deprecated("Super method is deprecated")
     @Composable
     override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance {
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/FocusableTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/FocusableTest.kt
index d1ebf73..38724ad 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/FocusableTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/FocusableTest.kt
@@ -35,6 +35,7 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.setValue
+import androidx.compose.testutils.assertModifierIsPure
 import androidx.compose.testutils.first
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
@@ -482,6 +483,17 @@
     }
 
     @Test
+    fun focusable_equality() {
+        val interactionSource = MutableInteractionSource()
+        assertModifierIsPure { toggleInput ->
+            Modifier.focusable(
+                enabled = toggleInput,
+                interactionSource = interactionSource,
+            )
+        }
+    }
+
+    @Test
     fun focusable_requestsBringIntoView_whenFocused() {
         // Arrange.
         val requestedRects = mutableListOf<Rect?>()
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/HoverableTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/HoverableTest.kt
index 5f0322e..cc2a51c 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/HoverableTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/HoverableTest.kt
@@ -27,6 +27,7 @@
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.setValue
+import androidx.compose.testutils.assertModifierIsPure
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
@@ -69,7 +70,7 @@
     }
 
     @Test
-    fun hoverableText_testInspectorValue() {
+    fun hoverableTest_testInspectorValue() {
         rule.setContent {
             val interactionSource = remember { MutableInteractionSource() }
             val modifier = Modifier.hoverable(interactionSource) as InspectableValue
@@ -83,6 +84,17 @@
         }
     }
 
+    @Test
+    fun hoverableTest_equality() {
+        val interactionSource = MutableInteractionSource()
+        assertModifierIsPure { toggleInput ->
+            Modifier.hoverable(
+                interactionSource = interactionSource,
+                enabled = toggleInput,
+            )
+        }
+    }
+
     @OptIn(ExperimentalTestApi::class)
     @ExperimentalComposeUiApi
     @Test
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridBeyondBoundsTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridBeyondBoundsTest.kt
index fda112e..5eccf0b 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridBeyondBoundsTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridBeyondBoundsTest.kt
@@ -22,8 +22,11 @@
 import androidx.compose.foundation.lazy.list.TrackPlacedElement
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.key
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
+import androidx.compose.testutils.ParameterizedComposeTestRule
+import androidx.compose.testutils.createParameterizedComposeTestRule
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Rect
@@ -37,8 +40,6 @@
 import androidx.compose.ui.layout.ModifierLocalBeyondBoundsLayout
 import androidx.compose.ui.modifier.modifierLocalConsumer
 import androidx.compose.ui.platform.LocalLayoutDirection
-import androidx.compose.ui.test.junit4.ComposeContentTestRule
-import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.LayoutDirection.Ltr
@@ -47,16 +48,13 @@
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
 
 @OptIn(ExperimentalComposeUiApi::class)
 @MediumTest
-@RunWith(Parameterized::class)
-class LazyStaggeredGridBeyondBoundsTest(param: Param) {
+class LazyStaggeredGridBeyondBoundsTest {
 
     @get:Rule
-    val rule = createComposeRule()
+    val rule = createParameterizedComposeTestRule<Param>()
 
     // We need to wrap the inline class parameter in another class because Java can't instantiate
     // the inline class.
@@ -68,21 +66,18 @@
         override fun toString() = "beyondBoundsLayoutDirection=$beyondBoundsLayoutDirection " +
             "reverseLayout=$reverseLayout " +
             "layoutDirection=$layoutDirection"
+
+        internal fun placementComparator(): PlacementComparator {
+            return PlacementComparator(beyondBoundsLayoutDirection, layoutDirection, reverseLayout)
+        }
     }
 
-    private val beyondBoundsLayoutDirection = param.beyondBoundsLayoutDirection
-    private val reverseLayout = param.reverseLayout
-    private val layoutDirection = param.layoutDirection
     private val placedItems = sortedMapOf<Int, Rect>()
     private var beyondBoundsLayout: BeyondBoundsLayout? = null
     private lateinit var lazyStaggeredGridState: LazyStaggeredGridState
-    private val placementComparator =
-        PlacementComparator(beyondBoundsLayoutDirection, layoutDirection, reverseLayout)
 
     companion object {
-        @JvmStatic
-        @Parameterized.Parameters(name = "{0}")
-        fun initParameters() = buildList {
+        val ParamsToTest = buildList {
             for (beyondBoundsLayoutDirection in listOf(Left, Right, Above, Below, Before, After)) {
                 for (reverseLayout in listOf(false, true)) {
                     for (layoutDirection in listOf(Ltr, Rtl)) {
@@ -93,6 +88,11 @@
         }
     }
 
+    private fun resetTestCase() {
+        placedItems.clear()
+        beyondBoundsLayout = null
+    }
+
     @Test
     fun onlyOneVisibleItemIsPlaced() {
         // Arrange.
@@ -107,9 +107,14 @@
         }
 
         // Assert.
-        rule.runOnIdle {
-            assertThat(placedItems.keys).containsExactly(0)
-            assertThat(visibleItems).containsExactly(0)
+        with(rule) {
+            forEachParameter(ParamsToTest) {
+                runOnIdle {
+                    assertThat(placedItems.keys).containsExactly(0)
+                    assertThat(visibleItems).containsExactly(0)
+                }
+                resetTestCase()
+            }
         }
     }
 
@@ -127,9 +132,14 @@
         }
 
         // Assert.
-        rule.runOnIdle {
-            assertThat(placedItems.keys).containsExactly(0, 1)
-            assertThat(visibleItems).containsExactly(0, 1)
+        with(rule) {
+            forEachParameter(ParamsToTest) {
+                runOnIdle {
+                    assertThat(placedItems.keys).containsExactly(0, 1)
+                    assertThat(visibleItems).containsExactly(0, 1)
+                }
+                resetTestCase()
+            }
         }
     }
 
@@ -147,9 +157,14 @@
         }
 
         // Assert.
-        rule.runOnIdle {
-            assertThat(placedItems.keys).containsExactly(0, 1, 2)
-            assertThat(visibleItems).containsExactly(0, 1, 2)
+        with(rule) {
+            forEachParameter(ParamsToTest) {
+                runOnIdle {
+                    assertThat(placedItems.keys).containsExactly(0, 1, 2)
+                    assertThat(visibleItems).containsExactly(0, 1, 2)
+                }
+                resetTestCase()
+            }
         }
     }
 
@@ -169,22 +184,29 @@
                 }
             }
         }
-        rule.runOnIdle {
-            beyondBoundsLayoutRef = beyondBoundsLayout!!
-            addItems = false
-        }
 
-        // Act.
-        val hasMoreContent = rule.runOnIdle {
-            beyondBoundsLayoutRef.layout(beyondBoundsLayoutDirection) {
-                hasMoreContent
+        with(rule) {
+            forEachParameter(ParamsToTest) { param ->
+                runOnIdle {
+                    beyondBoundsLayoutRef = beyondBoundsLayout!!
+                    addItems = false
+                }
+
+                // Act.
+                val hasMoreContent = rule.runOnIdle {
+                    beyondBoundsLayoutRef.layout(param.beyondBoundsLayoutDirection) {
+                        hasMoreContent
+                    }
+                }
+
+                // Assert.
+                runOnIdle {
+                    assertThat(hasMoreContent).isFalse()
+                }
+                resetTestCase()
+                addItems = true
             }
         }
-
-        // Assert.
-        rule.runOnIdle {
-            assertThat(hasMoreContent).isFalse()
-        }
     }
 
     @Test
@@ -199,188 +221,6 @@
                 )
             }
             item {
-                Box(Modifier
-                    .size(10.toDp())
-                    .trackPlaced(5)
-                    .modifierLocalConsumer {
-                        beyondBoundsLayout = ModifierLocalBeyondBoundsLayout.current
-                    }
-                )
-            }
-            items(5) { index ->
-                Box(
-                    Modifier
-                        .size(10.toDp())
-                        .trackPlaced(index + 6)
-                )
-            }
-        }
-
-        // Act.
-        rule.runOnUiThread {
-            beyondBoundsLayout!!.layout(beyondBoundsLayoutDirection) {
-                // Assert that the beyond bounds items are present.
-                if (expectedExtraItemsBeforeVisibleBounds()) {
-                    assertThat(placedItems.keys).containsExactly(4, 5, 6, 7)
-                } else {
-                    assertThat(placedItems.keys).containsExactly(5, 6, 7, 8)
-                }
-                assertThat(visibleItems).containsExactly(5, 6, 7)
-
-                assertThat(placedItems.values).isInOrder(placementComparator)
-
-                // Just return true so that we stop as soon as we run this once.
-                // This should result in one extra item being added.
-                true
-            }
-        }
-
-        // Assert that the beyond bounds items are removed.
-        rule.runOnIdle {
-            assertThat(placedItems.keys).containsExactly(5, 6, 7)
-            assertThat(visibleItems).containsExactly(5, 6, 7)
-        }
-    }
-
-    @Test
-    fun oneExtraItemBeyondVisibleBounds_multipleCells() {
-        val itemSize = 50
-        val itemSizeDp = itemSize.toDp()
-        // Arrange.
-        rule.setLazyContent(cells = 2, size = itemSizeDp * 3, firstVisibleItem = 10) {
-            // item | item  | x5
-            // item | local | x1
-            // item | item  | x5
-            items(11) { index ->
-                Box(
-                    Modifier
-                        .size(itemSizeDp)
-                        .trackPlaced(index)
-                )
-            }
-            item {
-                Box(Modifier
-                    .size(itemSizeDp)
-                    .trackPlaced(11)
-                    .modifierLocalConsumer {
-                        beyondBoundsLayout = ModifierLocalBeyondBoundsLayout.current
-                    }
-                )
-            }
-            items(10) { index ->
-                Box(
-                    Modifier
-                        .size(itemSizeDp)
-                        .trackPlaced(index + 12)
-                )
-            }
-        }
-
-        // Act.
-        rule.runOnUiThread {
-            beyondBoundsLayout!!.layout(beyondBoundsLayoutDirection) {
-                // Assert that the beyond bounds items are present.
-                if (expectedExtraItemsBeforeVisibleBounds()) {
-                    assertThat(placedItems.keys).containsExactly(9, 10, 11, 12, 13, 14, 15)
-                } else {
-                    assertThat(placedItems.keys).containsExactly(10, 11, 12, 13, 14, 15, 16)
-                }
-                assertThat(visibleItems).containsExactly(10, 11, 12, 13, 14, 15)
-
-                assertThat(placedItems.values).isInOrder(placementComparator)
-
-                // Just return true so that we stop as soon as we run this once.
-                // This should result in one extra item being added.
-                true
-            }
-        }
-
-        // Assert that the beyond bounds items are removed.
-        rule.runOnIdle {
-            assertThat(placedItems.keys).containsExactly(10, 11, 12, 13, 14, 15)
-            assertThat(visibleItems).containsExactly(10, 11, 12, 13, 14, 15)
-        }
-    }
-
-    @Test
-    fun oneExtraItemBeyondVisibleBounds_multipleCells_staggered() {
-        val itemSize = 50
-        val itemSizeDp = itemSize.toDp()
-        // Arrange.
-        rule.setLazyContent(cells = 3, size = itemSizeDp * 2, firstVisibleItem = 4) {
-            // -------------
-            // |   | 1 |   |
-            // | 0 |---| 2 |
-            // |   | 3 |   |
-            // |-----------|
-            // |     4     |
-            // |-----------|
-            // |   | 6 |   |
-            // | 5 |---| 7 |
-            // |   | 8 |   |
-            // -------------
-            items(4) { index ->
-                Box(
-                    Modifier
-                        .size(itemSizeDp * if (index % 2 == 0) 2f else 1f)
-                        .trackPlaced(index)
-                )
-            }
-            item(span = StaggeredGridItemSpan.FullLine) {
-                Box(Modifier
-                    .size(itemSizeDp)
-                    .trackPlaced(4)
-                    .modifierLocalConsumer {
-                        beyondBoundsLayout = ModifierLocalBeyondBoundsLayout.current
-                    }
-                )
-            }
-            items(4) { index ->
-                Box(
-                    Modifier
-                        .size(itemSizeDp * if (index % 2 == 0) 2f else 1f)
-                        .trackPlaced(index + 5)
-                )
-            }
-        }
-
-        // Act.
-        rule.runOnUiThread {
-            beyondBoundsLayout!!.layout(beyondBoundsLayoutDirection) {
-                // Assert that the beyond bounds items are present.
-                if (expectedExtraItemsBeforeVisibleBounds()) {
-                    assertThat(placedItems.keys).containsExactly(3, 4, 5, 6, 7)
-                    assertThat(visibleItems).containsExactly(4, 5, 6, 7)
-                } else {
-                    assertThat(placedItems.keys).containsExactly(4, 5, 6, 7, 8)
-                    assertThat(visibleItems).containsExactly(4, 5, 6, 7)
-                }
-                // Just return true so that we stop as soon as we run this once.
-                // This should result in one extra item being added.
-                true
-            }
-        }
-
-        // Assert that the beyond bounds items are removed.
-        rule.runOnIdle {
-            assertThat(placedItems.keys).containsExactly(4, 5, 6, 7)
-            assertThat(visibleItems).containsExactly(4, 5, 6, 7)
-        }
-    }
-
-    @Test
-    fun twoExtraItemsBeyondVisibleBounds() {
-        // Arrange.
-        var extraItemCount = 2
-        rule.setLazyContent(size = 30.toDp(), firstVisibleItem = 5) {
-            items(5) { index ->
-                Box(
-                    Modifier
-                        .size(10.toDp())
-                        .trackPlaced(index)
-                )
-            }
-            item {
                 Box(
                     Modifier
                         .size(10.toDp())
@@ -400,32 +240,237 @@
         }
 
         // Act.
-        rule.runOnUiThread {
-            beyondBoundsLayout!!.layout(beyondBoundsLayoutDirection) {
-                if (--extraItemCount > 0) {
-                    // Return null to continue the search.
-                    null
-                } else {
-                    // Assert that the beyond bounds items are present.
-                    if (expectedExtraItemsBeforeVisibleBounds()) {
-                        assertThat(placedItems.keys).containsExactly(3, 4, 5, 6, 7)
-                    } else {
-                        assertThat(placedItems.keys).containsExactly(5, 6, 7, 8, 9)
+        with(rule) {
+            forEachParameter(ParamsToTest) { param ->
+                runOnUiThread {
+                    beyondBoundsLayout!!.layout(param.beyondBoundsLayoutDirection) {
+                        // Assert that the beyond bounds items are present.
+                        if (param.expectedExtraItemsBeforeVisibleBounds()) {
+                            assertThat(placedItems.keys).containsExactly(4, 5, 6, 7)
+                        } else {
+                            assertThat(placedItems.keys).containsExactly(5, 6, 7, 8)
+                        }
+                        assertThat(visibleItems).containsExactly(5, 6, 7)
+
+                        assertThat(placedItems.values).isInOrder(param.placementComparator())
+
+                        // Just return true so that we stop as soon as we run this once.
+                        // This should result in one extra item being added.
+                        true
                     }
-                    assertThat(visibleItems).containsExactly(5, 6, 7)
-
-                    assertThat(placedItems.values).isInOrder(placementComparator)
-
-                    // Return true to stop the search.
-                    true
                 }
+
+                // Assert that the beyond bounds items are removed.
+                runOnIdle {
+                    assertThat(placedItems.keys).containsExactly(5, 6, 7)
+                    assertThat(visibleItems).containsExactly(5, 6, 7)
+                }
+                resetTestCase()
+            }
+        }
+    }
+
+    @Test
+    fun oneExtraItemBeyondVisibleBounds_multipleCells() {
+        val itemSize = 50
+        val itemSizeDp = itemSize.toDp()
+        // Arrange.
+        rule.setLazyContent(cells = 2, size = itemSizeDp * 3, firstVisibleItem = 10) {
+            // item | item  | x5
+            // item | local | x1
+            // item | item  | x5
+            items(11) { index ->
+                Box(
+                    Modifier
+                        .size(itemSizeDp)
+                        .trackPlaced(index)
+                )
+            }
+            item {
+                Box(
+                    Modifier
+                        .size(itemSizeDp)
+                        .trackPlaced(11)
+                        .modifierLocalConsumer {
+                            beyondBoundsLayout = ModifierLocalBeyondBoundsLayout.current
+                        }
+                )
+            }
+            items(10) { index ->
+                Box(
+                    Modifier
+                        .size(itemSizeDp)
+                        .trackPlaced(index + 12)
+                )
             }
         }
 
-        // Assert that the beyond bounds items are removed.
-        rule.runOnIdle {
-            assertThat(placedItems.keys).containsExactly(5, 6, 7)
-            assertThat(visibleItems).containsExactly(5, 6, 7)
+        // Act.
+        with(rule) {
+            forEachParameter(ParamsToTest) { param ->
+                runOnUiThread {
+                    beyondBoundsLayout!!.layout(param.beyondBoundsLayoutDirection) {
+                        // Assert that the beyond bounds items are present.
+                        if (param.expectedExtraItemsBeforeVisibleBounds()) {
+                            assertThat(placedItems.keys).containsExactly(9, 10, 11, 12, 13, 14, 15)
+                        } else {
+                            assertThat(placedItems.keys).containsExactly(10, 11, 12, 13, 14, 15, 16)
+                        }
+                        assertThat(visibleItems).containsExactly(10, 11, 12, 13, 14, 15)
+
+                        assertThat(placedItems.values).isInOrder(param.placementComparator())
+
+                        // Just return true so that we stop as soon as we run this once.
+                        // This should result in one extra item being added.
+                        true
+                    }
+                }
+
+                // Assert that the beyond bounds items are removed.
+                runOnIdle {
+                    assertThat(placedItems.keys).containsExactly(10, 11, 12, 13, 14, 15)
+                    assertThat(visibleItems).containsExactly(10, 11, 12, 13, 14, 15)
+                }
+                resetTestCase()
+            }
+        }
+    }
+
+    @Test
+    fun oneExtraItemBeyondVisibleBounds_multipleCells_staggered() {
+        val itemSize = 50
+        val itemSizeDp = itemSize.toDp()
+        // Arrange.
+        rule.setLazyContent(cells = 3, size = itemSizeDp * 2, firstVisibleItem = 4) {
+            // -------------
+            // |   | 1 |   |
+            // | 0 |---| 2 |
+            // |   | 3 |   |
+            // |-----------|
+            // |     4     |
+            // |-----------|
+            // |   | 6 |   |
+            // | 5 |---| 7 |
+            // |   | 8 |   |
+            // -------------
+            items(4) { index ->
+                Box(
+                    Modifier
+                        .size(itemSizeDp * if (index % 2 == 0) 2f else 1f)
+                        .trackPlaced(index)
+                )
+            }
+            item(span = StaggeredGridItemSpan.FullLine) {
+                Box(
+                    Modifier
+                        .size(itemSizeDp)
+                        .trackPlaced(4)
+                        .modifierLocalConsumer {
+                            beyondBoundsLayout = ModifierLocalBeyondBoundsLayout.current
+                        }
+                )
+            }
+            items(4) { index ->
+                Box(
+                    Modifier
+                        .size(itemSizeDp * if (index % 2 == 0) 2f else 1f)
+                        .trackPlaced(index + 5)
+                )
+            }
+        }
+
+        // Act.
+        with(rule) {
+            forEachParameter(ParamsToTest) { param ->
+                runOnUiThread {
+                    beyondBoundsLayout!!.layout(param.beyondBoundsLayoutDirection) {
+                        // Assert that the beyond bounds items are present.
+                        if (param.expectedExtraItemsBeforeVisibleBounds()) {
+                            assertThat(placedItems.keys).containsExactly(3, 4, 5, 6, 7)
+                            assertThat(visibleItems).containsExactly(4, 5, 6, 7)
+                        } else {
+                            assertThat(placedItems.keys).containsExactly(4, 5, 6, 7, 8)
+                            assertThat(visibleItems).containsExactly(4, 5, 6, 7)
+                        }
+                        // Just return true so that we stop as soon as we run this once.
+                        // This should result in one extra item being added.
+                        true
+                    }
+                }
+
+                // Assert that the beyond bounds items are removed.
+                runOnIdle {
+                    assertThat(placedItems.keys).containsExactly(4, 5, 6, 7)
+                    assertThat(visibleItems).containsExactly(4, 5, 6, 7)
+                }
+                resetTestCase()
+            }
+        }
+    }
+
+    @Test
+    fun twoExtraItemsBeyondVisibleBounds() {
+        // Arrange.
+        rule.setLazyContent(size = 30.toDp(), firstVisibleItem = 5) {
+            items(5) { index ->
+                Box(
+                    Modifier
+                        .size(10.toDp())
+                        .trackPlaced(index)
+                )
+            }
+            item {
+                Box(
+                    Modifier
+                        .size(10.toDp())
+                        .trackPlaced(5)
+                        .modifierLocalConsumer {
+                            beyondBoundsLayout = ModifierLocalBeyondBoundsLayout.current
+                        }
+                )
+            }
+            items(5) { index ->
+                Box(
+                    Modifier
+                        .size(10.toDp())
+                        .trackPlaced(index + 6)
+                )
+            }
+        }
+
+        // Act.
+        with(rule) {
+            forEachParameter(ParamsToTest) { param ->
+                var extraItemCount = 2
+                runOnUiThread {
+                    beyondBoundsLayout!!.layout(param.beyondBoundsLayoutDirection) {
+                        if (--extraItemCount > 0) {
+                            // Return null to continue the search.
+                            null
+                        } else {
+                            // Assert that the beyond bounds items are present.
+                            if (param.expectedExtraItemsBeforeVisibleBounds()) {
+                                assertThat(placedItems.keys).containsExactly(3, 4, 5, 6, 7)
+                            } else {
+                                assertThat(placedItems.keys).containsExactly(5, 6, 7, 8, 9)
+                            }
+                            assertThat(visibleItems).containsExactly(5, 6, 7)
+
+                            assertThat(placedItems.values).isInOrder(param.placementComparator())
+
+                            // Return true to stop the search.
+                            true
+                        }
+                    }
+                }
+
+                // Assert that the beyond bounds items are removed.
+                runOnIdle {
+                    assertThat(placedItems.keys).containsExactly(5, 6, 7)
+                    assertThat(visibleItems).containsExactly(5, 6, 7)
+                }
+                resetTestCase()
+            }
         }
     }
 
@@ -460,39 +505,45 @@
         }
 
         // Act.
-        rule.runOnUiThread {
-            beyondBoundsLayout!!.layout(beyondBoundsLayoutDirection) {
-                if (hasMoreContent) {
-                    // Just return null so that we keep adding more items till we reach the end.
-                    null
-                } else {
-                    // Assert that the beyond bounds items are present.
-                    if (expectedExtraItemsBeforeVisibleBounds()) {
-                        assertThat(placedItems.keys).containsExactly(0, 1, 2, 3, 4, 5, 6, 7)
-                    } else {
-                        assertThat(placedItems.keys).containsExactly(5, 6, 7, 8, 9, 10)
+        with(rule) {
+            forEachParameter(ParamsToTest) { param ->
+                runOnUiThread {
+                    beyondBoundsLayout!!.layout(param.beyondBoundsLayoutDirection) {
+                        if (hasMoreContent) {
+                            // Just return null so that we keep adding more items till we reach the end.
+                            null
+                        } else {
+                            // Assert that the beyond bounds items are present.
+                            if (param.expectedExtraItemsBeforeVisibleBounds()) {
+                                assertThat(placedItems.keys).containsExactly(0, 1, 2, 3, 4, 5, 6, 7)
+                            } else {
+                                assertThat(placedItems.keys).containsExactly(5, 6, 7, 8, 9, 10)
+                            }
+                            assertThat(visibleItems).containsExactly(5, 6, 7)
+
+                            // Verify if the placed item offsets are in order.
+                            assertThat(
+                                placedItems.toSortedMap().values
+                            ).isInOrder(param.placementComparator())
+
+                            // Return true to end the search.
+                            true
+                        }
                     }
-                    assertThat(visibleItems).containsExactly(5, 6, 7)
-
-                    // Verify if the placed item offsets are in order.
-                    assertThat(placedItems.toSortedMap().values).isInOrder(placementComparator)
-
-                    // Return true to end the search.
-                    true
                 }
-            }
-        }
 
-        // Assert that the beyond bounds items are removed.
-        rule.runOnIdle {
-            assertThat(placedItems.keys).containsExactly(5, 6, 7)
+                // Assert that the beyond bounds items are removed.
+                runOnIdle {
+                    assertThat(placedItems.keys).containsExactly(5, 6, 7)
+                }
+                resetTestCase()
+            }
         }
     }
 
     @Test
     fun beyondBoundsLayoutRequest_inDirectionPerpendicularToLazyListOrientation() {
         // Arrange.
-        var beyondBoundsLayoutCount = 0
         rule.setLazyContentInPerpendicularDirection(size = 30.toDp(), firstVisibleItem = 5) {
             items(5) { index ->
                 Box(
@@ -519,49 +570,58 @@
                 )
             }
         }
-        rule.runOnIdle {
-            assertThat(placedItems.keys).containsExactly(5, 6, 7)
-            assertThat(visibleItems).containsExactly(5, 6, 7)
-        }
-
-        // Act.
-        rule.runOnUiThread {
-            beyondBoundsLayout!!.layout(beyondBoundsLayoutDirection) {
-                beyondBoundsLayoutCount++
-                when (beyondBoundsLayoutDirection) {
-                    Left, Right, Above, Below -> {
-                        assertThat(placedItems.keys).containsExactly(5, 6, 7)
-                        assertThat(visibleItems).containsExactly(5, 6, 7)
-                    }
-                    Before, After -> {
-                        if (expectedExtraItemsBeforeVisibleBounds()) {
-                            assertThat(placedItems.keys).containsExactly(4, 5, 6, 7)
-                            assertThat(visibleItems).containsExactly(5, 6, 7)
-                        } else {
-                            assertThat(placedItems.keys).containsExactly(5, 6, 7, 8)
-                            assertThat(visibleItems).containsExactly(5, 6, 7)
-                        }
-                    }
-                }
-                // Just return true so that we stop as soon as we run this once.
-                // This should result in one extra item being added.
-                true
-            }
-        }
-
-        rule.runOnIdle {
-            when (beyondBoundsLayoutDirection) {
-                Left, Right, Above, Below -> {
-                    assertThat(beyondBoundsLayoutCount).isEqualTo(0)
-                }
-                Before, After -> {
-                    assertThat(beyondBoundsLayoutCount).isEqualTo(1)
-
-                    // Assert that the beyond bounds items are removed.
+        with(rule) {
+            forEachParameter(ParamsToTest) { param ->
+                var beyondBoundsLayoutCount = 0
+                runOnIdle {
                     assertThat(placedItems.keys).containsExactly(5, 6, 7)
                     assertThat(visibleItems).containsExactly(5, 6, 7)
                 }
-                else -> error("Unsupported BeyondBoundsLayoutDirection")
+
+                // Act.
+                runOnUiThread {
+                    beyondBoundsLayout!!.layout(param.beyondBoundsLayoutDirection) {
+                        beyondBoundsLayoutCount++
+                        when (param.beyondBoundsLayoutDirection) {
+                            Left, Right, Above, Below -> {
+                                assertThat(placedItems.keys).containsExactly(5, 6, 7)
+                                assertThat(visibleItems).containsExactly(5, 6, 7)
+                            }
+
+                            Before, After -> {
+                                if (param.expectedExtraItemsBeforeVisibleBounds()) {
+                                    assertThat(placedItems.keys).containsExactly(4, 5, 6, 7)
+                                    assertThat(visibleItems).containsExactly(5, 6, 7)
+                                } else {
+                                    assertThat(placedItems.keys).containsExactly(5, 6, 7, 8)
+                                    assertThat(visibleItems).containsExactly(5, 6, 7)
+                                }
+                            }
+                        }
+                        // Just return true so that we stop as soon as we run this once.
+                        // This should result in one extra item being added.
+                        true
+                    }
+                }
+
+                runOnIdle {
+                    when (param.beyondBoundsLayoutDirection) {
+                        Left, Right, Above, Below -> {
+                            assertThat(beyondBoundsLayoutCount).isEqualTo(0)
+                        }
+
+                        Before, After -> {
+                            assertThat(beyondBoundsLayoutCount).isEqualTo(1)
+
+                            // Assert that the beyond bounds items are removed.
+                            assertThat(placedItems.keys).containsExactly(5, 6, 7)
+                            assertThat(visibleItems).containsExactly(5, 6, 7)
+                        }
+
+                        else -> error("Unsupported BeyondBoundsLayoutDirection")
+                    }
+                }
+                resetTestCase()
             }
         }
     }
@@ -597,81 +657,95 @@
         }
 
         // Act.
-        var count = 0
-        rule.runOnUiThread {
-            beyondBoundsLayout!!.layout(beyondBoundsLayoutDirection) {
-                // Assert that we don't keep iterating when there is no ending condition.
-                assertThat(count++).isLessThan(lazyStaggeredGridState.layoutInfo.totalItemsCount)
-                // Always return null to continue the search.
-                null
-            }
-        }
+        with(rule) {
+            forEachParameter(ParamsToTest) { param ->
+                var count = 0
+                rule.runOnUiThread {
+                    beyondBoundsLayout!!.layout(param.beyondBoundsLayoutDirection) {
+                        // Assert that we don't keep iterating when there is no ending condition.
+                        assertThat(count++)
+                            .isLessThan(lazyStaggeredGridState.layoutInfo.totalItemsCount)
+                        // Always return null to continue the search.
+                        null
+                    }
+                }
 
-        // Assert that the beyond bounds items are removed.
-        rule.runOnIdle {
-            assertThat(placedItems.keys).containsExactly(5, 6, 7)
-            assertThat(visibleItems).containsExactly(5, 6, 7)
+                // Assert that the beyond bounds items are removed.
+                rule.runOnIdle {
+                    assertThat(placedItems.keys).containsExactly(5, 6, 7)
+                    assertThat(visibleItems).containsExactly(5, 6, 7)
+                }
+                resetTestCase()
+            }
         }
     }
 
-    private fun ComposeContentTestRule.setLazyContent(
+    private fun ParameterizedComposeTestRule<Param>.setLazyContent(
         size: Dp,
         firstVisibleItem: Int,
         cells: Int = 1,
         content: LazyStaggeredGridScope.() -> Unit
     ) {
         setContent {
-            CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
-                lazyStaggeredGridState = rememberLazyStaggeredGridState(firstVisibleItem)
-                when (beyondBoundsLayoutDirection) {
-                    Left, Right, Before, After ->
-                        LazyHorizontalStaggeredGrid(
-                            rows = StaggeredGridCells.Fixed(cells),
-                            modifier = Modifier.size(size),
-                            state = lazyStaggeredGridState,
-                            reverseLayout = reverseLayout,
-                            content = content
-                        )
-                    Above, Below ->
-                        LazyVerticalStaggeredGrid(
-                            columns = StaggeredGridCells.Fixed(cells),
-                            modifier = Modifier.size(size),
-                            state = lazyStaggeredGridState,
-                            reverseLayout = reverseLayout,
-                            content = content
-                        )
-                    else -> unsupportedDirection()
+            key(it) {
+                CompositionLocalProvider(LocalLayoutDirection provides it.layoutDirection) {
+                    lazyStaggeredGridState = rememberLazyStaggeredGridState(firstVisibleItem)
+                    when (it.beyondBoundsLayoutDirection) {
+                        Left, Right, Before, After ->
+                            LazyHorizontalStaggeredGrid(
+                                rows = StaggeredGridCells.Fixed(cells),
+                                modifier = Modifier.size(size),
+                                state = lazyStaggeredGridState,
+                                reverseLayout = it.reverseLayout,
+                                content = content
+                            )
+
+                        Above, Below ->
+                            LazyVerticalStaggeredGrid(
+                                columns = StaggeredGridCells.Fixed(cells),
+                                modifier = Modifier.size(size),
+                                state = lazyStaggeredGridState,
+                                reverseLayout = it.reverseLayout,
+                                content = content
+                            )
+
+                        else -> unsupportedDirection()
+                    }
                 }
             }
         }
     }
 
-    private fun ComposeContentTestRule.setLazyContentInPerpendicularDirection(
+    private fun ParameterizedComposeTestRule<Param>.setLazyContentInPerpendicularDirection(
         size: Dp,
         firstVisibleItem: Int,
         content: LazyStaggeredGridScope.() -> Unit
     ) {
         setContent {
-            CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) {
-                lazyStaggeredGridState = rememberLazyStaggeredGridState(firstVisibleItem)
-                when (beyondBoundsLayoutDirection) {
-                    Left, Right, Before, After ->
-                        LazyVerticalStaggeredGrid(
-                            columns = StaggeredGridCells.Fixed(1),
-                            modifier = Modifier.size(size),
-                            state = lazyStaggeredGridState,
-                            reverseLayout = reverseLayout,
-                            content = content
-                        )
-                    Above, Below ->
-                        LazyHorizontalStaggeredGrid(
-                            rows = StaggeredGridCells.Fixed(1),
-                            modifier = Modifier.size(size),
-                            state = lazyStaggeredGridState,
-                            reverseLayout = reverseLayout,
-                            content = content
-                        )
-                    else -> unsupportedDirection()
+            key(it) {
+                CompositionLocalProvider(LocalLayoutDirection provides it.layoutDirection) {
+                    lazyStaggeredGridState = rememberLazyStaggeredGridState(firstVisibleItem)
+                    when (it.beyondBoundsLayoutDirection) {
+                        Left, Right, Before, After ->
+                            LazyVerticalStaggeredGrid(
+                                columns = StaggeredGridCells.Fixed(1),
+                                modifier = Modifier.size(size),
+                                state = lazyStaggeredGridState,
+                                reverseLayout = it.reverseLayout,
+                                content = content
+                            )
+
+                        Above, Below ->
+                            LazyHorizontalStaggeredGrid(
+                                rows = StaggeredGridCells.Fixed(1),
+                                modifier = Modifier.size(size),
+                                state = lazyStaggeredGridState,
+                                reverseLayout = it.reverseLayout,
+                                content = content
+                            )
+
+                        else -> unsupportedDirection()
+                    }
                 }
             }
         }
@@ -682,7 +756,7 @@
     private val visibleItems: List<Int>
         get() = lazyStaggeredGridState.layoutInfo.visibleItemsInfo.map { it.index }
 
-    private fun expectedExtraItemsBeforeVisibleBounds() = when (beyondBoundsLayoutDirection) {
+    private fun Param.expectedExtraItemsBeforeVisibleBounds() = when (beyondBoundsLayoutDirection) {
         Right -> if (layoutDirection == Ltr) reverseLayout else !reverseLayout
         Left -> if (layoutDirection == Ltr) !reverseLayout else reverseLayout
         Above -> !reverseLayout
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/selection/SelectableTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/selection/SelectableTest.kt
index 52ea19d..effaf84 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/selection/SelectableTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/selection/SelectableTest.kt
@@ -18,6 +18,7 @@
 
 import android.os.Build.VERSION.SDK_INT
 import androidx.compose.foundation.TapIndicationDelay
+import androidx.compose.foundation.TestIndication
 import androidx.compose.foundation.TestIndicationNodeFactory
 import androidx.compose.foundation.interaction.FocusInteraction
 import androidx.compose.foundation.interaction.HoverInteraction
@@ -36,6 +37,7 @@
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.setValue
+import androidx.compose.testutils.assertModifierIsPure
 import androidx.compose.testutils.first
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
@@ -1191,4 +1193,113 @@
             assertThat(interactions.first()).isInstanceOf(PressInteraction.Press::class.java)
         }
     }
+
+    @Test
+    fun composedOverload_nonEquality() {
+        val >
+        val modifier1 = Modifier.selectable(selected = true, >
+        val modifier2 = Modifier.selectable(selected = true, >
+
+        // The composed overload can never compare equal
+        assertThat(modifier1).isNotEqualTo(modifier2)
+    }
+
+    @Test
+    fun nullInteractionSourceNullIndication_equality() {
+        val >
+        assertModifierIsPure { toggleInput ->
+            Modifier.selectable(
+                selected = toggleInput,
+                interactionSource = null,
+                indication = null,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun nonNullInteractionSourceNullIndication_equality() {
+        val >
+        val interactionSource = MutableInteractionSource()
+        assertModifierIsPure { toggleInput ->
+            Modifier.selectable(
+                selected = toggleInput,
+                interactionSource = interactionSource,
+                indication = null,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun nullInteractionSourceNonNullIndicationNodeFactory_equality() {
+        val >
+        val indication = TestIndicationNodeFactory({}, { _, _ -> })
+        assertModifierIsPure { toggleInput ->
+            Modifier.selectable(
+                selected = toggleInput,
+                interactionSource = null,
+                indication = indication,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun nullInteractionSourceNonNullIndication_nonEquality() {
+        val >
+        val indication = TestIndication {}
+        val modifier1 = Modifier.selectable(
+            selected = true,
+            interactionSource = null,
+            indication = indication,
+            >
+        )
+        val modifier2 = Modifier.selectable(
+            selected = true,
+            interactionSource = null,
+            indication = indication,
+            >
+        )
+
+        // Indication requires composed, so cannot compare equal
+        assertThat(modifier1).isNotEqualTo(modifier2)
+    }
+
+    @Test
+    fun nonNullInteractionSourceNonNullIndicationNodeFactory_equality() {
+        val >
+        val interactionSource = MutableInteractionSource()
+        val indication = TestIndicationNodeFactory({}, { _, _ -> })
+        assertModifierIsPure { toggleInput ->
+            Modifier.selectable(
+                selected = toggleInput,
+                interactionSource = interactionSource,
+                indication = indication,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun nonNullInteractionSourceNonNullIndication_nonEquality() {
+        val >
+        val interactionSource = MutableInteractionSource()
+        val indication = TestIndication {}
+        val modifier1 = Modifier.selectable(
+            selected = true,
+            interactionSource = interactionSource,
+            indication = indication,
+            >
+        )
+        val modifier2 = Modifier.selectable(
+            selected = true,
+            interactionSource = interactionSource,
+            indication = indication,
+            >
+        )
+
+        // Indication requires composed, so cannot compare equal
+        assertThat(modifier1).isNotEqualTo(modifier2)
+    }
 }
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/selection/ToggleableTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/selection/ToggleableTest.kt
index eb8c612..e95c2bd9 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/selection/ToggleableTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/selection/ToggleableTest.kt
@@ -18,6 +18,7 @@
 
 import android.os.Build.VERSION.SDK_INT
 import androidx.compose.foundation.TapIndicationDelay
+import androidx.compose.foundation.TestIndication
 import androidx.compose.foundation.TestIndicationNodeFactory
 import androidx.compose.foundation.interaction.FocusInteraction
 import androidx.compose.foundation.interaction.HoverInteraction
@@ -39,6 +40,7 @@
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.runtime.setValue
+import androidx.compose.testutils.assertModifierIsPure
 import androidx.compose.testutils.first
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
@@ -1410,7 +1412,7 @@
     }
 
     @Test
-    fun triStateToggleableTest_noInteractionSource_lazilyCreated_pointerInput() {
+    fun triStateToggleable_noInteractionSource_lazilyCreated_pointerInput() {
         var created = false
         val state = ToggleableState(value = false)
         lateinit var interactionSource: InteractionSource
@@ -1453,4 +1455,222 @@
             assertThat(interactions.first()).isInstanceOf(PressInteraction.Press::class.java)
         }
     }
+
+    @Test
+    fun toggleable_composedOverload_nonEquality() {
+        val onValueChange: (Boolean) -> Unit = {}
+        val modifier1 = Modifier.toggleable(value = true, >
+        val modifier2 = Modifier.toggleable(value = true, >
+
+        // The composed overload can never compare equal
+        assertThat(modifier1).isNotEqualTo(modifier2)
+    }
+
+    @Test
+    fun toggleable_nullInteractionSourceNullIndication_equality() {
+        val onValueChange: (Boolean) -> Unit = {}
+        assertModifierIsPure { toggleInput ->
+            Modifier.toggleable(
+                value = toggleInput,
+                interactionSource = null,
+                indication = null,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun toggleable_nonNullInteractionSourceNullIndication_equality() {
+        val onValueChange: (Boolean) -> Unit = {}
+        val interactionSource = MutableInteractionSource()
+        assertModifierIsPure { toggleInput ->
+            Modifier.toggleable(
+                value = toggleInput,
+                interactionSource = interactionSource,
+                indication = null,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun toggleable_nullInteractionSourceNonNullIndicationNodeFactory_equality() {
+        val onValueChange: (Boolean) -> Unit = {}
+        val indication = TestIndicationNodeFactory({}, { _, _ -> })
+        assertModifierIsPure { toggleInput ->
+            Modifier.toggleable(
+                value = toggleInput,
+                interactionSource = null,
+                indication = indication,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun toggleable_nullInteractionSourceNonNullIndication_nonEquality() {
+        val onValueChange: (Boolean) -> Unit = {}
+        val indication = TestIndication {}
+        val modifier1 = Modifier.toggleable(
+            value = true,
+            interactionSource = null,
+            indication = indication,
+            >
+        )
+        val modifier2 = Modifier.toggleable(
+            value = true,
+            interactionSource = null,
+            indication = indication,
+            >
+        )
+
+        // Indication requires composed, so cannot compare equal
+        assertThat(modifier1).isNotEqualTo(modifier2)
+    }
+
+    @Test
+    fun toggleable_nonNullInteractionSourceNonNullIndicationNodeFactory_equality() {
+        val onValueChange: (Boolean) -> Unit = {}
+        val interactionSource = MutableInteractionSource()
+        val indication = TestIndicationNodeFactory({}, { _, _ -> })
+        assertModifierIsPure { toggleInput ->
+            Modifier.toggleable(
+                value = toggleInput,
+                interactionSource = interactionSource,
+                indication = indication,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun toggleable_nonNullInteractionSourceNonNullIndication_nonEquality() {
+        val onValueChange: (Boolean) -> Unit = {}
+        val interactionSource = MutableInteractionSource()
+        val indication = TestIndication {}
+        val modifier1 = Modifier.toggleable(
+            value = true,
+            interactionSource = interactionSource,
+            indication = indication,
+            >
+        )
+        val modifier2 = Modifier.toggleable(
+            value = true,
+            interactionSource = interactionSource,
+            indication = indication,
+            >
+        )
+
+        // Indication requires composed, so cannot compare equal
+        assertThat(modifier1).isNotEqualTo(modifier2)
+    }
+
+    @Test
+    fun triStateToggleable_composedOverload_nonEquality() {
+        val >
+        val modifier1 = Modifier.triStateToggleable(state = ToggleableState.On, >
+        val modifier2 = Modifier.triStateToggleable(state = ToggleableState.On, >
+
+        // The composed overload can never compare equal
+        assertThat(modifier1).isNotEqualTo(modifier2)
+    }
+
+    @Test
+    fun triStateToggleable_nullInteractionSourceNullIndication_equality() {
+        val >
+        assertModifierIsPure { toggleInput ->
+            Modifier.triStateToggleable(
+                state = ToggleableState(toggleInput),
+                interactionSource = null,
+                indication = null,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun triStateToggleable_nonNullInteractionSourceNullIndication_equality() {
+        val >
+        val interactionSource = MutableInteractionSource()
+        assertModifierIsPure { toggleInput ->
+            Modifier.triStateToggleable(
+                state = ToggleableState(toggleInput),
+                interactionSource = interactionSource,
+                indication = null,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun triStateToggleable_nullInteractionSourceNonNullIndicationNodeFactory_equality() {
+        val >
+        val indication = TestIndicationNodeFactory({}, { _, _ -> })
+        assertModifierIsPure { toggleInput ->
+            Modifier.triStateToggleable(
+                state = ToggleableState(toggleInput),
+                interactionSource = null,
+                indication = indication,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun triStateToggleable_nullInteractionSourceNonNullIndication_nonEquality() {
+        val >
+        val indication = TestIndication {}
+        val modifier1 = Modifier.triStateToggleable(
+            state = ToggleableState.On,
+            interactionSource = null,
+            indication = indication,
+            >
+        )
+        val modifier2 = Modifier.triStateToggleable(
+            state = ToggleableState.On,
+            interactionSource = null,
+            indication = indication,
+            >
+        )
+
+        // Indication requires composed, so cannot compare equal
+        assertThat(modifier1).isNotEqualTo(modifier2)
+    }
+
+    @Test
+    fun triStateToggleable_nonNullInteractionSourceNonNullIndicationNodeFactory_equality() {
+        val >
+        val interactionSource = MutableInteractionSource()
+        val indication = TestIndicationNodeFactory({}, { _, _ -> })
+        assertModifierIsPure { toggleInput ->
+            Modifier.triStateToggleable(
+                state = ToggleableState(toggleInput),
+                interactionSource = interactionSource,
+                indication = indication,
+                >
+            )
+        }
+    }
+
+    @Test
+    fun triStateToggleable_nonNullInteractionSourceNonNullIndication_nonEquality() {
+        val >
+        val interactionSource = MutableInteractionSource()
+        val indication = TestIndication {}
+        val modifier1 = Modifier.triStateToggleable(
+            state = ToggleableState.On,
+            interactionSource = interactionSource,
+            indication = indication,
+            >
+        )
+        val modifier2 = Modifier.triStateToggleable(
+            state = ToggleableState.On,
+            interactionSource = interactionSource,
+            indication = indication,
+            >
+        )
+
+        // Indication requires composed, so cannot compare equal
+        assertThat(modifier1).isNotEqualTo(modifier2)
+    }
 }
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/TextFieldCursorTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/TextFieldCursorTest.kt
index 34a5847..fbb0eab 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/TextFieldCursorTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/TextFieldCursorTest.kt
@@ -754,7 +754,6 @@
             .assertDoesNotContainColor(cursorColor)
     }
 
-    @Ignore("b/305799612")
     @Test
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     fun focusedTextField_resumeBlinking_whenWindowRegainsFocus() {
diff --git a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/internal/undo/BasicTextField2UndoTest.kt b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/internal/undo/BasicTextField2UndoTest.kt
index ae68446..cdb3d02 100644
--- a/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/internal/undo/BasicTextField2UndoTest.kt
+++ b/compose/foundation/foundation/src/androidInstrumentedTest/kotlin/androidx/compose/foundation/text/input/internal/undo/BasicTextField2UndoTest.kt
@@ -40,6 +40,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import com.google.common.truth.Truth.assertThat
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -249,6 +250,7 @@
         assertThat(state.undoState.canUndo).isFalse()
     }
 
+    @Ignore("b/323405120")
     @Test
     fun clearHistory_removesAllUndoAndRedo() {
         val state = TextFieldState()
@@ -285,6 +287,7 @@
         }
     }
 
+    @Ignore("b/323344335")
     @Test
     fun paste_neverMerges() {
         val state = TextFieldState()
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text/input/internal/ToCharArray.android.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text/input/internal/ToCharArray.android.kt
index 968f6ec..700bbca 100644
--- a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text/input/internal/ToCharArray.android.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/text/input/internal/ToCharArray.android.kt
@@ -16,7 +16,6 @@
 
 package androidx.compose.foundation.text.input.internal
 
-import android.text.TextUtils
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.text.input.TextFieldCharSequence
 import androidx.compose.foundation.text.input.toCharArray
@@ -31,6 +30,9 @@
     if (this is TextFieldCharSequence) {
         toCharArray(destination, destinationOffset, startIndex, endIndex)
     } else {
-        TextUtils.getChars(this, startIndex, endIndex, destination, destinationOffset)
+        var dstIndex = destinationOffset
+        for (srcIndex in startIndex until endIndex) {
+            destination[dstIndex++] = this[srcIndex]
+        }
     }
 }
diff --git a/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/BasicTextPaparazziTest.kt b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/BasicTextPaparazziTest.kt
deleted file mode 100644
index c65c711..0000000
--- a/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/BasicTextPaparazziTest.kt
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.foundation.text
-
-import androidx.compose.foundation.background
-import androidx.compose.foundation.border
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.SideEffect
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.platform.LocalLayoutDirection
-import androidx.compose.ui.text.AnnotatedString
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.compose.ui.unit.dp
-import androidx.constraintlayout.compose.ConstraintLayout
-import androidx.constraintlayout.compose.Dimension
-import androidx.testutils.paparazzi.androidxPaparazzi
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class BasicTextPaparazziTest {
-    @get:Rule
-    val paparazzi = androidxPaparazzi()
-
-    @Test
-    fun colorChangingState_changesColor() {
-        paparazzi.snapshot {
-            var color = remember { mutableStateOf(Color.Red) }
-            BasicText(
-                "ABCD",
-                color = { color.value }
-            )
-            SideEffect {
-                color.value = Color.Yellow
-            }
-        }
-    }
-
-    @Test
-    fun colorChangingState_changesColor_annotatedString() {
-        paparazzi.snapshot {
-            var color = remember { mutableStateOf(Color.Red) }
-            BasicText(
-                AnnotatedString("ABCD"),
-                color = { color.value }
-            )
-            SideEffect {
-                color.value = Color.Yellow
-            }
-        }
-    }
-
-    @Test
-    fun overflowEllipsis_doesEllipsis_whenInPreferredWrapContent() {
-        paparazzi.snapshot {
-            // b/275369323
-            ConstraintLayout(modifier = Modifier
-                .width(100.dp)
-                .background(Color.White)
-                .padding(8.dp)) {
-                val (thumbnail, textBox, actionButton) = createRefs()
-                Box(modifier = Modifier
-                    .background(Color.Green)
-                    .constrainAs(thumbnail) {
-                        top.linkTo(parent.top)
-                        start.linkTo(parent.start)
-                        bottom.linkTo(parent.bottom)
-                    }
-                    .size(28.dp)
-                )
-                // Text region
-                Column(
-                    modifier = Modifier
-                        .constrainAs(textBox) {
-                            top.linkTo(parent.top)
-                            bottom.linkTo(parent.bottom)
-                            start.linkTo(thumbnail.end)
-                            end.linkTo(actionButton.start)
-                            width = Dimension.preferredWrapContent
-                        },
-                ) {
-                    BasicText(
-                        text = "ASome very long text that is sure to clip in this layout",
-                        maxLines = 1,
-                        overflow = TextOverflow.Ellipsis
-                    )
-                }
-                Box(modifier = Modifier
-                    .constrainAs(actionButton) {
-                        top.linkTo(parent.top)
-                        bottom.linkTo(parent.bottom)
-                        end.linkTo(parent.end)
-                    }
-                    .background(Color.Blue.copy(alpha = 0.5f))
-                    .size(28.dp)
-                )
-            }
-        }
-    }
-
-    @Test
-    fun RtlAppliedCorrectly_inConstraintLayout_withWrapContentText() {
-        // b/275369323
-        paparazzi.snapshot {
-            CompositionLocalProvider(
-                LocalLayoutDirection provides LayoutDirection.Rtl
-            ) {
-                ConstraintLayout(
-                    Modifier
-                        .fillMaxWidth()
-                        .background(Color.Green)) {
-                    val (title, progressBar, expander) = createRefs()
-                    BasicText(
-                        text = "Locale-aware Text",
-                        modifier = Modifier
-                            .constrainAs(title) {
-                                top.linkTo(parent.top)
-                                start.linkTo(parent.start)
-                                end.linkTo(expander.start)
-                                width = Dimension.fillToConstraints
-                            }
-                            .border(2.dp, Color.Red)
-                    )
-                    Box(
-                        modifier = Modifier
-                            .constrainAs(progressBar) {
-                                top.linkTo(title.bottom)
-                                start.linkTo(parent.start)
-                                end.linkTo(expander.start)
-                                width = Dimension.fillToConstraints
-                                height = Dimension.value(10.dp)
-                            }
-                            .background(Color.Yellow)
-                    )
-                    // expander image button
-                    Box(modifier = Modifier
-                        .constrainAs(expander) {
-                            top.linkTo(parent.top)
-                            start.linkTo(progressBar.end)
-                            end.linkTo(parent.end)
-                            width = Dimension.value(28.dp)
-                            height = Dimension.value(28.dp)
-                        }
-                        .background(Color.Cyan)
-                    )
-                }
-            }
-        }
-    }
-}
diff --git a/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/internal/CursorAnimationStateTest.kt b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/internal/CursorAnimationStateTest.kt
new file mode 100644
index 0000000..58920e6
--- /dev/null
+++ b/compose/foundation/foundation/src/androidUnitTest/kotlin/androidx/compose/foundation/text/input/internal/CursorAnimationStateTest.kt
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text.input.internal
+
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.Test
+import kotlinx.coroutines.CoroutineStart
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(JUnit4::class)
+class CursorAnimationStateTest {
+
+    private val animationState = CursorAnimationState()
+
+    @Test
+    fun alphaNotAnimatingInitially() = runTest {
+        assertNotAnimating()
+    }
+
+    @Test
+    fun snapToVisibleAndAnimate_animatesAlpha() = runTest {
+        val job = launch {
+            animationState.snapToVisibleAndAnimate()
+        }
+
+        // Should start immediately.
+        assertThat(animationState.cursorAlpha).isEqualTo(0f)
+        runCurrent()
+
+        // Then let's verify a few blinks…
+        assertThat(animationState.cursorAlpha).isEqualTo(1f)
+        testScheduler.advanceTimeBy(500)
+        assertThat(animationState.cursorAlpha).isEqualTo(1f)
+        testScheduler.advanceTimeBy(500)
+        assertThat(animationState.cursorAlpha).isEqualTo(0f)
+        testScheduler.advanceTimeBy(500)
+        assertThat(animationState.cursorAlpha).isEqualTo(1f)
+
+        job.cancel()
+    }
+
+    @Test
+    fun snapToVisibleAndAnimate_suspendsWhileAnimating() = runTest {
+        val job = launch(start = CoroutineStart.UNDISPATCHED) {
+            animationState.snapToVisibleAndAnimate()
+        }
+
+        // Advance a few blinks.
+        repeat(10) {
+            testScheduler.advanceTimeBy(500)
+            assertThat(job.isActive).isTrue()
+        }
+
+        job.cancel()
+    }
+
+    @Test
+    fun snapToVisibleAndAnimate_stopsAnimating_whenCancelledImmediately() = runTest {
+        val job = launch(start = CoroutineStart.UNDISPATCHED) {
+            animationState.snapToVisibleAndAnimate()
+        }
+        job.cancel()
+
+        assertNotAnimating()
+        assertThat(job.isActive).isFalse()
+    }
+
+    @Test
+    fun snapToVisibleAndAnimate_stopsAnimating_whenCancelledAsync() = runTest {
+        val job = launch {
+            animationState.snapToVisibleAndAnimate()
+        }
+        job.cancel()
+
+        assertNotAnimating()
+        assertThat(job.isActive).isFalse()
+    }
+
+    @Test
+    fun snapToVisibleAndAnimate_stopsAnimating_whenCancelledAfterAWhile() = runTest {
+        val job = launch(start = CoroutineStart.UNDISPATCHED) {
+            animationState.snapToVisibleAndAnimate()
+        }
+
+        // Advance a few blinks…
+        repeat(10) {
+            testScheduler.advanceTimeBy(500)
+        }
+        job.cancel()
+
+        assertNotAnimating()
+    }
+
+    @Test
+    fun cancelAndHide_stopsAnimating_immediately() = runTest {
+        val job = launch(start = CoroutineStart.UNDISPATCHED) {
+            animationState.snapToVisibleAndAnimate()
+        }
+        animationState.cancelAndHide()
+
+        assertNotAnimating()
+        assertThat(job.isActive).isFalse()
+    }
+
+    @Test
+    fun cancelAndHide_beforeStart_doesntBlockAnimation() = runTest {
+        animationState.cancelAndHide()
+        val job = launch {
+            animationState.snapToVisibleAndAnimate()
+        }
+
+        runCurrent()
+        assertThat(animationState.cursorAlpha).isEqualTo(1f)
+
+        job.cancel()
+    }
+
+    @Test
+    fun cancelAndHide_stopsAnimating_afterAWhile() = runTest {
+        val job = launch(start = CoroutineStart.UNDISPATCHED) {
+            animationState.snapToVisibleAndAnimate()
+        }
+
+        // Advance a few blinks…
+        repeat(10) {
+            testScheduler.advanceTimeBy(500)
+        }
+        animationState.cancelAndHide()
+
+        assertNotAnimating()
+        assertThat(job.isActive).isFalse()
+    }
+
+    private fun TestScope.assertNotAnimating() {
+        // Allow the cancellation to process.
+        advanceUntilIdle()
+
+        // Verify a few blinks.
+        repeat(10) {
+            assertThat(animationState.cursorAlpha).isEqualTo(0f)
+            testScheduler.advanceTimeBy(490)
+        }
+    }
+}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt
index 3666e2e..1fabc9c 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Clickable.kt
@@ -497,7 +497,6 @@
         )
     }
 
-    // Defined in the factory functions with inspectable
     override fun InspectorInfo.inspectableProperties() {
         name = "clickable"
         properties["enabled"] = enabled
@@ -573,7 +572,6 @@
         )
     }
 
-    // Defined in the factory functions with inspectable
     override fun InspectorInfo.inspectableProperties() {
         name = "combinedClickable"
         properties["indicationNodeFactory"] = indicationNodeFactory
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Focusable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Focusable.kt
index 59c5297..cd801d5 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Focusable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Focusable.kt
@@ -65,6 +65,7 @@
  * @param interactionSource [MutableInteractionSource] that will be used to emit
  * [FocusInteraction.Focus] when this element is being focused.
  */
+@Stable
 fun Modifier.focusable(
     enabled: Boolean = true,
     interactionSource: MutableInteractionSource? = null,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Hoverable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Hoverable.kt
index c0180eb..00adcf2 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Hoverable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Hoverable.kt
@@ -18,6 +18,7 @@
 
 import androidx.compose.foundation.interaction.HoverInteraction
 import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.runtime.Stable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.input.pointer.PointerEvent
 import androidx.compose.ui.input.pointer.PointerEventPass
@@ -37,6 +38,7 @@
  * [HoverInteraction.Enter] when this element is being hovered.
  * @param enabled Controls the enabled state. When `false`, hover events will be ignored.
  */
+@Stable
 fun Modifier.hoverable(
     interactionSource: MutableInteractionSource,
     enabled: Boolean = true
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextFieldCursor.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextFieldCursor.kt
index 4fda9bf..68272fc 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextFieldCursor.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/TextFieldCursor.kt
@@ -16,10 +16,10 @@
 
 package androidx.compose.foundation.text
 
-import androidx.compose.animation.core.Animatable
 import androidx.compose.animation.core.AnimationSpec
 import androidx.compose.animation.core.infiniteRepeatable
 import androidx.compose.animation.core.keyframes
+import androidx.compose.foundation.text.input.internal.CursorAnimationState
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
@@ -31,11 +31,10 @@
 import androidx.compose.ui.graphics.Brush
 import androidx.compose.ui.graphics.SolidColor
 import androidx.compose.ui.graphics.isUnspecified
+import androidx.compose.ui.platform.LocalWindowInfo
 import androidx.compose.ui.text.input.OffsetMapping
 import androidx.compose.ui.text.input.TextFieldValue
 import androidx.compose.ui.unit.dp
-import androidx.compose.ui.util.fastCoerceIn
-import kotlinx.coroutines.withContext
 
 internal fun Modifier.cursor(
     state: LegacyTextFieldState,
@@ -44,21 +43,20 @@
     cursorBrush: Brush,
     enabled: Boolean
 ) = if (enabled) composed {
-    val cursorAlpha = remember { Animatable(1f) }
+    val cursorAnimation = remember { CursorAnimationState() }
+    // Don't bother animating the cursor if it wouldn't draw any pixels.
     val isBrushSpecified = !(cursorBrush is SolidColor && cursorBrush.value.isUnspecified)
-    if (state.hasFocus && value.selection.collapsed && isBrushSpecified) {
+    // Only animate the cursor when its window is actually focused. This also disables the cursor
+    // animation when the screen is off.
+    // TODO confirm screen-off behavior.
+    val isWindowFocused = LocalWindowInfo.current.isWindowFocused
+    if (isWindowFocused && state.hasFocus && value.selection.collapsed && isBrushSpecified) {
         LaunchedEffect(value.annotatedString, value.selection) {
-            // Animate the cursor even when animations are disabled by the system.
-            withContext(FixedMotionDurationScale) {
-                // ensure that the value is always 1f _this_ frame by calling snapTo
-                cursorAlpha.snapTo(1f)
-                // then start the cursor blinking on animation clock (500ms on to start)
-                cursorAlpha.animateTo(0f, cursorAnimationSpec)
-            }
+            cursorAnimation.snapToVisibleAndAnimate()
         }
         drawWithContent {
             this.drawContent()
-            val cursorAlphaValue = cursorAlpha.value.fastCoerceIn(0f, 1f)
+            val cursorAlphaValue = cursorAnimation.cursorAlpha
             if (cursorAlphaValue != 0f) {
                 val transformedOffset = offsetMapping
                     .originalToTransformed(value.selection.start)
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/internal/CursorAnimationState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/internal/CursorAnimationState.kt
new file mode 100644
index 0000000..e9898ab
--- /dev/null
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/internal/CursorAnimationState.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.foundation.text.input.internal
+
+import androidx.compose.foundation.AtomicReference
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableFloatStateOf
+import androidx.compose.runtime.setValue
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.cancelAndJoin
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+
+/**
+ * Holds the state of the animation that blinks the cursor.
+ *
+ * We can't use the Compose Animation APIs because they busy-loop on delays, and this animation
+ * spends most of its time delayed so that's a ton of wasted frames. Pure coroutine delays, however,
+ * will not cause any work to be done until the delay is over.
+ */
+internal class CursorAnimationState {
+
+    private var animationJob = AtomicReference<Job?>(null)
+
+    /**
+     * The alpha value that should be used to draw the cursor.
+     * Will always be in the range [0, 1].
+     */
+    var cursorAlpha by mutableFloatStateOf(0f)
+        private set
+
+    /**
+     * Immediately shows the cursor (sets [cursorAlpha] to 1f) and starts blinking it on and off
+     * every 500ms. If a previous animation was running, it will be cancelled before the new one
+     * starts.
+     *
+     * Won't return until the animation cancelled via [cancelAndHide] or this coroutine's [Job] is
+     * cancelled. In both cases, the cursor will always end up hidden.
+     */
+    suspend fun snapToVisibleAndAnimate() {
+        coroutineScope {
+            // Can't do a single atomic update because we need to get the old value before launching
+            // the new coroutine. So we set to null first, and then launch only if still null (i.e.
+            // no other caller beat us to starting a new animation).
+            val oldJob = animationJob.getAndSet(null)
+
+            // Even though we're launching a new coroutine, because of structured concurrency, the
+            // restart function won't return until the animation is finished, and cancelling the
+            // calling coroutine will cancel the animation.
+            animationJob.compareAndSet(null, launch {
+                // Join the old job after cancelling to ensure it finishes its finally block before
+                // we start changing the cursor alpha, so we don't end up interleaving alpha
+                // updates.
+                oldJob?.cancelAndJoin()
+
+                // Start the new animation and run until cancelled.
+                try {
+                    while (true) {
+                        cursorAlpha = 1f
+                        // Ignore MotionDurationScale – the cursor should blink even when animations
+                        // are disabled by the system.
+                        delay(500)
+                        cursorAlpha = 0f
+                        delay(500)
+                    }
+                } finally {
+                    // Hide cursor when the animation is cancelled.
+                    cursorAlpha = 0f
+                }
+            })
+        }
+    }
+
+    /**
+     * Immediately cancels the cursor animation and hides the cursor (sets [cursorAlpha] to 0f).
+     */
+    fun cancelAndHide() {
+        val job = animationJob.getAndSet(null)
+        job?.cancel()
+    }
+}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldCoreModifier.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldCoreModifier.kt
index 18b6885..48d9bbd 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldCoreModifier.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text/input/internal/TextFieldCoreModifier.kt
@@ -16,10 +16,6 @@
 
 package androidx.compose.foundation.text.input.internal
 
-import androidx.compose.animation.core.Animatable
-import androidx.compose.animation.core.AnimationSpec
-import androidx.compose.animation.core.infiniteRepeatable
-import androidx.compose.animation.core.keyframes
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.ScrollState
 import androidx.compose.foundation.gestures.Orientation
@@ -29,7 +25,6 @@
 import androidx.compose.foundation.text.input.internal.selection.textFieldMagnifierNode
 import androidx.compose.foundation.text.selection.LocalTextSelectionColors
 import androidx.compose.runtime.snapshotFlow
-import androidx.compose.ui.MotionDurationScale
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.graphics.Brush
 import androidx.compose.ui.graphics.Color
@@ -52,6 +47,7 @@
 import androidx.compose.ui.node.currentValueOf
 import androidx.compose.ui.node.invalidateMeasurement
 import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.platform.LocalWindowInfo
 import androidx.compose.ui.semantics.SemanticsPropertyReceiver
 import androidx.compose.ui.text.TextLayoutResult
 import androidx.compose.ui.text.TextPainter
@@ -60,7 +56,6 @@
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
-import androidx.compose.ui.util.fastCoerceIn
 import kotlin.math.ceil
 import kotlin.math.floor
 import kotlin.math.min
@@ -69,7 +64,6 @@
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
 
 /**
  * Modifier element for the core functionality of [BasicTextField2] that is passed as inner
@@ -146,7 +140,7 @@
      * another half a second when TextField is focused and editable. Initial value should be 0f
      * so that when cursor needs to be drawn for the first time, change to 1f invalidates draw.
      */
-    private val cursorAlpha = Animatable(0f)
+    private val cursorAnimation = CursorAnimationState()
 
     /**
      * Whether to show cursor at all when TextField has focus. This depends on enabled, read only,
@@ -221,7 +215,7 @@
         if (!showCursor) {
             changeObserverJob?.cancel()
             changeObserverJob = null
-            coroutineScope.launch { cursorAlpha.snapTo(0f) }
+            cursorAnimation.cancelAndHide()
         } else if (!wasFocused ||
             previousTextFieldState != textFieldState ||
             !previousShowCursor
@@ -229,15 +223,17 @@
             // this node is writeable, focused and gained that focus just now.
             // start the state value observation
             changeObserverJob = coroutineScope.launch {
-                // Animate the cursor even when animations are disabled by the system.
-                withContext(FixedMotionDurationScale) {
-                    snapshotFlow { textFieldState.visualText }
-                        .collectLatest {
-                            // ensure that the value is always 1f _this_ frame by calling snapTo
-                            cursorAlpha.snapTo(1f)
-                            // then start the cursor blinking on animation clock (500ms on to start)
-                            cursorAlpha.animateTo(0f, cursorAnimationSpec)
-                        }
+                snapshotFlow {
+                    // Read the text state, so the animation restarts when the text or cursor
+                    // position change.
+                    textFieldState.visualText
+                    // Only animate the cursor when its window is actually focused. This also
+                    // disables the cursor animation when the screen is off.
+                    currentValueOf(LocalWindowInfo).isWindowFocused
+                }.collectLatest { isWindowFocused ->
+                    if (isWindowFocused) {
+                        cursorAnimation.snapToVisibleAndAnimate()
+                    }
                 }
             }
         }
@@ -443,10 +439,7 @@
             // this call will respect the earlier set maxValue
             // no need to coerce again.
             // prefer to use immediate dispatch instead of suspending scroll calls
-            coroutineScope.launch(
-                DisabledMotionDurationScale,
-                start = CoroutineStart.UNDISPATCHED
-            ) {
+            coroutineScope.launch(start = CoroutineStart.UNDISPATCHED) {
                 scrollState.scrollBy(offsetDifference.roundToNext())
                 // make sure to use the cursor rect from text layout since bringIntoView does its
                 // own checks for RTL layouts.
@@ -488,12 +481,9 @@
     private fun DrawScope.drawCursor() {
         // Only draw cursor if it can be shown and its alpha is higher than 0f
         // Alpha is checked before showCursor purposefully to make sure that we read
-        // cursorAlpha.value in draw phase. So, when the alpha value changes, draw phase
-        // invalidates.
-        if (cursorAlpha.value <= 0f || !showCursor) return
-
-        val cursorAlphaValue = cursorAlpha.value.fastCoerceIn(0f, 1f)
-        if (cursorAlphaValue == 0f) return
+        // cursorAlpha in draw phase. So, when the alpha value changes, draw phase invalidates.
+        val cursorAlphaValue = cursorAnimation.cursorAlpha
+        if (cursorAlphaValue == 0f || !showCursor) return
 
         val cursorRect = textFieldSelectionState.cursorRect
 
@@ -516,16 +506,6 @@
     }
 }
 
-private val cursorAnimationSpec: AnimationSpec<Float> = infiniteRepeatable(
-    animation = keyframes {
-        durationMillis = 1000
-        1f at 0
-        1f at 499
-        0f at 500
-        0f at 999
-    }
-)
-
 private val DefaultCursorThickness = 2.dp
 
 /**
@@ -534,16 +514,6 @@
 private val Brush.isSpecified: Boolean
     get() = !(this is SolidColor && this.value.isUnspecified)
 
-private object FixedMotionDurationScale : MotionDurationScale {
-    override val scaleFactor: Float
-        get() = 1f
-}
-
-private object DisabledMotionDurationScale : MotionDurationScale {
-    override val scaleFactor: Float
-        get() = 0f
-}
-
 /**
  * Converts cursorRect in text layout coordinates to scroller coordinates by adding the default
  * cursor thickness and calculating the relative positioning caused by the layout direction.
diff --git a/compose/material/material/build.gradle b/compose/material/material/build.gradle
index 7234f90..21f35fb2 100644
--- a/compose/material/material/build.gradle
+++ b/compose/material/material/build.gradle
@@ -28,7 +28,6 @@
     id("AndroidXPlugin")
     id("com.android.library")
     id("AndroidXComposePlugin")
-    id("AndroidXPaparazziPlugin")
 }
 
 androidXMultiplatform {
@@ -49,6 +48,7 @@
                 api("androidx.compose.ui:ui:1.6.0")
                 api("androidx.compose.ui:ui-text:1.6.0")
 
+                implementation(project(":compose:animation:animation-core"))
                 implementation("androidx.compose.animation:animation:1.6.0")
                 implementation("androidx.compose.foundation:foundation-layout:1.6.0")
                 implementation("androidx.compose.ui:ui-util:1.6.0")
diff --git a/compose/material/material/src/androidUnitTest/kotlin/androidx/compose/material/ButtonPaparazziScreenshotTest.kt b/compose/material/material/src/androidUnitTest/kotlin/androidx/compose/material/ButtonPaparazziScreenshotTest.kt
deleted file mode 100644
index 1aec7be..0000000
--- a/compose/material/material/src/androidUnitTest/kotlin/androidx/compose/material/ButtonPaparazziScreenshotTest.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material
-
-import androidx.testutils.paparazzi.androidxPaparazzi
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class ButtonPaparazziScreenshotTest {
-    @get:Rule
-    val paparazzi = androidxPaparazzi()
-
-    @Test
-    fun default_button() {
-        paparazzi.snapshot {
-            MaterialTheme {
-                Surface {
-                    Button( }) {
-                        Text("Button")
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/compose/material3/material3-adaptive/OWNERS b/compose/material3/adaptive/OWNERS
similarity index 100%
rename from compose/material3/material3-adaptive/OWNERS
rename to compose/material3/adaptive/OWNERS
diff --git a/compose/material3/adaptive/adaptive-layout/api/current.txt b/compose/material3/adaptive/adaptive-layout/api/current.txt
new file mode 100644
index 0000000..34e7c93
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-layout/api/current.txt
@@ -0,0 +1,173 @@
+// Signature format: 4.0
+package androidx.compose.material3.adaptive.layout {
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public interface AdaptStrategy {
+    method public String adapt();
+    field public static final androidx.compose.material3.adaptive.layout.AdaptStrategy.Companion Companion;
+  }
+
+  public static final class AdaptStrategy.Companion {
+    method public androidx.compose.material3.adaptive.layout.AdaptStrategy getHide();
+    property public final androidx.compose.material3.adaptive.layout.AdaptStrategy Hide;
+  }
+
+  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class HingePolicy {
+    field public static final androidx.compose.material3.adaptive.layout.HingePolicy.Companion Companion;
+  }
+
+  public static final class HingePolicy.Companion {
+    method public int getAlwaysAvoid();
+    method public int getAvoidOccluding();
+    method public int getAvoidSeparating();
+    method public int getNeverAvoid();
+    property public final int AlwaysAvoid;
+    property public final int AvoidOccluding;
+    property public final int AvoidSeparating;
+    property public final int NeverAvoid;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ListDetailPaneScaffoldDefaults {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies(optional androidx.compose.material3.adaptive.layout.AdaptStrategy detailPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy listPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy extraPaneAdaptStrategy);
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldDefaults INSTANCE;
+  }
+
+  public final class ListDetailPaneScaffoldKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> listPane, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit>? extraPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> detailPane);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState calculateListDetailPaneScaffoldState(optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<?> currentDestination, optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState calculateListDetailPaneScaffoldState(java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<?>> destinationHistory, optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ListDetailPaneScaffoldRole {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getDetail();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getExtra();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getList();
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Detail;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Extra;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole List;
+    field public static final androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole INSTANCE;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @kotlin.jvm.JvmInline public final value class PaneAdaptedValue {
+    field public static final androidx.compose.material3.adaptive.layout.PaneAdaptedValue.Companion Companion;
+  }
+
+  public static final class PaneAdaptedValue.Companion {
+    method public String getExpanded();
+    method public String getHidden();
+    property public final String Expanded;
+    property public final String Hidden;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class PaneScaffoldDirective {
+    ctor public PaneScaffoldDirective(androidx.compose.foundation.layout.PaddingValues contentPadding, int maxHorizontalPartitions, float horizontalPartitionSpacerSize, int maxVerticalPartitions, float verticalPartitionSpacerSize, java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds);
+    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
+    method public java.util.List<androidx.compose.ui.geometry.Rect> getExcludedBounds();
+    method public float getHorizontalPartitionSpacerSize();
+    method public int getMaxHorizontalPartitions();
+    method public int getMaxVerticalPartitions();
+    method public float getVerticalPartitionSpacerSize();
+    property public final androidx.compose.foundation.layout.PaddingValues contentPadding;
+    property public final java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds;
+    property public final float horizontalPartitionSpacerSize;
+    property public final int maxHorizontalPartitions;
+    property public final int maxVerticalPartitions;
+    property public final float verticalPartitionSpacerSize;
+  }
+
+  public final class PaneScaffoldDirectiveKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.PaneScaffoldDirective calculateDensePaneScaffoldDirective(androidx.compose.material3.adaptive.WindowAdaptiveInfo windowAdaptiveInfo, optional int verticalHingePolicy);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.PaneScaffoldDirective calculateStandardPaneScaffoldDirective(androidx.compose.material3.adaptive.WindowAdaptiveInfo windowAdaptiveInfo, optional int verticalHingePolicy);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public interface PaneScaffoldScope {
+    method public androidx.compose.ui.Modifier preferredWidth(androidx.compose.ui.Modifier, float width);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldDefaults {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies(optional androidx.compose.material3.adaptive.layout.AdaptStrategy mainPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy supportingPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy extraPaneAdaptStrategy);
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldDefaults INSTANCE;
+  }
+
+  public final class SupportingPaneScaffoldKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit>? extraPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> mainPane);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState calculateSupportingPaneScaffoldState(optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<?> currentDestination, optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState calculateSupportingPaneScaffoldState(java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<?>> destinationHistory, optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldRole {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getExtra();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getMain();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getSupporting();
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Extra;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Main;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Supporting;
+    field public static final androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole INSTANCE;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldAdaptStrategies {
+    ctor public ThreePaneScaffoldAdaptStrategies(androidx.compose.material3.adaptive.layout.AdaptStrategy primaryPaneAdaptStrategy, androidx.compose.material3.adaptive.layout.AdaptStrategy secondaryPaneAdaptStrategy, androidx.compose.material3.adaptive.layout.AdaptStrategy tertiaryPaneAdaptStrategy);
+    method public operator androidx.compose.material3.adaptive.layout.AdaptStrategy get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldDestinationItem<T> {
+    ctor public ThreePaneScaffoldDestinationItem(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole pane, optional T? content);
+    method public T? getContent();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getPane();
+    property public final T? content;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole pane;
+  }
+
+  public final class ThreePaneScaffoldKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void AnimatedPane(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope, androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> content);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public enum ThreePaneScaffoldRole {
+    method public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole[] values();
+    enum_constant public static final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Primary;
+    enum_constant public static final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Secondary;
+    enum_constant public static final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Tertiary;
+  }
+
+  public interface ThreePaneScaffoldScope extends androidx.compose.material3.adaptive.layout.PaneScaffoldScope {
+    method public String getAnimationToolingLabel();
+    method public androidx.compose.animation.EnterTransition getEnterTransition();
+    method public androidx.compose.animation.ExitTransition getExitTransition();
+    method public String getPaneAdaptedValue();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>? getPositionAnimationSpec();
+    property public abstract String animationToolingLabel;
+    property public abstract androidx.compose.animation.EnterTransition enterTransition;
+    property public abstract androidx.compose.animation.ExitTransition exitTransition;
+    property public abstract String paneAdaptedValue;
+    property public abstract androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>? positionAnimationSpec;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public interface ThreePaneScaffoldState {
+    method public androidx.compose.material3.adaptive.layout.PaneScaffoldDirective getScaffoldDirective();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue getScaffoldValue();
+    property public abstract androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective;
+    property public abstract androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue scaffoldValue;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class ThreePaneScaffoldValue {
+    ctor public ThreePaneScaffoldValue(String primary, String secondary, String tertiary);
+    method public operator String get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role);
+    method public String getPrimary();
+    method public String getSecondary();
+    method public String getTertiary();
+    property public final String primary;
+    property public final String secondary;
+    property public final String tertiary;
+  }
+
+  public final class ThreePaneScaffoldValueKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue calculateThreePaneScaffoldValue(int maxHorizontalPartitions, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<?>? currentDestination);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue calculateThreePaneScaffoldValue(int maxHorizontalPartitions, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<?>> destinationHistory);
+  }
+
+}
+
diff --git a/compose/material3/material3-adaptive/api/res-current.txt b/compose/material3/adaptive/adaptive-layout/api/res-current.txt
similarity index 100%
copy from compose/material3/material3-adaptive/api/res-current.txt
copy to compose/material3/adaptive/adaptive-layout/api/res-current.txt
diff --git a/compose/material3/adaptive/adaptive-layout/api/restricted_current.txt b/compose/material3/adaptive/adaptive-layout/api/restricted_current.txt
new file mode 100644
index 0000000..34e7c93
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-layout/api/restricted_current.txt
@@ -0,0 +1,173 @@
+// Signature format: 4.0
+package androidx.compose.material3.adaptive.layout {
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public interface AdaptStrategy {
+    method public String adapt();
+    field public static final androidx.compose.material3.adaptive.layout.AdaptStrategy.Companion Companion;
+  }
+
+  public static final class AdaptStrategy.Companion {
+    method public androidx.compose.material3.adaptive.layout.AdaptStrategy getHide();
+    property public final androidx.compose.material3.adaptive.layout.AdaptStrategy Hide;
+  }
+
+  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class HingePolicy {
+    field public static final androidx.compose.material3.adaptive.layout.HingePolicy.Companion Companion;
+  }
+
+  public static final class HingePolicy.Companion {
+    method public int getAlwaysAvoid();
+    method public int getAvoidOccluding();
+    method public int getAvoidSeparating();
+    method public int getNeverAvoid();
+    property public final int AlwaysAvoid;
+    property public final int AvoidOccluding;
+    property public final int AvoidSeparating;
+    property public final int NeverAvoid;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ListDetailPaneScaffoldDefaults {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies(optional androidx.compose.material3.adaptive.layout.AdaptStrategy detailPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy listPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy extraPaneAdaptStrategy);
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldDefaults INSTANCE;
+  }
+
+  public final class ListDetailPaneScaffoldKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> listPane, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit>? extraPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> detailPane);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState calculateListDetailPaneScaffoldState(optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<?> currentDestination, optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState calculateListDetailPaneScaffoldState(java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<?>> destinationHistory, optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ListDetailPaneScaffoldRole {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getDetail();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getExtra();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getList();
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Detail;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Extra;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole List;
+    field public static final androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole INSTANCE;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @kotlin.jvm.JvmInline public final value class PaneAdaptedValue {
+    field public static final androidx.compose.material3.adaptive.layout.PaneAdaptedValue.Companion Companion;
+  }
+
+  public static final class PaneAdaptedValue.Companion {
+    method public String getExpanded();
+    method public String getHidden();
+    property public final String Expanded;
+    property public final String Hidden;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class PaneScaffoldDirective {
+    ctor public PaneScaffoldDirective(androidx.compose.foundation.layout.PaddingValues contentPadding, int maxHorizontalPartitions, float horizontalPartitionSpacerSize, int maxVerticalPartitions, float verticalPartitionSpacerSize, java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds);
+    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
+    method public java.util.List<androidx.compose.ui.geometry.Rect> getExcludedBounds();
+    method public float getHorizontalPartitionSpacerSize();
+    method public int getMaxHorizontalPartitions();
+    method public int getMaxVerticalPartitions();
+    method public float getVerticalPartitionSpacerSize();
+    property public final androidx.compose.foundation.layout.PaddingValues contentPadding;
+    property public final java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds;
+    property public final float horizontalPartitionSpacerSize;
+    property public final int maxHorizontalPartitions;
+    property public final int maxVerticalPartitions;
+    property public final float verticalPartitionSpacerSize;
+  }
+
+  public final class PaneScaffoldDirectiveKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.PaneScaffoldDirective calculateDensePaneScaffoldDirective(androidx.compose.material3.adaptive.WindowAdaptiveInfo windowAdaptiveInfo, optional int verticalHingePolicy);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.PaneScaffoldDirective calculateStandardPaneScaffoldDirective(androidx.compose.material3.adaptive.WindowAdaptiveInfo windowAdaptiveInfo, optional int verticalHingePolicy);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public interface PaneScaffoldScope {
+    method public androidx.compose.ui.Modifier preferredWidth(androidx.compose.ui.Modifier, float width);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldDefaults {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies(optional androidx.compose.material3.adaptive.layout.AdaptStrategy mainPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy supportingPaneAdaptStrategy, optional androidx.compose.material3.adaptive.layout.AdaptStrategy extraPaneAdaptStrategy);
+    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
+    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
+    field public static final androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldDefaults INSTANCE;
+  }
+
+  public final class SupportingPaneScaffoldKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit>? extraPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> mainPane);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState calculateSupportingPaneScaffoldState(optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<?> currentDestination, optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState calculateSupportingPaneScaffoldState(java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<?>> destinationHistory, optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldRole {
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getExtra();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getMain();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getSupporting();
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Extra;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Main;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Supporting;
+    field public static final androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole INSTANCE;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldAdaptStrategies {
+    ctor public ThreePaneScaffoldAdaptStrategies(androidx.compose.material3.adaptive.layout.AdaptStrategy primaryPaneAdaptStrategy, androidx.compose.material3.adaptive.layout.AdaptStrategy secondaryPaneAdaptStrategy, androidx.compose.material3.adaptive.layout.AdaptStrategy tertiaryPaneAdaptStrategy);
+    method public operator androidx.compose.material3.adaptive.layout.AdaptStrategy get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldDestinationItem<T> {
+    ctor public ThreePaneScaffoldDestinationItem(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole pane, optional T? content);
+    method public T? getContent();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole getPane();
+    property public final T? content;
+    property public final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole pane;
+  }
+
+  public final class ThreePaneScaffoldKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void AnimatedPane(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope, androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope,kotlin.Unit> content);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public enum ThreePaneScaffoldRole {
+    method public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole[] values();
+    enum_constant public static final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Primary;
+    enum_constant public static final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Secondary;
+    enum_constant public static final androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole Tertiary;
+  }
+
+  public interface ThreePaneScaffoldScope extends androidx.compose.material3.adaptive.layout.PaneScaffoldScope {
+    method public String getAnimationToolingLabel();
+    method public androidx.compose.animation.EnterTransition getEnterTransition();
+    method public androidx.compose.animation.ExitTransition getExitTransition();
+    method public String getPaneAdaptedValue();
+    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>? getPositionAnimationSpec();
+    property public abstract String animationToolingLabel;
+    property public abstract androidx.compose.animation.EnterTransition enterTransition;
+    property public abstract androidx.compose.animation.ExitTransition exitTransition;
+    property public abstract String paneAdaptedValue;
+    property public abstract androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>? positionAnimationSpec;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public interface ThreePaneScaffoldState {
+    method public androidx.compose.material3.adaptive.layout.PaneScaffoldDirective getScaffoldDirective();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue getScaffoldValue();
+    property public abstract androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective;
+    property public abstract androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue scaffoldValue;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class ThreePaneScaffoldValue {
+    ctor public ThreePaneScaffoldValue(String primary, String secondary, String tertiary);
+    method public operator String get(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole role);
+    method public String getPrimary();
+    method public String getSecondary();
+    method public String getTertiary();
+    property public final String primary;
+    property public final String secondary;
+    property public final String tertiary;
+  }
+
+  public final class ThreePaneScaffoldValueKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue calculateThreePaneScaffoldValue(int maxHorizontalPartitions, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<?>? currentDestination);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue calculateThreePaneScaffoldValue(int maxHorizontalPartitions, androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<?>> destinationHistory);
+  }
+
+}
+
diff --git a/compose/material3/material3-adaptive/build.gradle b/compose/material3/adaptive/adaptive-layout/build.gradle
similarity index 90%
copy from compose/material3/material3-adaptive/build.gradle
copy to compose/material3/adaptive/adaptive-layout/build.gradle
index cbd842e..ec87135 100644
--- a/compose/material3/material3-adaptive/build.gradle
+++ b/compose/material3/adaptive/adaptive-layout/build.gradle
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@
  */
 import androidx.build.LibraryType
 import androidx.build.PlatformIdentifier
-import androidx.build.Publish
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
 plugins {
@@ -43,6 +42,7 @@
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
                 api("androidx.compose.foundation:foundation:1.6.0-rc01")
+                api(project(":compose:material3:adaptive:adaptive"))
                 implementation("androidx.compose.foundation:foundation-layout:1.6.0-rc01")
                 implementation("androidx.compose.ui:ui-util:1.6.0-rc01")
                 // TODO(conradchen): pin the depe when the change required is released to public
@@ -67,7 +67,6 @@
             dependencies {
                 api("androidx.annotation:annotation:1.1.0")
                 api("androidx.annotation:annotation-experimental:1.4.0")
-                implementation("androidx.window:window:1.2.0")
             }
         }
 
@@ -110,12 +109,11 @@
 }
 
 android {
-    namespace "androidx.compose.material3.adaptive"
+    namespace "androidx.compose.material3.adaptive.layout"
 }
 
 androidx {
     name = "Material Adaptive"
-    mavenVersion = LibraryVersions.COMPOSE_MATERIAL3_ADAPTIVE
     type = LibraryType.PUBLISHED_LIBRARY
     inceptionYear = "2023"
     description = "Compose Material Design Adaptive Library"
@@ -128,6 +126,6 @@
 // Screenshot tests related setup
 android {
     sourceSets.androidTest.assets.srcDirs +=
-            project.rootDir.absolutePath + "/../../golden/compose/material3/material3-adaptive"
-    namespace "androidx.compose.material3.adaptive"
+            project.rootDir.absolutePath + "/../../golden/compose/material3/adaptive"
+    namespace "androidx.compose.material3.adaptive.layout"
 }
diff --git a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/GoldenCommon.kt b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/GoldenCommon.kt
similarity index 90%
rename from compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/GoldenCommon.kt
rename to compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/GoldenCommon.kt
index a693e3a..f16ff5e 100644
--- a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/GoldenCommon.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/GoldenCommon.kt
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
-internal const val GOLDEN_MATERIAL3_ADAPTIVE = "compose/material3/material3-adaptive"
+internal const val GOLDEN_MATERIAL3_ADAPTIVE = "compose/material3/adaptive"
diff --git a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/LargeScreenTestUtils.kt b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/LargeScreenTestUtils.kt
similarity index 90%
rename from compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/LargeScreenTestUtils.kt
rename to compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/LargeScreenTestUtils.kt
index 8ed7c70..5dfa0175 100644
--- a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/LargeScreenTestUtils.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/LargeScreenTestUtils.kt
@@ -14,11 +14,13 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
+import androidx.compose.material3.adaptive.currentWindowSize
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.ui.Modifier
diff --git a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/ListDetailPaneScaffoldStateTest.kt b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ListDetailPaneScaffoldStateTest.kt
similarity index 89%
rename from compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/ListDetailPaneScaffoldStateTest.kt
rename to compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ListDetailPaneScaffoldStateTest.kt
index 01bd1f7..77df51f 100644
--- a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/ListDetailPaneScaffoldStateTest.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ListDetailPaneScaffoldStateTest.kt
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
 import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -72,8 +73,10 @@
         composeRule.setContent {
             scaffoldState = calculateListDetailPaneScaffoldState(
                 scaffoldDirective = MockSinglePaneScaffoldDirective,
-                currentDestination =
-                    ThreePaneScaffoldDestinationItem(ListDetailPaneScaffoldRole.Detail, null)
+                currentDestination = ThreePaneScaffoldDestinationItem(
+                    ListDetailPaneScaffoldRole.Detail,
+                    null
+                )
             )
         }
 
@@ -90,8 +93,10 @@
         composeRule.setContent {
             scaffoldState = calculateListDetailPaneScaffoldState(
                 scaffoldDirective = MockDualPaneScaffoldDirective,
-                currentDestination =
-                    ThreePaneScaffoldDestinationItem(ListDetailPaneScaffoldRole.Extra, null)
+                currentDestination = ThreePaneScaffoldDestinationItem(
+                    ListDetailPaneScaffoldRole.Extra,
+                    null
+                )
             )
         }
 
diff --git a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/SupportingPaneScaffoldStateTest.kt b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/SupportingPaneScaffoldStateTest.kt
similarity index 89%
rename from compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/SupportingPaneScaffoldStateTest.kt
rename to compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/SupportingPaneScaffoldStateTest.kt
index 169ccb9..fc8bb82 100644
--- a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/SupportingPaneScaffoldStateTest.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/SupportingPaneScaffoldStateTest.kt
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
 import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -72,8 +73,10 @@
         composeRule.setContent {
             scaffoldState = calculateSupportingPaneScaffoldState(
                 scaffoldDirective = MockSinglePaneScaffoldDirective,
-                currentDestination =
-                    ThreePaneScaffoldDestinationItem(SupportingPaneScaffoldRole.Supporting, null)
+                currentDestination = ThreePaneScaffoldDestinationItem(
+                    SupportingPaneScaffoldRole.Supporting,
+                    null
+                )
             )
         }
 
@@ -90,8 +93,10 @@
         composeRule.setContent {
             scaffoldState = calculateSupportingPaneScaffoldState(
                 scaffoldDirective = MockDualPaneScaffoldDirective,
-                currentDestination =
-                    ThreePaneScaffoldDestinationItem(SupportingPaneScaffoldRole.Extra, null)
+                currentDestination = ThreePaneScaffoldDestinationItem(
+                    SupportingPaneScaffoldRole.Extra,
+                    null
+                )
             )
         }
 
diff --git a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldScreenshotTest.kt b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScreenshotTest.kt
similarity index 96%
rename from compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldScreenshotTest.kt
rename to compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScreenshotTest.kt
index 1659ae5..c707ab5 100644
--- a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldScreenshotTest.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScreenshotTest.kt
@@ -14,10 +14,12 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
 import android.os.Build
 import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
+import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
 import androidx.compose.runtime.Composable
 import androidx.compose.testutils.assertAgainstGolden
 import androidx.compose.ui.test.captureToImage
diff --git a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldTest.kt b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldTest.kt
similarity index 98%
rename from compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldTest.kt
rename to compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldTest.kt
index f142449..57db5ac 100644
--- a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldTest.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.WindowInsets
@@ -24,6 +24,7 @@
 import androidx.compose.foundation.layout.union
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Surface
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
diff --git a/compose/material3/material3-adaptive/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/PaneScaffoldDirectiveTest.kt b/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirectiveTest.kt
similarity index 97%
rename from compose/material3/material3-adaptive/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/PaneScaffoldDirectiveTest.kt
rename to compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirectiveTest.kt
index f40a549..2813adb 100644
--- a/compose/material3/material3-adaptive/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/PaneScaffoldDirectiveTest.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirectiveTest.kt
@@ -14,8 +14,12 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
+import androidx.compose.material3.adaptive.HingeInfo
+import androidx.compose.material3.adaptive.Posture
+import androidx.compose.material3.adaptive.WindowAdaptiveInfo
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
diff --git a/compose/material3/material3-adaptive/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/ThreePaneMotionTest.kt b/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneMotionTest.kt
similarity index 98%
rename from compose/material3/material3-adaptive/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/ThreePaneMotionTest.kt
rename to compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneMotionTest.kt
index f8d2333..cf50df31 100644
--- a/compose/material3/material3-adaptive/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/ThreePaneMotionTest.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneMotionTest.kt
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/compose/material3/material3-adaptive/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldValueTest.kt b/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldValueTest.kt
similarity index 97%
rename from compose/material3/material3-adaptive/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldValueTest.kt
rename to compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldValueTest.kt
index b2b2fba..48dbd86 100644
--- a/compose/material3/material3-adaptive/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldValueTest.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/androidUnitTest/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldValueTest.kt
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/AdaptStrategy.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/AdaptStrategy.kt
similarity index 92%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/AdaptStrategy.kt
rename to compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/AdaptStrategy.kt
index 550ffda..6f73836 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/AdaptStrategy.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/AdaptStrategy.kt
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
+
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 
 /**
  * Provides the information about how the associated pane should be adapted if it cannot be
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/AnimateBoundsModifier.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/AnimateBoundsModifier.kt
similarity index 98%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/AnimateBoundsModifier.kt
rename to compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/AnimateBoundsModifier.kt
index 43c39b7..0e97207 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/AnimateBoundsModifier.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/AnimateBoundsModifier.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
 import androidx.compose.animation.core.Animatable
 import androidx.compose.animation.core.AnimationVector
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ListDetailPaneScaffold.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ListDetailPaneScaffold.kt
similarity index 97%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ListDetailPaneScaffold.kt
rename to compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ListDetailPaneScaffold.kt
index 690c11b..e6d9904 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ListDetailPaneScaffold.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ListDetailPaneScaffold.kt
@@ -14,13 +14,15 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
 import androidx.compose.foundation.layout.WindowInsets
 import androidx.compose.foundation.layout.displayCutout
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.systemBars
 import androidx.compose.foundation.layout.union
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
+import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/PaneAdaptedValue.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneAdaptedValue.kt
similarity index 90%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/PaneAdaptedValue.kt
rename to compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneAdaptedValue.kt
index 5d21a80..54501b1 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/PaneAdaptedValue.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneAdaptedValue.kt
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
+
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 
 /**
  * The adapted state of a pane. It gives clues to pane scaffolds about if a certain pane should be
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/PaneScaffold.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.kt
similarity index 96%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/PaneScaffold.kt
rename to compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.kt
index a25f6b9..57f1ad7 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/PaneScaffold.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffold.kt
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.node.ModifierNodeElement
 import androidx.compose.ui.node.ParentDataModifierNode
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/PaneScaffoldDirective.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirective.kt
similarity index 92%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/PaneScaffoldDirective.kt
rename to compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirective.kt
index 272dffd..18bc602 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/PaneScaffoldDirective.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/PaneScaffoldDirective.kt
@@ -14,9 +14,16 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
 import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
+import androidx.compose.material3.adaptive.Posture
+import androidx.compose.material3.adaptive.WindowAdaptiveInfo
+import androidx.compose.material3.adaptive.allVerticalHingeBounds
+import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
+import androidx.compose.material3.adaptive.occludingVerticalHingeBounds
+import androidx.compose.material3.adaptive.separatingVerticalHingeBounds
 import androidx.compose.runtime.Immutable
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.unit.Dp
@@ -25,7 +32,7 @@
 
 /**
  * Calculates the standard [PaneScaffoldDirective] from a given [WindowAdaptiveInfo]. Use this
- * method with [calculateWindowAdaptiveInfo] to acquire Material-recommended adaptive layout
+ * method with [currentWindowAdaptiveInfo] to acquire Material-recommended adaptive layout
  * settings of the current activity window.
  *
  * See more details on the [Material design guideline site]
@@ -87,7 +94,7 @@
 
 /**
  * Calculates the dense-mode [PaneScaffoldDirective] from a given [WindowAdaptiveInfo]. Use this
- * method with [calculateWindowAdaptiveInfo] to acquire Material-recommended dense-mode adaptive
+ * method with [currentWindowAdaptiveInfo] to acquire Material-recommended dense-mode adaptive
  * layout settings of the current activity window.
  *
  * See more details on the [Material design guideline site]
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/SupportingPaneScaffold.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/SupportingPaneScaffold.kt
similarity index 97%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/SupportingPaneScaffold.kt
rename to compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/SupportingPaneScaffold.kt
index 6cc19e6..7764d64 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/SupportingPaneScaffold.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/SupportingPaneScaffold.kt
@@ -14,13 +14,15 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
 import androidx.compose.foundation.layout.WindowInsets
 import androidx.compose.foundation.layout.displayCutout
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.systemBars
 import androidx.compose.foundation.layout.union
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
+import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffold.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffold.kt
similarity index 99%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffold.kt
rename to compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffold.kt
index ecea8a9..d17b2c6 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffold.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffold.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
 import androidx.annotation.VisibleForTesting
 import androidx.compose.animation.AnimatedVisibility
@@ -28,6 +28,7 @@
 import androidx.compose.animation.slideInHorizontally
 import androidx.compose.animation.slideOutHorizontally
 import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.getValue
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldAdaptStrategies.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldAdaptStrategies.kt
similarity index 94%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldAdaptStrategies.kt
rename to compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldAdaptStrategies.kt
index b0f43b1..62fd21c 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldAdaptStrategies.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldAdaptStrategies.kt
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
+
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 
 /**
  * The adaptation specs of [ThreePaneScaffold]. This class denotes how each pane of
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldDestinationItem.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldDestinationItem.kt
similarity index 73%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldDestinationItem.kt
rename to compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldDestinationItem.kt
index 6ff7e00..797a08f 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldDestinationItem.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldDestinationItem.kt
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
-import androidx.compose.runtime.saveable.Saver
-import androidx.compose.runtime.saveable.listSaver
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 
 /**
  * An item representing a navigation destination in a [ThreePaneScaffold].
@@ -31,19 +30,6 @@
     val pane: ThreePaneScaffoldRole,
     val content: T? = null,
 ) {
-    companion object {
-        internal fun <T> saver(): Saver<ThreePaneScaffoldDestinationItem<T>, Any> = listSaver(
-            save = { listOf(it.pane, it.content) },
-            restore = {
-                @Suppress("UNCHECKED_CAST")
-                ThreePaneScaffoldDestinationItem(
-                    pane = it[0] as ThreePaneScaffoldRole,
-                    content = it[1] as T?
-                )
-            }
-        )
-    }
-
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (other !is ThreePaneScaffoldDestinationItem<*>) return false
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldHorizontalOrder.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldHorizontalOrder.kt
similarity index 96%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldHorizontalOrder.kt
rename to compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldHorizontalOrder.kt
index 131e717..589c663 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldHorizontalOrder.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldHorizontalOrder.kt
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 import androidx.compose.runtime.Immutable
 import androidx.compose.ui.unit.LayoutDirection
 
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldState.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldState.kt
similarity index 92%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldState.kt
rename to compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldState.kt
index 4e02b85..8d4bc0f 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldState.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldState.kt
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 import androidx.compose.runtime.Stable
 
 /**
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldValue.kt b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldValue.kt
similarity index 98%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldValue.kt
rename to compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldValue.kt
index 4f28529..fd9b397 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldValue.kt
+++ b/compose/material3/adaptive/adaptive-layout/src/commonMain/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldValue.kt
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.layout
 
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
 import androidx.compose.runtime.Immutable
 import androidx.compose.ui.util.fastForEachReversed
 
diff --git a/compose/material3/adaptive/adaptive-navigation/api/current.txt b/compose/material3/adaptive/adaptive-navigation/api/current.txt
new file mode 100644
index 0000000..f3c507c
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-navigation/api/current.txt
@@ -0,0 +1,32 @@
+// Signature format: 4.0
+package androidx.compose.material3.adaptive.navigation {
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public enum BackNavigationBehavior {
+    method public static androidx.compose.material3.adaptive.navigation.BackNavigationBehavior valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.adaptive.navigation.BackNavigationBehavior[] values();
+    enum_constant public static final androidx.compose.material3.adaptive.navigation.BackNavigationBehavior PopLatest;
+    enum_constant public static final androidx.compose.material3.adaptive.navigation.BackNavigationBehavior PopUntilContentChange;
+    enum_constant public static final androidx.compose.material3.adaptive.navigation.BackNavigationBehavior PopUntilCurrentDestinationChange;
+    enum_constant public static final androidx.compose.material3.adaptive.navigation.BackNavigationBehavior PopUntilScaffoldValueChange;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public interface ThreePaneScaffoldNavigator<T> {
+    method public boolean canNavigateBack(optional androidx.compose.material3.adaptive.navigation.BackNavigationBehavior backNavigationBehavior);
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<T>? getCurrentDestination();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState getScaffoldState();
+    method public boolean isDestinationHistoryAware();
+    method public boolean navigateBack(optional androidx.compose.material3.adaptive.navigation.BackNavigationBehavior backNavigationBehavior);
+    method public void navigateTo(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole pane, optional T? content);
+    method public void setDestinationHistoryAware(boolean);
+    property public abstract androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<T>? currentDestination;
+    property public abstract boolean isDestinationHistoryAware;
+    property public abstract androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState;
+  }
+
+  public final class ThreePaneScaffoldNavigatorKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static <T> androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<T> rememberListDetailPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware, optional java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<? extends T>> initialDestinationHistory);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static <T> androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<T> rememberSupportingPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware, optional java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<? extends T>> initialDestinationHistory);
+  }
+
+}
+
diff --git a/compose/material3/material3-adaptive/api/res-current.txt b/compose/material3/adaptive/adaptive-navigation/api/res-current.txt
similarity index 100%
copy from compose/material3/material3-adaptive/api/res-current.txt
copy to compose/material3/adaptive/adaptive-navigation/api/res-current.txt
diff --git a/compose/material3/adaptive/adaptive-navigation/api/restricted_current.txt b/compose/material3/adaptive/adaptive-navigation/api/restricted_current.txt
new file mode 100644
index 0000000..f3c507c
--- /dev/null
+++ b/compose/material3/adaptive/adaptive-navigation/api/restricted_current.txt
@@ -0,0 +1,32 @@
+// Signature format: 4.0
+package androidx.compose.material3.adaptive.navigation {
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public enum BackNavigationBehavior {
+    method public static androidx.compose.material3.adaptive.navigation.BackNavigationBehavior valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.compose.material3.adaptive.navigation.BackNavigationBehavior[] values();
+    enum_constant public static final androidx.compose.material3.adaptive.navigation.BackNavigationBehavior PopLatest;
+    enum_constant public static final androidx.compose.material3.adaptive.navigation.BackNavigationBehavior PopUntilContentChange;
+    enum_constant public static final androidx.compose.material3.adaptive.navigation.BackNavigationBehavior PopUntilCurrentDestinationChange;
+    enum_constant public static final androidx.compose.material3.adaptive.navigation.BackNavigationBehavior PopUntilScaffoldValueChange;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public interface ThreePaneScaffoldNavigator<T> {
+    method public boolean canNavigateBack(optional androidx.compose.material3.adaptive.navigation.BackNavigationBehavior backNavigationBehavior);
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<T>? getCurrentDestination();
+    method public androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState getScaffoldState();
+    method public boolean isDestinationHistoryAware();
+    method public boolean navigateBack(optional androidx.compose.material3.adaptive.navigation.BackNavigationBehavior backNavigationBehavior);
+    method public void navigateTo(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole pane, optional T? content);
+    method public void setDestinationHistoryAware(boolean);
+    property public abstract androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<T>? currentDestination;
+    property public abstract boolean isDestinationHistoryAware;
+    property public abstract androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState scaffoldState;
+  }
+
+  public final class ThreePaneScaffoldNavigatorKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static <T> androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<T> rememberListDetailPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware, optional java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<? extends T>> initialDestinationHistory);
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static <T> androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator<T> rememberSupportingPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.layout.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware, optional java.util.List<? extends androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem<? extends T>> initialDestinationHistory);
+  }
+
+}
+
diff --git a/compose/material3/material3-adaptive/build.gradle b/compose/material3/adaptive/adaptive-navigation/build.gradle
similarity index 90%
copy from compose/material3/material3-adaptive/build.gradle
copy to compose/material3/adaptive/adaptive-navigation/build.gradle
index cbd842e..3736767 100644
--- a/compose/material3/material3-adaptive/build.gradle
+++ b/compose/material3/adaptive/adaptive-navigation/build.gradle
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@
  */
 import androidx.build.LibraryType
 import androidx.build.PlatformIdentifier
-import androidx.build.Publish
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
 plugins {
@@ -45,6 +44,7 @@
                 api("androidx.compose.foundation:foundation:1.6.0-rc01")
                 implementation("androidx.compose.foundation:foundation-layout:1.6.0-rc01")
                 implementation("androidx.compose.ui:ui-util:1.6.0-rc01")
+                implementation(project(":compose:material3:adaptive:adaptive-layout"))
                 // TODO(conradchen): pin the depe when the change required is released to public
                 implementation(project(":window:window-core"))
             }
@@ -67,7 +67,6 @@
             dependencies {
                 api("androidx.annotation:annotation:1.1.0")
                 api("androidx.annotation:annotation-experimental:1.4.0")
-                implementation("androidx.window:window:1.2.0")
             }
         }
 
@@ -110,12 +109,11 @@
 }
 
 android {
-    namespace "androidx.compose.material3.adaptive"
+    namespace "androidx.compose.material3.adaptive.navigation"
 }
 
 androidx {
     name = "Material Adaptive"
-    mavenVersion = LibraryVersions.COMPOSE_MATERIAL3_ADAPTIVE
     type = LibraryType.PUBLISHED_LIBRARY
     inceptionYear = "2023"
     description = "Compose Material Design Adaptive Library"
@@ -128,6 +126,6 @@
 // Screenshot tests related setup
 android {
     sourceSets.androidTest.assets.srcDirs +=
-            project.rootDir.absolutePath + "/../../golden/compose/material3/material3-adaptive"
-    namespace "androidx.compose.material3.adaptive"
+            project.rootDir.absolutePath + "/../../golden/compose/material3/adaptive"
+    namespace "androidx.compose.material3.adaptive.navigation"
 }
diff --git a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/ListDetailPaneScaffoldNavigatorTest.kt b/compose/material3/adaptive/adaptive-navigation/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/navigation/ListDetailPaneScaffoldNavigatorTest.kt
similarity index 97%
rename from compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/ListDetailPaneScaffoldNavigatorTest.kt
rename to compose/material3/adaptive/adaptive-navigation/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/navigation/ListDetailPaneScaffoldNavigatorTest.kt
index efdd348..603fd04d 100644
--- a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/ListDetailPaneScaffoldNavigatorTest.kt
+++ b/compose/material3/adaptive/adaptive-navigation/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/navigation/ListDetailPaneScaffoldNavigatorTest.kt
@@ -14,9 +14,15 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.navigation
 
 import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
+import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
+import androidx.compose.material3.adaptive.layout.PaneAdaptedValue
+import androidx.compose.material3.adaptive.layout.PaneScaffoldDirective
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.unit.dp
diff --git a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/SupportingPaneScaffoldNavigatorTest.kt b/compose/material3/adaptive/adaptive-navigation/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/navigation/SupportingPaneScaffoldNavigatorTest.kt
similarity index 97%
rename from compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/SupportingPaneScaffoldNavigatorTest.kt
rename to compose/material3/adaptive/adaptive-navigation/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/navigation/SupportingPaneScaffoldNavigatorTest.kt
index bd224dc..8ef7193 100644
--- a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/SupportingPaneScaffoldNavigatorTest.kt
+++ b/compose/material3/adaptive/adaptive-navigation/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/navigation/SupportingPaneScaffoldNavigatorTest.kt
@@ -14,9 +14,15 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.navigation
 
 import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
+import androidx.compose.material3.adaptive.layout.PaneAdaptedValue
+import androidx.compose.material3.adaptive.layout.PaneScaffoldDirective
+import androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.unit.dp
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/BackNavigationBehavior.kt b/compose/material3/adaptive/adaptive-navigation/src/commonMain/kotlin/androidx/compose/material3/adaptive/navigation/BackNavigationBehavior.kt
similarity index 84%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/BackNavigationBehavior.kt
rename to compose/material3/adaptive/adaptive-navigation/src/commonMain/kotlin/androidx/compose/material3/adaptive/navigation/BackNavigationBehavior.kt
index 6332068..3ae80e2 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/BackNavigationBehavior.kt
+++ b/compose/material3/adaptive/adaptive-navigation/src/commonMain/kotlin/androidx/compose/material3/adaptive/navigation/BackNavigationBehavior.kt
@@ -14,7 +14,12 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.navigation
+
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
+import androidx.compose.material3.adaptive.layout.PaneAdaptedValue
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole
 
 /**
  * A class to control how back navigation should behave in a [ThreePaneScaffoldNavigator].
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldNavigator.kt b/compose/material3/adaptive/adaptive-navigation/src/commonMain/kotlin/androidx/compose/material3/adaptive/navigation/ThreePaneScaffoldNavigator.kt
similarity index 89%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldNavigator.kt
rename to compose/material3/adaptive/adaptive-navigation/src/commonMain/kotlin/androidx/compose/material3/adaptive/navigation/ThreePaneScaffoldNavigator.kt
index a8a181f..e4c9e79 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffoldNavigator.kt
+++ b/compose/material3/adaptive/adaptive-navigation/src/commonMain/kotlin/androidx/compose/material3/adaptive/navigation/ThreePaneScaffoldNavigator.kt
@@ -14,8 +14,24 @@
  * limitations under the License.
  */
 
-package androidx.compose.material3.adaptive
+package androidx.compose.material3.adaptive.navigation
 
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
+import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
+import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold
+import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldDefaults
+import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
+import androidx.compose.material3.adaptive.layout.PaneScaffoldDirective
+import androidx.compose.material3.adaptive.layout.SupportingPaneScaffold
+import androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldDefaults
+import androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldAdaptStrategies
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldState
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue
+import androidx.compose.material3.adaptive.layout.calculateStandardPaneScaffoldDirective
+import androidx.compose.material3.adaptive.layout.calculateThreePaneScaffoldValue
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.derivedStateOf
@@ -29,7 +45,8 @@
 import androidx.compose.ui.util.fastMap
 
 /**
- * The common interface of the default navigation implementations for different [ThreePaneScaffold].
+ * The common interface of the default navigation implementations for different three-pane
+ * scaffolds.
  *
  * In general, we suggest you to use [rememberListDetailPaneScaffoldNavigator] or
  * [rememberSupportingPaneScaffoldNavigator] to get remembered default instances of this interface
@@ -329,7 +346,7 @@
             initialAdaptStrategies: ThreePaneScaffoldAdaptStrategies,
             initialDestinationHistoryAware: Boolean
         ): Saver<DefaultThreePaneScaffoldNavigator<T>, *> {
-            val destinationItemSaver = ThreePaneScaffoldDestinationItem.saver<T>()
+            val destinationItemSaver = destinationItemSaver<T>()
             return listSaver(
                 save = {
                     it.destinationHistory.fastMap { destination ->
@@ -350,6 +367,18 @@
         }
     }
 }
+@OptIn(ExperimentalMaterial3AdaptiveApi::class)
+internal fun <T> destinationItemSaver(): Saver<ThreePaneScaffoldDestinationItem<T>, Any> =
+    listSaver(
+        save = { listOf(it.pane, it.content) },
+        restore = {
+            @Suppress("UNCHECKED_CAST")
+            (ThreePaneScaffoldDestinationItem(
+                pane = it[0] as ThreePaneScaffoldRole,
+                content = it[1] as T?
+            ))
+        }
+    )
 
 @OptIn(ExperimentalMaterial3AdaptiveApi::class)
 private val DefaultListDetailPaneHistory: List<ThreePaneScaffoldDestinationItem<Nothing>> =
diff --git a/compose/material3/adaptive/adaptive/api/current.txt b/compose/material3/adaptive/adaptive/api/current.txt
new file mode 100644
index 0000000..b7dcb35
--- /dev/null
+++ b/compose/material3/adaptive/adaptive/api/current.txt
@@ -0,0 +1,55 @@
+// Signature format: 4.0
+package androidx.compose.material3.adaptive {
+
+  public final class AndroidPosture_androidKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.Posture calculatePosture(java.util.List<? extends androidx.window.layout.FoldingFeature> foldingFeatures);
+  }
+
+  public final class AndroidWindowAdaptiveInfo_androidKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.util.List<androidx.window.layout.FoldingFeature>> collectFoldingFeaturesAsState();
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.WindowAdaptiveInfo currentWindowAdaptiveInfo();
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static long currentWindowSize();
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This material3 adaptive API is experimental and is likely to change or to be" + "removed in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMaterial3AdaptiveApi {
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class HingeInfo {
+    ctor public HingeInfo(androidx.compose.ui.geometry.Rect bounds, boolean isVertical, boolean isSeparating, boolean isOccluding);
+    method public androidx.compose.ui.geometry.Rect getBounds();
+    method public boolean isOccluding();
+    method public boolean isSeparating();
+    method public boolean isVertical();
+    property public final androidx.compose.ui.geometry.Rect bounds;
+    property public final boolean isOccluding;
+    property public final boolean isSeparating;
+    property public final boolean isVertical;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class Posture {
+    ctor public Posture(optional boolean isTabletop, optional java.util.List<androidx.compose.material3.adaptive.HingeInfo> hingeList);
+    method public java.util.List<androidx.compose.material3.adaptive.HingeInfo> getHingeList();
+    method public boolean isTabletop();
+    property public final java.util.List<androidx.compose.material3.adaptive.HingeInfo> hingeList;
+    property public final boolean isTabletop;
+  }
+
+  public final class PostureKt {
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getAllHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getAllVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getOccludingHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getOccludingVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getSeparatingHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getSeparatingVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class WindowAdaptiveInfo {
+    ctor public WindowAdaptiveInfo(androidx.window.core.layout.WindowSizeClass windowSizeClass, androidx.compose.material3.adaptive.Posture windowPosture);
+    method public androidx.compose.material3.adaptive.Posture getWindowPosture();
+    method public androidx.window.core.layout.WindowSizeClass getWindowSizeClass();
+    property public final androidx.compose.material3.adaptive.Posture windowPosture;
+    property public final androidx.window.core.layout.WindowSizeClass windowSizeClass;
+  }
+
+}
+
diff --git a/compose/material3/material3-adaptive/api/res-current.txt b/compose/material3/adaptive/adaptive/api/res-current.txt
similarity index 100%
rename from compose/material3/material3-adaptive/api/res-current.txt
rename to compose/material3/adaptive/adaptive/api/res-current.txt
diff --git a/compose/material3/adaptive/adaptive/api/restricted_current.txt b/compose/material3/adaptive/adaptive/api/restricted_current.txt
new file mode 100644
index 0000000..b7dcb35
--- /dev/null
+++ b/compose/material3/adaptive/adaptive/api/restricted_current.txt
@@ -0,0 +1,55 @@
+// Signature format: 4.0
+package androidx.compose.material3.adaptive {
+
+  public final class AndroidPosture_androidKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.Posture calculatePosture(java.util.List<? extends androidx.window.layout.FoldingFeature> foldingFeatures);
+  }
+
+  public final class AndroidWindowAdaptiveInfo_androidKt {
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.util.List<androidx.window.layout.FoldingFeature>> collectFoldingFeaturesAsState();
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.WindowAdaptiveInfo currentWindowAdaptiveInfo();
+    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static long currentWindowSize();
+  }
+
+  @SuppressCompatibility @kotlin.RequiresOptIn(message="This material3 adaptive API is experimental and is likely to change or to be" + "removed in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMaterial3AdaptiveApi {
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class HingeInfo {
+    ctor public HingeInfo(androidx.compose.ui.geometry.Rect bounds, boolean isVertical, boolean isSeparating, boolean isOccluding);
+    method public androidx.compose.ui.geometry.Rect getBounds();
+    method public boolean isOccluding();
+    method public boolean isSeparating();
+    method public boolean isVertical();
+    property public final androidx.compose.ui.geometry.Rect bounds;
+    property public final boolean isOccluding;
+    property public final boolean isSeparating;
+    property public final boolean isVertical;
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class Posture {
+    ctor public Posture(optional boolean isTabletop, optional java.util.List<androidx.compose.material3.adaptive.HingeInfo> hingeList);
+    method public java.util.List<androidx.compose.material3.adaptive.HingeInfo> getHingeList();
+    method public boolean isTabletop();
+    property public final java.util.List<androidx.compose.material3.adaptive.HingeInfo> hingeList;
+    property public final boolean isTabletop;
+  }
+
+  public final class PostureKt {
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getAllHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getAllVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getOccludingHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getOccludingVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getSeparatingHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
+    method public static java.util.List<androidx.compose.ui.geometry.Rect> getSeparatingVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
+  }
+
+  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class WindowAdaptiveInfo {
+    ctor public WindowAdaptiveInfo(androidx.window.core.layout.WindowSizeClass windowSizeClass, androidx.compose.material3.adaptive.Posture windowPosture);
+    method public androidx.compose.material3.adaptive.Posture getWindowPosture();
+    method public androidx.window.core.layout.WindowSizeClass getWindowSizeClass();
+    property public final androidx.compose.material3.adaptive.Posture windowPosture;
+    property public final androidx.window.core.layout.WindowSizeClass windowSizeClass;
+  }
+
+}
+
diff --git a/compose/material3/material3-adaptive/build.gradle b/compose/material3/adaptive/adaptive/build.gradle
similarity index 93%
rename from compose/material3/material3-adaptive/build.gradle
rename to compose/material3/adaptive/adaptive/build.gradle
index cbd842e..17f440f 100644
--- a/compose/material3/material3-adaptive/build.gradle
+++ b/compose/material3/adaptive/adaptive/build.gradle
@@ -23,7 +23,6 @@
  */
 import androidx.build.LibraryType
 import androidx.build.PlatformIdentifier
-import androidx.build.Publish
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
 plugins {
@@ -42,9 +41,8 @@
         commonMain {
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
-                api("androidx.compose.foundation:foundation:1.6.0-rc01")
-                implementation("androidx.compose.foundation:foundation-layout:1.6.0-rc01")
-                implementation("androidx.compose.ui:ui-util:1.6.0-rc01")
+                api("androidx.compose.foundation:foundation:1.6.0")
+                implementation("androidx.compose.ui:ui-util:1.6.0")
                 // TODO(conradchen): pin the depe when the change required is released to public
                 implementation(project(":window:window-core"))
             }
@@ -115,7 +113,6 @@
 
 androidx {
     name = "Material Adaptive"
-    mavenVersion = LibraryVersions.COMPOSE_MATERIAL3_ADAPTIVE
     type = LibraryType.PUBLISHED_LIBRARY
     inceptionYear = "2023"
     description = "Compose Material Design Adaptive Library"
@@ -128,6 +125,6 @@
 // Screenshot tests related setup
 android {
     sourceSets.androidTest.assets.srcDirs +=
-            project.rootDir.absolutePath + "/../../golden/compose/material3/material3-adaptive"
+            project.rootDir.absolutePath + "/../../golden/compose/material3/adaptive"
     namespace "androidx.compose.material3.adaptive"
 }
diff --git a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CalculatePostureTest.kt b/compose/material3/adaptive/adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CalculatePostureTest.kt
similarity index 100%
rename from compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CalculatePostureTest.kt
rename to compose/material3/adaptive/adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CalculatePostureTest.kt
diff --git a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CollectFoldingFeaturesAsStateTest.kt b/compose/material3/adaptive/adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CollectFoldingFeaturesAsStateTest.kt
similarity index 100%
rename from compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CollectFoldingFeaturesAsStateTest.kt
rename to compose/material3/adaptive/adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CollectFoldingFeaturesAsStateTest.kt
diff --git a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CollectWindowSizeAsStateTest.kt b/compose/material3/adaptive/adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CollectWindowSizeAsStateTest.kt
similarity index 100%
rename from compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CollectWindowSizeAsStateTest.kt
rename to compose/material3/adaptive/adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CollectWindowSizeAsStateTest.kt
diff --git a/compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CurrentWindowAdaptiveInfoTest.kt b/compose/material3/adaptive/adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CurrentWindowAdaptiveInfoTest.kt
similarity index 100%
rename from compose/material3/material3-adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CurrentWindowAdaptiveInfoTest.kt
rename to compose/material3/adaptive/adaptive/src/androidInstrumentedTest/kotlin/androidx/compose/material3/adaptive/CurrentWindowAdaptiveInfoTest.kt
diff --git a/compose/material3/material3-adaptive/src/androidMain/AndroidManifest.xml b/compose/material3/adaptive/adaptive/src/androidMain/AndroidManifest.xml
similarity index 100%
rename from compose/material3/material3-adaptive/src/androidMain/AndroidManifest.xml
rename to compose/material3/adaptive/adaptive/src/androidMain/AndroidManifest.xml
diff --git a/compose/material3/material3-adaptive/src/androidMain/kotlin/androidx/compose/material3/adaptive/AndroidPosture.android.kt b/compose/material3/adaptive/adaptive/src/androidMain/kotlin/androidx/compose/material3/adaptive/AndroidPosture.android.kt
similarity index 100%
rename from compose/material3/material3-adaptive/src/androidMain/kotlin/androidx/compose/material3/adaptive/AndroidPosture.android.kt
rename to compose/material3/adaptive/adaptive/src/androidMain/kotlin/androidx/compose/material3/adaptive/AndroidPosture.android.kt
diff --git a/compose/material3/material3-adaptive/src/androidMain/kotlin/androidx/compose/material3/adaptive/AndroidWindowInfo.android.kt b/compose/material3/adaptive/adaptive/src/androidMain/kotlin/androidx/compose/material3/adaptive/AndroidWindowAdaptiveInfo.android.kt
similarity index 100%
rename from compose/material3/material3-adaptive/src/androidMain/kotlin/androidx/compose/material3/adaptive/AndroidWindowInfo.android.kt
rename to compose/material3/adaptive/adaptive/src/androidMain/kotlin/androidx/compose/material3/adaptive/AndroidWindowAdaptiveInfo.android.kt
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ExperimentalMaterial3AdaptiveApi.kt b/compose/material3/adaptive/adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ExperimentalMaterial3AdaptiveApi.kt
similarity index 92%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ExperimentalMaterial3AdaptiveApi.kt
rename to compose/material3/adaptive/adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ExperimentalMaterial3AdaptiveApi.kt
index 4636316..3ad72c5 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ExperimentalMaterial3AdaptiveApi.kt
+++ b/compose/material3/adaptive/adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/ExperimentalMaterial3AdaptiveApi.kt
@@ -17,7 +17,7 @@
 package androidx.compose.material3.adaptive
 
 @RequiresOptIn(
-    "This material3-adaptive API is experimental and is likely to change or to be" +
+    "This material3 adaptive API is experimental and is likely to change or to be" +
         "removed in the future."
 )
 @Retention(AnnotationRetention.BINARY)
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/Posture.kt b/compose/material3/adaptive/adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/Posture.kt
similarity index 100%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/Posture.kt
rename to compose/material3/adaptive/adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/Posture.kt
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/WindowAdaptiveInfo.kt b/compose/material3/adaptive/adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/WindowAdaptiveInfo.kt
similarity index 80%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/WindowAdaptiveInfo.kt
rename to compose/material3/adaptive/adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/WindowAdaptiveInfo.kt
index de1f979..57b2015 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/WindowAdaptiveInfo.kt
+++ b/compose/material3/adaptive/adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/WindowAdaptiveInfo.kt
@@ -16,10 +16,22 @@
 
 package androidx.compose.material3.adaptive
 
+import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Immutable
 import androidx.window.core.layout.WindowSizeClass
 
 /**
+ * Calculates and returns [WindowAdaptiveInfo] of the provided context. It's a convenient function
+ * that uses the default [WindowSizeClass] constructor and the default [Posture] calculation
+ * functions to retrieve [WindowSizeClass] and [Posture].
+ *
+ * @return [WindowAdaptiveInfo] of the provided context
+ */
+@ExperimentalMaterial3AdaptiveApi
+@Composable
+expect fun currentWindowAdaptiveInfo(): WindowAdaptiveInfo
+
+/**
  * This class collects window info that affects adaptation decisions. An adaptive layout is supposed
  * to use the info from this class to decide how the layout is supposed to be adapted.
  *
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/androidx-compose-material3-adaptive-documentation.md b/compose/material3/adaptive/adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/androidx-compose-material3-adaptive-documentation.md
similarity index 100%
rename from compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/androidx-compose-material3-adaptive-documentation.md
rename to compose/material3/adaptive/adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/androidx-compose-material3-adaptive-documentation.md
diff --git a/compose/material3/material3-adaptive/src/desktopMain/kotlin/androidx/compose/material3/adaptive/DesktopWindowInfo.desktop.kt b/compose/material3/adaptive/adaptive/src/desktopMain/kotlin/androidx/compose/material3/adaptive/DesktopWindowInfo.desktop.kt
similarity index 100%
rename from compose/material3/material3-adaptive/src/desktopMain/kotlin/androidx/compose/material3/adaptive/DesktopWindowInfo.desktop.kt
rename to compose/material3/adaptive/adaptive/src/desktopMain/kotlin/androidx/compose/material3/adaptive/DesktopWindowInfo.desktop.kt
diff --git a/compose/material3/material3-adaptive/benchmark/build.gradle b/compose/material3/adaptive/benchmark/build.gradle
similarity index 93%
rename from compose/material3/material3-adaptive/benchmark/build.gradle
rename to compose/material3/adaptive/benchmark/build.gradle
index 48f6444..e63b29e 100644
--- a/compose/material3/material3-adaptive/benchmark/build.gradle
+++ b/compose/material3/adaptive/benchmark/build.gradle
@@ -23,7 +23,7 @@
 }
 
 dependencies {
-    androidTestImplementation(project(":compose:material3:material3-adaptive"))
+    androidTestImplementation(project(":compose:material3:adaptive:adaptive-layout"))
     androidTestImplementation(project(":benchmark:benchmark-junit4"))
     androidTestImplementation(project(":compose:runtime:runtime"))
     androidTestImplementation(project(":compose:benchmark-utils"))
diff --git a/compose/material3/material3-adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/ListDetailPaneScaffoldBenchmark.kt b/compose/material3/adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/ListDetailPaneScaffoldBenchmark.kt
similarity index 95%
rename from compose/material3/material3-adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/ListDetailPaneScaffoldBenchmark.kt
rename to compose/material3/adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/ListDetailPaneScaffoldBenchmark.kt
index b6974a1..2a48785 100644
--- a/compose/material3/material3-adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/ListDetailPaneScaffoldBenchmark.kt
+++ b/compose/material3/adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/ListDetailPaneScaffoldBenchmark.kt
@@ -17,10 +17,10 @@
 package androidx.compose.material3.adaptive.benchmark
 
 import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
-import androidx.compose.material3.adaptive.ListDetailPaneScaffold
-import androidx.compose.material3.adaptive.ListDetailPaneScaffoldRole
-import androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem
-import androidx.compose.material3.adaptive.calculateListDetailPaneScaffoldState
+import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold
+import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem
+import androidx.compose.material3.adaptive.layout.calculateListDetailPaneScaffoldState
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
diff --git a/compose/material3/material3-adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/SupportingPaneScaffoldBenchmark.kt b/compose/material3/adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/SupportingPaneScaffoldBenchmark.kt
similarity index 95%
rename from compose/material3/material3-adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/SupportingPaneScaffoldBenchmark.kt
rename to compose/material3/adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/SupportingPaneScaffoldBenchmark.kt
index a96d4d9..dcfaec7 100644
--- a/compose/material3/material3-adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/SupportingPaneScaffoldBenchmark.kt
+++ b/compose/material3/adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/SupportingPaneScaffoldBenchmark.kt
@@ -17,10 +17,10 @@
 package androidx.compose.material3.adaptive.benchmark
 
 import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
-import androidx.compose.material3.adaptive.SupportingPaneScaffold
-import androidx.compose.material3.adaptive.SupportingPaneScaffoldRole
-import androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem
-import androidx.compose.material3.adaptive.calculateSupportingPaneScaffoldState
+import androidx.compose.material3.adaptive.layout.SupportingPaneScaffold
+import androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem
+import androidx.compose.material3.adaptive.layout.calculateSupportingPaneScaffoldState
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
diff --git a/compose/material3/material3-adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/TestUtils.kt b/compose/material3/adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/TestUtils.kt
similarity index 90%
rename from compose/material3/material3-adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/TestUtils.kt
rename to compose/material3/adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/TestUtils.kt
index c71021b..acfcf48 100644
--- a/compose/material3/material3-adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/TestUtils.kt
+++ b/compose/material3/adaptive/benchmark/src/androidTest/java/androidx/compose/material3/adaptive/benchmark/TestUtils.kt
@@ -20,11 +20,11 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.material3.adaptive.AnimatedPane
 import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
-import androidx.compose.material3.adaptive.PaneScaffoldDirective
-import androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem
-import androidx.compose.material3.adaptive.ThreePaneScaffoldScope
+import androidx.compose.material3.adaptive.layout.AnimatedPane
+import androidx.compose.material3.adaptive.layout.PaneScaffoldDirective
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldDestinationItem
+import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
diff --git a/compose/material3/material3-adaptive/samples/build.gradle b/compose/material3/adaptive/samples/build.gradle
similarity index 92%
rename from compose/material3/material3-adaptive/samples/build.gradle
rename to compose/material3/adaptive/samples/build.gradle
index 1c8ac3c..45dec1d 100644
--- a/compose/material3/material3-adaptive/samples/build.gradle
+++ b/compose/material3/adaptive/samples/build.gradle
@@ -38,8 +38,9 @@
 
     implementation("androidx.compose.foundation:foundation:1.6.0-rc01")
     implementation("androidx.compose.foundation:foundation-layout:1.6.0-rc01")
+    implementation(project(":compose:material3:adaptive:adaptive-layout"))
+    implementation(project(":compose:material3:adaptive:adaptive-navigation"))
     implementation(project(":compose:material3:material3"))
-    implementation(project(":compose:material3:material3-adaptive"))
     implementation(project(":compose:material3:material3-window-size-class"))
     implementation("androidx.compose.ui:ui-util:1.6.0-rc01")
     implementation("androidx.compose.ui:ui-tooling-preview:1.4.1")
diff --git a/compose/material3/material3-adaptive/samples/src/main/java/androidx/compose/material3/adaptive/samples/ThreePaneScaffoldSample.kt b/compose/material3/adaptive/samples/src/main/java/androidx/compose/material3/adaptive/samples/ThreePaneScaffoldSample.kt
similarity index 94%
rename from compose/material3/material3-adaptive/samples/src/main/java/androidx/compose/material3/adaptive/samples/ThreePaneScaffoldSample.kt
rename to compose/material3/adaptive/samples/src/main/java/androidx/compose/material3/adaptive/samples/ThreePaneScaffoldSample.kt
index 5ddc87f..29d75b0 100644
--- a/compose/material3/material3-adaptive/samples/src/main/java/androidx/compose/material3/adaptive/samples/ThreePaneScaffoldSample.kt
+++ b/compose/material3/adaptive/samples/src/main/java/androidx/compose/material3/adaptive/samples/ThreePaneScaffoldSample.kt
@@ -29,11 +29,11 @@
 import androidx.compose.material3.Surface
 import androidx.compose.material3.Text
 import androidx.compose.material3.VerticalDivider
-import androidx.compose.material3.adaptive.AnimatedPane
 import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
-import androidx.compose.material3.adaptive.ListDetailPaneScaffold
-import androidx.compose.material3.adaptive.ListDetailPaneScaffoldRole
-import androidx.compose.material3.adaptive.rememberListDetailPaneScaffoldNavigator
+import androidx.compose.material3.adaptive.layout.AnimatedPane
+import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold
+import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
+import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
diff --git a/compose/material3/material3-adaptive-navigation-suite/build.gradle b/compose/material3/material3-adaptive-navigation-suite/build.gradle
index 47289bf..769a941 100644
--- a/compose/material3/material3-adaptive-navigation-suite/build.gradle
+++ b/compose/material3/material3-adaptive-navigation-suite/build.gradle
@@ -43,9 +43,9 @@
         commonMain {
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
-                implementation("androidx.compose.material3:material3:1.2.0-rc01")
-                implementation(project(":compose:material3:material3-adaptive"))
-                implementation("androidx.compose.ui:ui-util:1.6.0-rc01")
+                implementation("androidx.compose.material3:material3:1.2.0")
+                implementation(project(":compose:material3:adaptive:adaptive"))
+                implementation("androidx.compose.ui:ui-util:1.6.0")
                 // TODO(conradchen): pin the depe when the change required is released to public
                 implementation(project(":window:window-core"))
             }
@@ -110,6 +110,9 @@
 
 android {
     namespace "androidx.compose.material3.adaptive.navigationsuite"
+    lintOptions {
+        disable 'IllegalExperimentalApiUsage' // TODO (conradchen): Address before moving to beta
+    }
 }
 
 androidx {
diff --git a/compose/material3/material3-adaptive-navigation-suite/samples/build.gradle b/compose/material3/material3-adaptive-navigation-suite/samples/build.gradle
index 2e1bb69..135d478 100644
--- a/compose/material3/material3-adaptive-navigation-suite/samples/build.gradle
+++ b/compose/material3/material3-adaptive-navigation-suite/samples/build.gradle
@@ -38,8 +38,8 @@
 
     implementation("androidx.compose.foundation:foundation:1.6.0-rc01")
     implementation("androidx.compose.foundation:foundation-layout:1.6.0-rc01")
+    implementation(project(":compose:material3:adaptive:adaptive"))
     implementation(project(":compose:material3:material3"))
-    implementation(project(":compose:material3:material3-adaptive"))
     implementation(project(":compose:material3:material3-adaptive-navigation-suite"))
     implementation("androidx.compose.ui:ui-util:1.6.0-rc01")
     implementation("androidx.compose.ui:ui-tooling-preview:1.4.1")
diff --git a/compose/material3/material3-adaptive/api/current.txt b/compose/material3/material3-adaptive/api/current.txt
deleted file mode 100644
index ade4688..0000000
--- a/compose/material3/material3-adaptive/api/current.txt
+++ /dev/null
@@ -1,254 +0,0 @@
-// Signature format: 4.0
-package androidx.compose.material3.adaptive {
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public interface AdaptStrategy {
-    method public String adapt();
-    field public static final androidx.compose.material3.adaptive.AdaptStrategy.Companion Companion;
-  }
-
-  public static final class AdaptStrategy.Companion {
-    method public androidx.compose.material3.adaptive.AdaptStrategy getHide();
-    property public final androidx.compose.material3.adaptive.AdaptStrategy Hide;
-  }
-
-  public final class AndroidPosture_androidKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.Posture calculatePosture(java.util.List<? extends androidx.window.layout.FoldingFeature> foldingFeatures);
-  }
-
-  public final class AndroidWindowInfo_androidKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.util.List<androidx.window.layout.FoldingFeature>> collectFoldingFeaturesAsState();
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.WindowAdaptiveInfo currentWindowAdaptiveInfo();
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static long currentWindowSize();
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public enum BackNavigationBehavior {
-    method public static androidx.compose.material3.adaptive.BackNavigationBehavior valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
-    method public static androidx.compose.material3.adaptive.BackNavigationBehavior[] values();
-    enum_constant public static final androidx.compose.material3.adaptive.BackNavigationBehavior PopLatest;
-    enum_constant public static final androidx.compose.material3.adaptive.BackNavigationBehavior PopUntilContentChange;
-    enum_constant public static final androidx.compose.material3.adaptive.BackNavigationBehavior PopUntilCurrentDestinationChange;
-    enum_constant public static final androidx.compose.material3.adaptive.BackNavigationBehavior PopUntilScaffoldValueChange;
-  }
-
-  @SuppressCompatibility @kotlin.RequiresOptIn(message="This material3-adaptive API is experimental and is likely to change or to be" + "removed in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMaterial3AdaptiveApi {
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class HingeInfo {
-    ctor public HingeInfo(androidx.compose.ui.geometry.Rect bounds, boolean isVertical, boolean isSeparating, boolean isOccluding);
-    method public androidx.compose.ui.geometry.Rect getBounds();
-    method public boolean isOccluding();
-    method public boolean isSeparating();
-    method public boolean isVertical();
-    property public final androidx.compose.ui.geometry.Rect bounds;
-    property public final boolean isOccluding;
-    property public final boolean isSeparating;
-    property public final boolean isVertical;
-  }
-
-  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class HingePolicy {
-    field public static final androidx.compose.material3.adaptive.HingePolicy.Companion Companion;
-  }
-
-  public static final class HingePolicy.Companion {
-    method public int getAlwaysAvoid();
-    method public int getAvoidOccluding();
-    method public int getAvoidSeparating();
-    method public int getNeverAvoid();
-    property public final int AlwaysAvoid;
-    property public final int AvoidOccluding;
-    property public final int AvoidSeparating;
-    property public final int NeverAvoid;
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ListDetailPaneScaffoldDefaults {
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies(optional androidx.compose.material3.adaptive.AdaptStrategy detailPaneAdaptStrategy, optional androidx.compose.material3.adaptive.AdaptStrategy listPaneAdaptStrategy, optional androidx.compose.material3.adaptive.AdaptStrategy extraPaneAdaptStrategy);
-    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
-    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
-    field public static final androidx.compose.material3.adaptive.ListDetailPaneScaffoldDefaults INSTANCE;
-  }
-
-  public final class ListDetailPaneScaffoldKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit> listPane, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.adaptive.ThreePaneScaffoldState scaffoldState, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit>? extraPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit> detailPane);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.ThreePaneScaffoldState calculateListDetailPaneScaffoldState(optional androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<?> currentDestination, optional androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.ThreePaneScaffoldState calculateListDetailPaneScaffoldState(java.util.List<? extends androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<?>> destinationHistory, optional androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ListDetailPaneScaffoldRole {
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getDetail();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getExtra();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getList();
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Detail;
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Extra;
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole List;
-    field public static final androidx.compose.material3.adaptive.ListDetailPaneScaffoldRole INSTANCE;
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @kotlin.jvm.JvmInline public final value class PaneAdaptedValue {
-    field public static final androidx.compose.material3.adaptive.PaneAdaptedValue.Companion Companion;
-  }
-
-  public static final class PaneAdaptedValue.Companion {
-    method public String getExpanded();
-    method public String getHidden();
-    property public final String Expanded;
-    property public final String Hidden;
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class PaneScaffoldDirective {
-    ctor public PaneScaffoldDirective(androidx.compose.foundation.layout.PaddingValues contentPadding, int maxHorizontalPartitions, float horizontalPartitionSpacerSize, int maxVerticalPartitions, float verticalPartitionSpacerSize, java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds);
-    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
-    method public java.util.List<androidx.compose.ui.geometry.Rect> getExcludedBounds();
-    method public float getHorizontalPartitionSpacerSize();
-    method public int getMaxHorizontalPartitions();
-    method public int getMaxVerticalPartitions();
-    method public float getVerticalPartitionSpacerSize();
-    property public final androidx.compose.foundation.layout.PaddingValues contentPadding;
-    property public final java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds;
-    property public final float horizontalPartitionSpacerSize;
-    property public final int maxHorizontalPartitions;
-    property public final int maxVerticalPartitions;
-    property public final float verticalPartitionSpacerSize;
-  }
-
-  public final class PaneScaffoldDirectiveKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.PaneScaffoldDirective calculateDensePaneScaffoldDirective(androidx.compose.material3.adaptive.WindowAdaptiveInfo windowAdaptiveInfo, optional int verticalHingePolicy);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.PaneScaffoldDirective calculateStandardPaneScaffoldDirective(androidx.compose.material3.adaptive.WindowAdaptiveInfo windowAdaptiveInfo, optional int verticalHingePolicy);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public interface PaneScaffoldScope {
-    method public androidx.compose.ui.Modifier preferredWidth(androidx.compose.ui.Modifier, float width);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class Posture {
-    ctor public Posture(optional boolean isTabletop, optional java.util.List<androidx.compose.material3.adaptive.HingeInfo> hingeList);
-    method public java.util.List<androidx.compose.material3.adaptive.HingeInfo> getHingeList();
-    method public boolean isTabletop();
-    property public final java.util.List<androidx.compose.material3.adaptive.HingeInfo> hingeList;
-    property public final boolean isTabletop;
-  }
-
-  public final class PostureKt {
-    method public static java.util.List<androidx.compose.ui.geometry.Rect> getAllHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
-    method public static java.util.List<androidx.compose.ui.geometry.Rect> getAllVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
-    method public static java.util.List<androidx.compose.ui.geometry.Rect> getOccludingHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
-    method public static java.util.List<androidx.compose.ui.geometry.Rect> getOccludingVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
-    method public static java.util.List<androidx.compose.ui.geometry.Rect> getSeparatingHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
-    method public static java.util.List<androidx.compose.ui.geometry.Rect> getSeparatingVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldDefaults {
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies(optional androidx.compose.material3.adaptive.AdaptStrategy mainPaneAdaptStrategy, optional androidx.compose.material3.adaptive.AdaptStrategy supportingPaneAdaptStrategy, optional androidx.compose.material3.adaptive.AdaptStrategy extraPaneAdaptStrategy);
-    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
-    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
-    field public static final androidx.compose.material3.adaptive.SupportingPaneScaffoldDefaults INSTANCE;
-  }
-
-  public final class SupportingPaneScaffoldKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.adaptive.ThreePaneScaffoldState scaffoldState, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit>? extraPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit> mainPane);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.ThreePaneScaffoldState calculateSupportingPaneScaffoldState(optional androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<?> currentDestination, optional androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.ThreePaneScaffoldState calculateSupportingPaneScaffoldState(java.util.List<? extends androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<?>> destinationHistory, optional androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldRole {
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getExtra();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getMain();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getSupporting();
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Extra;
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Main;
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Supporting;
-    field public static final androidx.compose.material3.adaptive.SupportingPaneScaffoldRole INSTANCE;
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldAdaptStrategies {
-    ctor public ThreePaneScaffoldAdaptStrategies(androidx.compose.material3.adaptive.AdaptStrategy primaryPaneAdaptStrategy, androidx.compose.material3.adaptive.AdaptStrategy secondaryPaneAdaptStrategy, androidx.compose.material3.adaptive.AdaptStrategy tertiaryPaneAdaptStrategy);
-    method public operator androidx.compose.material3.adaptive.AdaptStrategy get(androidx.compose.material3.adaptive.ThreePaneScaffoldRole role);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldDestinationItem<T> {
-    ctor public ThreePaneScaffoldDestinationItem(androidx.compose.material3.adaptive.ThreePaneScaffoldRole pane, optional T? content);
-    method public T? getContent();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getPane();
-    property public final T? content;
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole pane;
-    field public static final androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem.Companion Companion;
-  }
-
-  public static final class ThreePaneScaffoldDestinationItem.Companion {
-  }
-
-  public final class ThreePaneScaffoldKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void AnimatedPane(androidx.compose.material3.adaptive.ThreePaneScaffoldScope, androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit> content);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public interface ThreePaneScaffoldNavigator<T> {
-    method public boolean canNavigateBack(optional androidx.compose.material3.adaptive.BackNavigationBehavior backNavigationBehavior);
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<T>? getCurrentDestination();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldState getScaffoldState();
-    method public boolean isDestinationHistoryAware();
-    method public boolean navigateBack(optional androidx.compose.material3.adaptive.BackNavigationBehavior backNavigationBehavior);
-    method public void navigateTo(androidx.compose.material3.adaptive.ThreePaneScaffoldRole pane, optional T? content);
-    method public void setDestinationHistoryAware(boolean);
-    property public abstract androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<T>? currentDestination;
-    property public abstract boolean isDestinationHistoryAware;
-    property public abstract androidx.compose.material3.adaptive.ThreePaneScaffoldState scaffoldState;
-  }
-
-  public final class ThreePaneScaffoldNavigatorKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static <T> androidx.compose.material3.adaptive.ThreePaneScaffoldNavigator<T> rememberListDetailPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware, optional java.util.List<? extends androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<? extends T>> initialDestinationHistory);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static <T> androidx.compose.material3.adaptive.ThreePaneScaffoldNavigator<T> rememberSupportingPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware, optional java.util.List<? extends androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<? extends T>> initialDestinationHistory);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public enum ThreePaneScaffoldRole {
-    method public static androidx.compose.material3.adaptive.ThreePaneScaffoldRole valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
-    method public static androidx.compose.material3.adaptive.ThreePaneScaffoldRole[] values();
-    enum_constant public static final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Primary;
-    enum_constant public static final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Secondary;
-    enum_constant public static final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Tertiary;
-  }
-
-  public interface ThreePaneScaffoldScope extends androidx.compose.material3.adaptive.PaneScaffoldScope {
-    method public String getAnimationToolingLabel();
-    method public androidx.compose.animation.EnterTransition getEnterTransition();
-    method public androidx.compose.animation.ExitTransition getExitTransition();
-    method public String getPaneAdaptedValue();
-    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>? getPositionAnimationSpec();
-    property public abstract String animationToolingLabel;
-    property public abstract androidx.compose.animation.EnterTransition enterTransition;
-    property public abstract androidx.compose.animation.ExitTransition exitTransition;
-    property public abstract String paneAdaptedValue;
-    property public abstract androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>? positionAnimationSpec;
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public interface ThreePaneScaffoldState {
-    method public androidx.compose.material3.adaptive.PaneScaffoldDirective getScaffoldDirective();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldValue getScaffoldValue();
-    property public abstract androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective;
-    property public abstract androidx.compose.material3.adaptive.ThreePaneScaffoldValue scaffoldValue;
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class ThreePaneScaffoldValue {
-    ctor public ThreePaneScaffoldValue(String primary, String secondary, String tertiary);
-    method public operator String get(androidx.compose.material3.adaptive.ThreePaneScaffoldRole role);
-    method public String getPrimary();
-    method public String getSecondary();
-    method public String getTertiary();
-    property public final String primary;
-    property public final String secondary;
-    property public final String tertiary;
-  }
-
-  public final class ThreePaneScaffoldValueKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.ThreePaneScaffoldValue calculateThreePaneScaffoldValue(int maxHorizontalPartitions, androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies, androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<?>? currentDestination);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.ThreePaneScaffoldValue calculateThreePaneScaffoldValue(int maxHorizontalPartitions, androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies, java.util.List<? extends androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<?>> destinationHistory);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class WindowAdaptiveInfo {
-    ctor public WindowAdaptiveInfo(androidx.window.core.layout.WindowSizeClass windowSizeClass, androidx.compose.material3.adaptive.Posture windowPosture);
-    method public androidx.compose.material3.adaptive.Posture getWindowPosture();
-    method public androidx.window.core.layout.WindowSizeClass getWindowSizeClass();
-    property public final androidx.compose.material3.adaptive.Posture windowPosture;
-    property public final androidx.window.core.layout.WindowSizeClass windowSizeClass;
-  }
-
-}
-
diff --git a/compose/material3/material3-adaptive/api/restricted_current.txt b/compose/material3/material3-adaptive/api/restricted_current.txt
deleted file mode 100644
index ade4688..0000000
--- a/compose/material3/material3-adaptive/api/restricted_current.txt
+++ /dev/null
@@ -1,254 +0,0 @@
-// Signature format: 4.0
-package androidx.compose.material3.adaptive {
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public interface AdaptStrategy {
-    method public String adapt();
-    field public static final androidx.compose.material3.adaptive.AdaptStrategy.Companion Companion;
-  }
-
-  public static final class AdaptStrategy.Companion {
-    method public androidx.compose.material3.adaptive.AdaptStrategy getHide();
-    property public final androidx.compose.material3.adaptive.AdaptStrategy Hide;
-  }
-
-  public final class AndroidPosture_androidKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.Posture calculatePosture(java.util.List<? extends androidx.window.layout.FoldingFeature> foldingFeatures);
-  }
-
-  public final class AndroidWindowInfo_androidKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.runtime.State<java.util.List<androidx.window.layout.FoldingFeature>> collectFoldingFeaturesAsState();
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.WindowAdaptiveInfo currentWindowAdaptiveInfo();
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static long currentWindowSize();
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public enum BackNavigationBehavior {
-    method public static androidx.compose.material3.adaptive.BackNavigationBehavior valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
-    method public static androidx.compose.material3.adaptive.BackNavigationBehavior[] values();
-    enum_constant public static final androidx.compose.material3.adaptive.BackNavigationBehavior PopLatest;
-    enum_constant public static final androidx.compose.material3.adaptive.BackNavigationBehavior PopUntilContentChange;
-    enum_constant public static final androidx.compose.material3.adaptive.BackNavigationBehavior PopUntilCurrentDestinationChange;
-    enum_constant public static final androidx.compose.material3.adaptive.BackNavigationBehavior PopUntilScaffoldValueChange;
-  }
-
-  @SuppressCompatibility @kotlin.RequiresOptIn(message="This material3-adaptive API is experimental and is likely to change or to be" + "removed in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalMaterial3AdaptiveApi {
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class HingeInfo {
-    ctor public HingeInfo(androidx.compose.ui.geometry.Rect bounds, boolean isVertical, boolean isSeparating, boolean isOccluding);
-    method public androidx.compose.ui.geometry.Rect getBounds();
-    method public boolean isOccluding();
-    method public boolean isSeparating();
-    method public boolean isVertical();
-    property public final androidx.compose.ui.geometry.Rect bounds;
-    property public final boolean isOccluding;
-    property public final boolean isSeparating;
-    property public final boolean isVertical;
-  }
-
-  @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class HingePolicy {
-    field public static final androidx.compose.material3.adaptive.HingePolicy.Companion Companion;
-  }
-
-  public static final class HingePolicy.Companion {
-    method public int getAlwaysAvoid();
-    method public int getAvoidOccluding();
-    method public int getAvoidSeparating();
-    method public int getNeverAvoid();
-    property public final int AlwaysAvoid;
-    property public final int AvoidOccluding;
-    property public final int AvoidSeparating;
-    property public final int NeverAvoid;
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ListDetailPaneScaffoldDefaults {
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies(optional androidx.compose.material3.adaptive.AdaptStrategy detailPaneAdaptStrategy, optional androidx.compose.material3.adaptive.AdaptStrategy listPaneAdaptStrategy, optional androidx.compose.material3.adaptive.AdaptStrategy extraPaneAdaptStrategy);
-    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
-    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
-    field public static final androidx.compose.material3.adaptive.ListDetailPaneScaffoldDefaults INSTANCE;
-  }
-
-  public final class ListDetailPaneScaffoldKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void ListDetailPaneScaffold(kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit> listPane, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.adaptive.ThreePaneScaffoldState scaffoldState, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit>? extraPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit> detailPane);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.ThreePaneScaffoldState calculateListDetailPaneScaffoldState(optional androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<?> currentDestination, optional androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.ThreePaneScaffoldState calculateListDetailPaneScaffoldState(java.util.List<? extends androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<?>> destinationHistory, optional androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ListDetailPaneScaffoldRole {
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getDetail();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getExtra();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getList();
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Detail;
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Extra;
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole List;
-    field public static final androidx.compose.material3.adaptive.ListDetailPaneScaffoldRole INSTANCE;
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @kotlin.jvm.JvmInline public final value class PaneAdaptedValue {
-    field public static final androidx.compose.material3.adaptive.PaneAdaptedValue.Companion Companion;
-  }
-
-  public static final class PaneAdaptedValue.Companion {
-    method public String getExpanded();
-    method public String getHidden();
-    property public final String Expanded;
-    property public final String Hidden;
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class PaneScaffoldDirective {
-    ctor public PaneScaffoldDirective(androidx.compose.foundation.layout.PaddingValues contentPadding, int maxHorizontalPartitions, float horizontalPartitionSpacerSize, int maxVerticalPartitions, float verticalPartitionSpacerSize, java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds);
-    method public androidx.compose.foundation.layout.PaddingValues getContentPadding();
-    method public java.util.List<androidx.compose.ui.geometry.Rect> getExcludedBounds();
-    method public float getHorizontalPartitionSpacerSize();
-    method public int getMaxHorizontalPartitions();
-    method public int getMaxVerticalPartitions();
-    method public float getVerticalPartitionSpacerSize();
-    property public final androidx.compose.foundation.layout.PaddingValues contentPadding;
-    property public final java.util.List<androidx.compose.ui.geometry.Rect> excludedBounds;
-    property public final float horizontalPartitionSpacerSize;
-    property public final int maxHorizontalPartitions;
-    property public final int maxVerticalPartitions;
-    property public final float verticalPartitionSpacerSize;
-  }
-
-  public final class PaneScaffoldDirectiveKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.PaneScaffoldDirective calculateDensePaneScaffoldDirective(androidx.compose.material3.adaptive.WindowAdaptiveInfo windowAdaptiveInfo, optional int verticalHingePolicy);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.PaneScaffoldDirective calculateStandardPaneScaffoldDirective(androidx.compose.material3.adaptive.WindowAdaptiveInfo windowAdaptiveInfo, optional int verticalHingePolicy);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public interface PaneScaffoldScope {
-    method public androidx.compose.ui.Modifier preferredWidth(androidx.compose.ui.Modifier, float width);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class Posture {
-    ctor public Posture(optional boolean isTabletop, optional java.util.List<androidx.compose.material3.adaptive.HingeInfo> hingeList);
-    method public java.util.List<androidx.compose.material3.adaptive.HingeInfo> getHingeList();
-    method public boolean isTabletop();
-    property public final java.util.List<androidx.compose.material3.adaptive.HingeInfo> hingeList;
-    property public final boolean isTabletop;
-  }
-
-  public final class PostureKt {
-    method public static java.util.List<androidx.compose.ui.geometry.Rect> getAllHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
-    method public static java.util.List<androidx.compose.ui.geometry.Rect> getAllVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
-    method public static java.util.List<androidx.compose.ui.geometry.Rect> getOccludingHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
-    method public static java.util.List<androidx.compose.ui.geometry.Rect> getOccludingVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
-    method public static java.util.List<androidx.compose.ui.geometry.Rect> getSeparatingHorizontalHingeBounds(androidx.compose.material3.adaptive.Posture);
-    method public static java.util.List<androidx.compose.ui.geometry.Rect> getSeparatingVerticalHingeBounds(androidx.compose.material3.adaptive.Posture);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldDefaults {
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies(optional androidx.compose.material3.adaptive.AdaptStrategy mainPaneAdaptStrategy, optional androidx.compose.material3.adaptive.AdaptStrategy supportingPaneAdaptStrategy, optional androidx.compose.material3.adaptive.AdaptStrategy extraPaneAdaptStrategy);
-    method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getWindowInsets();
-    property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets windowInsets;
-    field public static final androidx.compose.material3.adaptive.SupportingPaneScaffoldDefaults INSTANCE;
-  }
-
-  public final class SupportingPaneScaffoldKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void SupportingPaneScaffold(kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit> supportingPane, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.material3.adaptive.ThreePaneScaffoldState scaffoldState, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit>? extraPane, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit> mainPane);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.ThreePaneScaffoldState calculateSupportingPaneScaffoldState(optional androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<?> currentDestination, optional androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static androidx.compose.material3.adaptive.ThreePaneScaffoldState calculateSupportingPaneScaffoldState(java.util.List<? extends androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<?>> destinationHistory, optional androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class SupportingPaneScaffoldRole {
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getExtra();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getMain();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getSupporting();
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Extra;
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Main;
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Supporting;
-    field public static final androidx.compose.material3.adaptive.SupportingPaneScaffoldRole INSTANCE;
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldAdaptStrategies {
-    ctor public ThreePaneScaffoldAdaptStrategies(androidx.compose.material3.adaptive.AdaptStrategy primaryPaneAdaptStrategy, androidx.compose.material3.adaptive.AdaptStrategy secondaryPaneAdaptStrategy, androidx.compose.material3.adaptive.AdaptStrategy tertiaryPaneAdaptStrategy);
-    method public operator androidx.compose.material3.adaptive.AdaptStrategy get(androidx.compose.material3.adaptive.ThreePaneScaffoldRole role);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public final class ThreePaneScaffoldDestinationItem<T> {
-    ctor public ThreePaneScaffoldDestinationItem(androidx.compose.material3.adaptive.ThreePaneScaffoldRole pane, optional T? content);
-    method public T? getContent();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldRole getPane();
-    property public final T? content;
-    property public final androidx.compose.material3.adaptive.ThreePaneScaffoldRole pane;
-    field public static final androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem.Companion Companion;
-  }
-
-  public static final class ThreePaneScaffoldDestinationItem.Companion {
-  }
-
-  public final class ThreePaneScaffoldKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static void AnimatedPane(androidx.compose.material3.adaptive.ThreePaneScaffoldScope, androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1<? super androidx.compose.material3.adaptive.ThreePaneScaffoldScope,kotlin.Unit> content);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public interface ThreePaneScaffoldNavigator<T> {
-    method public boolean canNavigateBack(optional androidx.compose.material3.adaptive.BackNavigationBehavior backNavigationBehavior);
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<T>? getCurrentDestination();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldState getScaffoldState();
-    method public boolean isDestinationHistoryAware();
-    method public boolean navigateBack(optional androidx.compose.material3.adaptive.BackNavigationBehavior backNavigationBehavior);
-    method public void navigateTo(androidx.compose.material3.adaptive.ThreePaneScaffoldRole pane, optional T? content);
-    method public void setDestinationHistoryAware(boolean);
-    property public abstract androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<T>? currentDestination;
-    property public abstract boolean isDestinationHistoryAware;
-    property public abstract androidx.compose.material3.adaptive.ThreePaneScaffoldState scaffoldState;
-  }
-
-  public final class ThreePaneScaffoldNavigatorKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static <T> androidx.compose.material3.adaptive.ThreePaneScaffoldNavigator<T> rememberListDetailPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware, optional java.util.List<? extends androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<? extends T>> initialDestinationHistory);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Composable public static <T> androidx.compose.material3.adaptive.ThreePaneScaffoldNavigator<T> rememberSupportingPaneScaffoldNavigator(optional androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective, optional androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies, optional boolean isDestinationHistoryAware, optional java.util.List<? extends androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<? extends T>> initialDestinationHistory);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public enum ThreePaneScaffoldRole {
-    method public static androidx.compose.material3.adaptive.ThreePaneScaffoldRole valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
-    method public static androidx.compose.material3.adaptive.ThreePaneScaffoldRole[] values();
-    enum_constant public static final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Primary;
-    enum_constant public static final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Secondary;
-    enum_constant public static final androidx.compose.material3.adaptive.ThreePaneScaffoldRole Tertiary;
-  }
-
-  public interface ThreePaneScaffoldScope extends androidx.compose.material3.adaptive.PaneScaffoldScope {
-    method public String getAnimationToolingLabel();
-    method public androidx.compose.animation.EnterTransition getEnterTransition();
-    method public androidx.compose.animation.ExitTransition getExitTransition();
-    method public String getPaneAdaptedValue();
-    method public androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>? getPositionAnimationSpec();
-    property public abstract String animationToolingLabel;
-    property public abstract androidx.compose.animation.EnterTransition enterTransition;
-    property public abstract androidx.compose.animation.ExitTransition exitTransition;
-    property public abstract String paneAdaptedValue;
-    property public abstract androidx.compose.animation.core.FiniteAnimationSpec<androidx.compose.ui.unit.IntOffset>? positionAnimationSpec;
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Stable public interface ThreePaneScaffoldState {
-    method public androidx.compose.material3.adaptive.PaneScaffoldDirective getScaffoldDirective();
-    method public androidx.compose.material3.adaptive.ThreePaneScaffoldValue getScaffoldValue();
-    property public abstract androidx.compose.material3.adaptive.PaneScaffoldDirective scaffoldDirective;
-    property public abstract androidx.compose.material3.adaptive.ThreePaneScaffoldValue scaffoldValue;
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class ThreePaneScaffoldValue {
-    ctor public ThreePaneScaffoldValue(String primary, String secondary, String tertiary);
-    method public operator String get(androidx.compose.material3.adaptive.ThreePaneScaffoldRole role);
-    method public String getPrimary();
-    method public String getSecondary();
-    method public String getTertiary();
-    property public final String primary;
-    property public final String secondary;
-    property public final String tertiary;
-  }
-
-  public final class ThreePaneScaffoldValueKt {
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.ThreePaneScaffoldValue calculateThreePaneScaffoldValue(int maxHorizontalPartitions, androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies, androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<?>? currentDestination);
-    method @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi public static androidx.compose.material3.adaptive.ThreePaneScaffoldValue calculateThreePaneScaffoldValue(int maxHorizontalPartitions, androidx.compose.material3.adaptive.ThreePaneScaffoldAdaptStrategies adaptStrategies, java.util.List<? extends androidx.compose.material3.adaptive.ThreePaneScaffoldDestinationItem<?>> destinationHistory);
-  }
-
-  @SuppressCompatibility @androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi @androidx.compose.runtime.Immutable public final class WindowAdaptiveInfo {
-    ctor public WindowAdaptiveInfo(androidx.window.core.layout.WindowSizeClass windowSizeClass, androidx.compose.material3.adaptive.Posture windowPosture);
-    method public androidx.compose.material3.adaptive.Posture getWindowPosture();
-    method public androidx.window.core.layout.WindowSizeClass getWindowSizeClass();
-    property public final androidx.compose.material3.adaptive.Posture windowPosture;
-    property public final androidx.window.core.layout.WindowSizeClass windowSizeClass;
-  }
-
-}
-
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/WindowInfo.kt b/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/WindowInfo.kt
deleted file mode 100644
index dca80dd..0000000
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/WindowInfo.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3.adaptive
-
-import androidx.compose.runtime.Composable
-import androidx.window.core.layout.WindowSizeClass
-
-/**
- * Calculates and returns [WindowAdaptiveInfo] of the provided context. It's a convenient function
- * that uses the default [WindowSizeClass] constructor and the default [Posture] calculation
- * functions to retrieve [WindowSizeClass] and [Posture].
- *
- * @return [WindowAdaptiveInfo] of the provided context
- */
-@ExperimentalMaterial3AdaptiveApi
-@Composable
-expect fun currentWindowAdaptiveInfo(): WindowAdaptiveInfo
diff --git a/compose/material3/material3-common/build.gradle b/compose/material3/material3-common/build.gradle
index 09fa42b..804a2d2 100644
--- a/compose/material3/material3-common/build.gradle
+++ b/compose/material3/material3-common/build.gradle
@@ -42,14 +42,12 @@
         commonMain {
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
-
-                api(project(":compose:foundation:foundation"))
-                api(project(":compose:foundation:foundation-layout"))
-                api(project(":compose:runtime:runtime"))
-                api(project(":compose:ui:ui-graphics"))
-                api(project(":compose:ui:ui-text"))
-
                 implementation(project(":compose:ui:ui-util"))
+                api("androidx.compose.foundation:foundation:1.6.0")
+                api("androidx.compose.foundation:foundation-layout:1.6.0")
+                api("androidx.compose.runtime:runtime:1.6.0")
+                api("androidx.compose.ui:ui-graphics:1.6.0")
+                api("androidx.compose.ui:ui-text:1.6.0")
             }
         }
         androidMain.dependencies {
@@ -77,7 +75,6 @@
         desktopMain {
             dependsOn(jvmMain)
             dependencies {
-                implementation(libs.kotlinStdlib)
             }
         }
 
diff --git a/compose/material3/material3-window-size-class/build.gradle b/compose/material3/material3-window-size-class/build.gradle
index ed1e25f..8ae1969 100644
--- a/compose/material3/material3-window-size-class/build.gradle
+++ b/compose/material3/material3-window-size-class/build.gradle
@@ -40,10 +40,10 @@
         commonMain {
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
-                implementation(project(":compose:ui:ui-util"))
-                api(project(":compose:runtime:runtime"))
-                api(project(":compose:ui:ui"))
-                api(project(":compose:ui:ui-unit"))
+                implementation("androidx.compose.ui:ui-util:1.6.0")
+                api("androidx.compose.runtime:runtime:1.6.0")
+                api("androidx.compose.ui:ui:1.6.0")
+                api("androidx.compose.ui:ui-unit:1.6.0")
             }
         }
 
@@ -63,11 +63,6 @@
         skikoMain {
             dependsOn(commonMain)
             dependencies {
-                // Because dependencies are pinned in the android/common code.
-                implementation("androidx.compose.ui:ui-util:1.6.0-rc01")
-                api("androidx.compose.runtime:runtime:1.6.0-rc01")
-                api("androidx.compose.ui:ui:1.6.0-rc01")
-                api("androidx.compose.ui:ui-unit:1.6.0-rc01")
             }
         }
 
diff --git a/compose/material3/material3/build.gradle b/compose/material3/material3/build.gradle
index 101f313..aa50925 100644
--- a/compose/material3/material3/build.gradle
+++ b/compose/material3/material3/build.gradle
@@ -28,7 +28,6 @@
     id("AndroidXPlugin")
     id("com.android.library")
     id("AndroidXComposePlugin")
-    id("AndroidXPaparazziPlugin")
 }
 
 androidXMultiplatform {
@@ -43,16 +42,15 @@
                 implementation(libs.kotlinStdlibCommon)
                 // Keep pinned unless there is a need for tip of tree behavior
                 implementation("androidx.collection:collection:1.4.0")
-                implementation(project(":compose:animation:animation-core"))
-
+                implementation("androidx.compose.animation:animation-core:1.6.0")
+                implementation("androidx.compose.ui:ui-util:1.6.0")
                 api(project(":compose:foundation:foundation"))
-                api(project(":compose:foundation:foundation-layout"))
-                api(project(":compose:material:material-icons-core"))
+                api("androidx.compose.foundation:foundation-layout:1.6.0")
+                api("androidx.compose.material:material-icons-core:1.6.0")
                 api(project(":compose:material:material-ripple"))
-                api(project(":compose:runtime:runtime"))
-                api(project(":compose:ui:ui"))
-                api(project(":compose:ui:ui-text"))
-                implementation(project(":compose:ui:ui-util"))
+                api("androidx.compose.runtime:runtime:1.6.0")
+                api("androidx.compose.ui:ui:1.6.0")
+                api("androidx.compose.ui:ui-text:1.6.0")
             }
         }
 
@@ -70,14 +68,6 @@
         skikoMain {
             dependsOn(commonMain)
             dependencies {
-                api(project(":compose:animation:animation-core"))
-                api(project(":compose:runtime:runtime"))
-                api(project(":compose:ui:ui"))
-                api(project(":compose:ui:ui-text"))
-                api(project(":compose:foundation:foundation-layout"))
-
-                implementation(project(":compose:animation:animation"))
-                implementation(project(":compose:ui:ui-util"))
             }
         }
 
diff --git a/compose/material3/material3/integration-tests/material3-catalog/build.gradle b/compose/material3/material3/integration-tests/material3-catalog/build.gradle
index c7aeee6..699cb55 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/build.gradle
+++ b/compose/material3/material3/integration-tests/material3-catalog/build.gradle
@@ -39,9 +39,9 @@
     implementation project(":compose:ui:ui")
     implementation project(":compose:material:material")
     implementation project(":compose:material:material-icons-extended")
+    implementation project(":compose:material3:adaptive:adaptive-samples")
     implementation project(":compose:material3:material3")
     implementation project(":compose:material3:material3:material3-samples")
-    implementation project(":compose:material3:material3-adaptive:material3-adaptive-samples")
     implementation project(":compose:material3:material3-adaptive-navigation-suite:material3-adaptive-navigation-suite-samples")
     implementation project(":datastore:datastore-preferences")
     implementation project(":navigation:navigation-compose")
diff --git a/compose/material3/material3/lint-baseline.xml b/compose/material3/material3/lint-baseline.xml
index dc2af50..f59d635 100644
--- a/compose/material3/material3/lint-baseline.xml
+++ b/compose/material3/material3/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="BanThreadSleep"
@@ -40,24 +40,6 @@
     <issue
         id="BanThreadSleep"
         message="Uses Thread.sleep()"
-        errorLine1="        Thread.sleep(300)"
-        errorLine2="               ~~~~~">
-        <location
-            file="src/androidInstrumentedTest/kotlin/androidx/compose/material3/MaterialRippleThemeTest.kt"/>
-    </issue>
-
-    <issue
-        id="BanThreadSleep"
-        message="Uses Thread.sleep()"
-        errorLine1="            Thread.sleep(300)"
-        errorLine2="                   ~~~~~">
-        <location
-            file="src/androidInstrumentedTest/kotlin/androidx/compose/material3/MaterialRippleThemeTest.kt"/>
-    </issue>
-
-    <issue
-        id="BanThreadSleep"
-        message="Uses Thread.sleep()"
         errorLine1="            Thread.sleep(300)"
         errorLine2="                   ~~~~~">
         <location
@@ -284,24 +266,6 @@
 
     <issue
         id="PrimitiveInCollection"
-        message="variable xCandidates with type List&lt;? extends Integer>: replace with IntList"
-        errorLine1="        val xCandidates = listOf("
-        errorLine2="        ^">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/material3/MenuPosition.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="variable yCandidates with type List&lt;? extends Integer>: replace with IntList"
-        errorLine1="        val yCandidates = listOf("
-        errorLine2="        ^">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/material3/MenuPosition.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
         message="variable tabContentWidths with type List&lt;Dp>: replace with FloatList"
         errorLine1="            val tabContentWidths = mutableListOf&lt;Dp>()"
         errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
diff --git a/compose/material3/material3/src/androidUnitTest/kotlin/androidx/compose/material3/ButtonPaparazziTest.kt b/compose/material3/material3/src/androidUnitTest/kotlin/androidx/compose/material3/ButtonPaparazziTest.kt
deleted file mode 100644
index e386d4e..0000000
--- a/compose/material3/material3/src/androidUnitTest/kotlin/androidx/compose/material3/ButtonPaparazziTest.kt
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.compose.material3
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.requiredSize
-import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.wrapContentSize
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Favorite
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.unit.dp
-import androidx.testutils.paparazzi.androidxPaparazzi
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class ButtonPaparazziTest {
-    @get:Rule
-    val paparazzi = androidxPaparazzi()
-
-    @Test
-    fun default_button_light_theme() {
-        paparazzi.snapshot {
-            MaterialTheme(lightColorScheme()) {
-                Surface {
-                    Button( }) {
-                        Text("Button")
-                    }
-                }
-            }
-        }
-    }
-
-    @Test
-    fun default_button_dark_theme() {
-        paparazzi.snapshot {
-            MaterialTheme(darkColorScheme()) {
-                Surface {
-                    Button( }) {
-                        Text("Button")
-                    }
-                }
-            }
-        }
-    }
-
-    @Test
-    fun disabled_button_light_theme() {
-        paparazzi.snapshot {
-            MaterialTheme(lightColorScheme()) {
-                Surface {
-                    Button( }, enabled = false) {
-                        Text("Button")
-                    }
-                }
-            }
-        }
-    }
-
-    @Test
-    fun disabled_button_dark_theme() {
-        paparazzi.snapshot {
-            MaterialTheme(darkColorScheme()) {
-                Surface {
-                    Button( }, enabled = false) {
-                        Text("Button")
-                    }
-                }
-            }
-        }
-    }
-
-    @Test
-    fun elevated_button_light_theme() {
-        paparazzi.snapshot {
-            MaterialTheme(lightColorScheme()) {
-                Surface {
-                    Box(
-                        Modifier.requiredSize(
-                            200.dp,
-                            100.dp
-                        ).wrapContentSize().testTag("elevated button")
-                    ) {
-                        ElevatedButton( { Text("Elevated Button") }
-                    }
-                }
-            }
-        }
-    }
-
-    @Test
-    fun elevated_button_dark_theme() {
-        paparazzi.snapshot {
-            MaterialTheme(darkColorScheme()) {
-                Surface {
-                    Box(
-                        Modifier.requiredSize(
-                            200.dp,
-                            100.dp
-                        ).wrapContentSize().testTag("elevated button")
-                    ) {
-                        ElevatedButton( { Text("Elevated Button") }
-                    }
-                }
-            }
-        }
-    }
-
-    @Test
-    fun disabled_elevated_button_light_theme() {
-        paparazzi.snapshot {
-            MaterialTheme(lightColorScheme()) {
-                Surface {
-                    Box(
-                        Modifier.requiredSize(
-                            200.dp,
-                            100.dp
-                        ).wrapContentSize().testTag("elevated button")
-                    ) {
-                        ElevatedButton( enabled = false) { Text("Elevated Button") }
-                    }
-                }
-            }
-        }
-    }
-
-    @Test
-    fun disabled_elevated_button_dark_theme() {
-        paparazzi.snapshot {
-            MaterialTheme(darkColorScheme()) {
-                Surface {
-                    Box(
-                        Modifier.requiredSize(
-                            200.dp,
-                            100.dp
-                        ).wrapContentSize().testTag("elevated button")
-                    ) {
-                        ElevatedButton( enabled = false) { Text("Elevated Button") }
-                    }
-                }
-            }
-        }
-    }
-
-    @Test
-    fun button_with_icon_light_theme() {
-        paparazzi.snapshot {
-            MaterialTheme(lightColorScheme()) {
-                Surface {
-                    Button(
-                         /* Do something! */ },
-                        contentPadding = ButtonDefaults.ButtonWithIconContentPadding
-                    ) {
-                        Icon(
-                            Icons.Filled.Favorite,
-                            contentDescription = "Localized description",
-                            modifier = Modifier.size(ButtonDefaults.IconSize)
-                        )
-                        Spacer(Modifier.size(ButtonDefaults.IconSpacing))
-                        Text("Like")
-                    }
-                }
-            }
-        }
-    }
-
-    @Test
-    fun button_with_icon_dark_theme() {
-        paparazzi.snapshot {
-            MaterialTheme(darkColorScheme()) {
-                Surface {
-                    Button(
-                         /* Do something! */ },
-                        contentPadding = ButtonDefaults.ButtonWithIconContentPadding
-                    ) {
-                        Icon(
-                            Icons.Filled.Favorite,
-                            contentDescription = "Localized description",
-                            modifier = Modifier.size(ButtonDefaults.IconSize)
-                        )
-                        Spacer(Modifier.size(ButtonDefaults.IconSpacing))
-                        Text("Like")
-                    }
-                }
-            }
-        }
-    }
-
-    @Test
-    fun disabled_button_with_icon_light_theme() {
-        paparazzi.snapshot {
-            MaterialTheme(lightColorScheme()) {
-                Surface {
-                    Button(
-                         /* Do something! */ },
-                        contentPadding = ButtonDefaults.ButtonWithIconContentPadding,
-                        enabled = false,
-                    ) {
-                        Icon(
-                            Icons.Filled.Favorite,
-                            contentDescription = "Localized description",
-                            modifier = Modifier.size(ButtonDefaults.IconSize)
-                        )
-                        Spacer(Modifier.size(ButtonDefaults.IconSpacing))
-                        Text("Like")
-                    }
-                }
-            }
-        }
-    }
-
-    @Test
-    fun disabled_button_with_icon_dark_theme() {
-        paparazzi.snapshot {
-            MaterialTheme(darkColorScheme()) {
-                Surface {
-                    Button(
-                         /* Do something! */ },
-                        contentPadding = ButtonDefaults.ButtonWithIconContentPadding,
-                        enabled = false,
-                    ) {
-                        Icon(
-                            Icons.Filled.Favorite,
-                            contentDescription = "Localized description",
-                            modifier = Modifier.size(ButtonDefaults.IconSize)
-                        )
-                        Spacer(Modifier.size(ButtonDefaults.IconSpacing))
-                        Text("Like")
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/compose/material3/material3/src/androidUnitTest/kotlin/androidx/compose/material3/carousel/MultiBrowseTest.kt b/compose/material3/material3/src/androidUnitTest/kotlin/androidx/compose/material3/carousel/MultiBrowseTest.kt
index 2b6d054..1583cc5 100644
--- a/compose/material3/material3/src/androidUnitTest/kotlin/androidx/compose/material3/carousel/MultiBrowseTest.kt
+++ b/compose/material3/material3/src/androidUnitTest/kotlin/androidx/compose/material3/carousel/MultiBrowseTest.kt
@@ -25,13 +25,13 @@
 @RunWith(JUnit4::class)
 class MultiBrowseTest {
 
-    private val density = Density(1f)
+    private val Density = Density(1f)
 
     @Test
     fun testMultiBrowse_doesNotResizeLargeWhenEnoughRoom() {
         val itemSize = 120f // minSmallItemSize = 40.dp * 3
         val keylineList = multiBrowseKeylineList(
-            density = density,
+            density = Density,
             carouselMainAxisSize = 500f,
             preferredItemSize = itemSize,
             itemSpacing = 0f
@@ -48,7 +48,7 @@
     fun testMultiBrowse_resizesItemLargerThanContainerToFit1Small() {
         val itemSize = 200f
         val keylineList = multiBrowseKeylineList(
-            density = density,
+            density = Density,
             carouselMainAxisSize = 100f,
             preferredItemSize = itemSize,
             itemSpacing = 0f
@@ -58,7 +58,7 @@
             carouselMainAxisSize = 100f,
             keylineList = keylineList
         )
-        val minSmallItemSize: Float = with(density) { StrategyDefaults.minSmallSize.toPx() }
+        val minSmallItemSize: Float = with(Density) { StrategyDefaults.MinSmallSize.toPx() }
         val keylines = strategy.getDefaultKeylines()
 
         // If the item size given is larger than the container, the adjusted keyline list from
@@ -73,9 +73,9 @@
 
     @Test
     fun testMultiBrowse_hasNoSmallItemsIfNotEnoughRoom() {
-        val minSmallItemSize: Float = with(density) { StrategyDefaults.minSmallSize.toPx() }
+        val minSmallItemSize: Float = with(Density) { StrategyDefaults.MinSmallSize.toPx() }
         val keylineList = multiBrowseKeylineList(
-            density = density,
+            density = Density,
             carouselMainAxisSize = minSmallItemSize,
             preferredItemSize = 200f,
             itemSpacing = 0f
@@ -94,7 +94,7 @@
     @Test
     fun testMultiBrowse_isNullIfAvailableSpaceIsZero() {
         val keylineList = multiBrowseKeylineList(
-            density = density,
+            density = Density,
             carouselMainAxisSize = 0f,
             preferredItemSize = 200f,
             itemSpacing = 0f
@@ -104,11 +104,11 @@
 
     @Test
     fun testMultiBrowse_adjustsMediumSizeToBeProportional() {
-        val maxSmallItemSize: Float = with(density) { StrategyDefaults.maxSmallSize.toPx() }
+        val maxSmallItemSize: Float = with(Density) { StrategyDefaults.MaxSmallSize.toPx() }
         val preferredItemSize = 200f
         val carouselSize = preferredItemSize * 2 + maxSmallItemSize * 2
         val keylineList = multiBrowseKeylineList(
-            density = density,
+            density = Density,
             carouselMainAxisSize = carouselSize,
             preferredItemSize = preferredItemSize,
             itemSpacing = 0f
diff --git a/compose/material3/material3/src/androidUnitTest/kotlin/androidx/compose/material3/carousel/UncontainedTest.kt b/compose/material3/material3/src/androidUnitTest/kotlin/androidx/compose/material3/carousel/UncontainedTest.kt
new file mode 100644
index 0000000..0110805
--- /dev/null
+++ b/compose/material3/material3/src/androidUnitTest/kotlin/androidx/compose/material3/carousel/UncontainedTest.kt
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.carousel
+
+import androidx.compose.ui.unit.Density
+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 UncontainedTest {
+
+    private val Density = Density(1f)
+
+    @Test
+    fun testLargeItem_withFullCarouselWidth() {
+        val itemSize = 500f
+        val carouselSize = 500f
+        val keylineList = uncontainedKeylineList(
+            density = Density,
+            carouselMainAxisSize = carouselSize,
+            itemSize = itemSize,
+            itemSpacing = 0f
+        )!!
+        val strategy = Strategy.create(
+            carouselMainAxisSize = carouselSize,
+            keylineList = keylineList
+        )
+        val keylines = strategy.getDefaultKeylines()
+        val anchorSize = with(Density) { StrategyDefaults.AnchorSize.toPx() }
+
+        // A fullscreen layout should be [xSmall-large-xSmall] where the xSmall items are
+        // outside the bounds of the carousel container and the large item takes up the
+        // containers full width.
+        assertThat(keylines.size).isEqualTo(3)
+        assertThat(keylines[0].offset).isEqualTo(-anchorSize / 2f)
+        assertThat(keylines[1].size).isEqualTo(carouselSize)
+        assertThat(keylines[2].offset).isEqualTo(carouselSize + anchorSize / 2f)
+    }
+
+    @Test
+    fun testLargeItem_largerThanFullCarouselWidth() {
+        val carouselSize = 400f
+        val itemSize = 500f
+        val keylineList = uncontainedKeylineList(
+            density = Density,
+            carouselMainAxisSize = carouselSize,
+            itemSize = itemSize,
+            itemSpacing = 0f
+        )!!
+        val strategy = Strategy.create(
+            carouselMainAxisSize = carouselSize,
+            keylineList = keylineList
+        )
+        val keylines = strategy.getDefaultKeylines()
+        val anchorSize = with(Density) { StrategyDefaults.AnchorSize.toPx() }
+
+        // The layout should be [xSmall-large-xSmall] where the xSmall items are
+        // outside the bounds of the carousel container and the large item takes up the
+        // containers full width.
+        assertThat(keylines.size).isEqualTo(3)
+        assertThat(keylines[0].offset).isEqualTo(-anchorSize / 2f)
+        assertThat(keylines[1].size).isEqualTo(carouselSize)
+        assertThat(keylines[2].offset).isEqualTo(carouselSize + anchorSize / 2f)
+    }
+
+    @Test
+    fun testRemainingSpaceWithItemSize_fitsItemWithThirdCutoff() {
+        val carouselSize = 400f
+        // With size 125px, 3 large items can fit with in 400px, with 25px left. 25px * 3 = 75px,
+        // which will be the size of the medium item since it can be a third cut off and it is less
+        // than the threshold percentage * large item size.
+        val itemSize = 125f
+        val keylineList = uncontainedKeylineList(
+            density = Density,
+            carouselMainAxisSize = carouselSize,
+            itemSize = itemSize,
+            itemSpacing = 0f
+        )!!
+        val strategy = Strategy.create(
+            carouselMainAxisSize = carouselSize,
+            keylineList = keylineList
+        )
+        val keylines = strategy.getDefaultKeylines()
+
+        // The layout should be [xSmall-large-large-large-medium-xSmall] where medium is a size
+        // such that a third of it is cut off.
+        assertThat(keylines.size).isEqualTo(6)
+        assertThat(keylines[1].size).isEqualTo(itemSize)
+        assertThat(keylines[2].size).isEqualTo(itemSize)
+        assertThat(keylines[3].size).isEqualTo(itemSize)
+        // The cutoff size should be a size that has a third of itself cut off with the given
+        // remaining space, which is 25f as explained above.
+        assertThat(keylines[4].size).isEqualTo(25f * 1.5f)
+        assertThat(keylines[4].offset).isEqualTo(393.75f) // itemSize * 3 + (25 * 1.5f / 2)
+        assertThat(keylines[0].size).isEqualTo(18.75f) // half the med size is the anchor size
+        assertThat(keylines[0].offset).isEqualTo(-9.375f) // -18.75f/2
+        assertThat(keylines[5].offset)
+            .isEqualTo(421.875f) // itemSize*3 + 25f * 1.5f + 18.75f/2
+    }
+
+    @Test
+    fun testRemainingSpaceWithItemSize_fitsMediumItemWithCutoff() {
+        val carouselSize = 400f
+        // With size 105px, 3 large items can fit with in 400px, with 85px left over.  85*3 = 255
+        // which is well over the size of the large item, so the medium size will be limited to
+        // whichever is larger between 85% of the large size, or 110% of the remainingSpace to make
+        // it at most 10% cut off.
+        val itemSize = 105f
+        val keylineList = uncontainedKeylineList(
+            density = Density,
+            carouselMainAxisSize = carouselSize,
+            itemSize = itemSize,
+            itemSpacing = 0f
+        )!!
+        val strategy = Strategy.create(
+            carouselMainAxisSize = carouselSize,
+            keylineList = keylineList
+        )
+        val keylines = strategy.getDefaultKeylines()
+
+        // The layout should be [xSmall-large-large-large-medium-xSmall]
+        assertThat(keylines.size).isEqualTo(6)
+        assertThat(keylines[1].size).isEqualTo(itemSize)
+        assertThat(keylines[2].size).isEqualTo(itemSize)
+        assertThat(keylines[3].size).isEqualTo(itemSize)
+        // remainingSpace * 120%
+        assertThat(keylines[4].size).isEqualTo(85 * 1.2f)
+        assertThat(keylines[0].size).isEqualTo(85 * 1.2f * 0.5f)
+        assertThat(keylines[5].size).isEqualTo(85 * 1.2f * 0.5f)
+        assertThat(keylines[0].offset).isEqualTo(-(85 * 1.2f * 0.5f) / 2f)
+        assertThat(keylines[5].offset)
+            .isEqualTo(itemSize * 3 + 85 * 1.2f + (85 * 1.2f * 0.5f) / 2f)
+    }
+}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Carousel.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Carousel.kt
index 8982afe..9dd4eb7 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Carousel.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Carousel.kt
@@ -56,20 +56,18 @@
  * For more information, see <a href="https://material.io/components/carousel/overview">design
  * guidelines</a>.
  *
- * @param state The state object to be used to control the carousel's state.
+ * @param state The state object to be used to control the carousel's state
  * @param preferredItemSize The size fully visible items would like to be in the main axis. This
  * size is a target and will likely be adjusted by carousel in order to fit a whole number of
- * items within the container.
- * @param modifier A modifier instance to be applied to this carousel outer layout
+ * items within the container
+ * @param modifier A modifier instance to be applied to this carousel container
  * @param itemSpacing The amount of space used to separate items in the carousel
  * @param minSmallSize The minimum allowable size of small masked items
  * @param maxSmallSize The maximum allowable size of small masked items
- * @param content The carousel's content Composable.
+ * @param content The carousel's content Composable
  *
  * TODO: Add sample link
  */
-@Suppress("IllegalExperimentalApiUsage")
-@OptIn(ExperimentalFoundationApi::class)
 @ExperimentalMaterial3Api
 @Composable
 internal fun HorizontalMultiBrowseCarousel(
@@ -77,9 +75,9 @@
     preferredItemSize: Dp,
     modifier: Modifier = Modifier,
     itemSpacing: Dp = 0.dp,
-    minSmallSize: Dp = StrategyDefaults.minSmallSize,
-    maxSmallSize: Dp = StrategyDefaults.maxSmallSize,
-    content: @Composable CarouselScope.(item: Int) -> Unit
+    minSmallSize: Dp = StrategyDefaults.MinSmallSize,
+    maxSmallSize: Dp = StrategyDefaults.MaxSmallSize,
+    content: @Composable CarouselScope.(itemIndex: Int) -> Unit
 ) {
     val density = LocalDensity.current
     Carousel(
@@ -106,6 +104,56 @@
 /**
  * <a href=https://m3.material.io/components/carousel/overview" class="external" target="_blank">Material Design Carousel</a>
  *
+ * A horizontal carousel that displays its items with the given size except for one item at the end
+ * that is cut off.
+ *
+ * Note that the item size will be bound by the size of the carousel. Otherwise, this carousel lays
+ * out as many items as it can in the given size, and changes the size of the last cut off item such
+ * that there is a range of motion when items scroll off the edge.
+ *
+ * For more information, see <a href="https://material.io/components/carousel/overview">design
+ * guidelines</a>.
+ *
+ * @param state The state object to be used to control the carousel's state
+ * @param itemSize The size of items in the carousel
+ * @param modifier A modifier instance to be applied to this carousel container
+ * @param itemSpacing The amount of space used to separate items in the carousel
+ * @param content The carousel's content Composable
+ *
+ * TODO: Add sample link
+ */
+@ExperimentalMaterial3Api
+@Composable
+internal fun HorizontalUncontainedCarousel(
+    state: CarouselState,
+    itemSize: Dp,
+    modifier: Modifier = Modifier,
+    itemSpacing: Dp = 0.dp,
+    content: @Composable CarouselScope.(itemIndex: Int) -> Unit
+) {
+    val density = LocalDensity.current
+    Carousel(
+        state = state,
+        orientation = Orientation.Horizontal,
+        keylineList = {
+            with(density) {
+                uncontainedKeylineList(
+                    density = this,
+                    carouselMainAxisSize = state.pagerState.layoutInfo.viewportSize.width.toFloat(),
+                    itemSize = itemSize.toPx(),
+                    itemSpacing = itemSpacing.toPx(),
+                )
+            }
+        },
+        modifier = modifier,
+        itemSpacing = itemSpacing,
+        content = content
+    )
+}
+
+/**
+ * <a href=https://m3.material.io/components/carousel/overview" class="external" target="_blank">Material Design Carousel</a>
+ *
  * Carousels contain a collection of items that changes sizes according to their placement and the
  * chosen strategy.
  *
@@ -119,10 +167,6 @@
  * total item count, of the item being composed
  * TODO: Add sample link
  */
-// TODO: b/321997456 - Remove lint suppression once version checks are added in lint or library
-// moves to beta
-@Suppress("IllegalExperimentalApiUsage")
-@OptIn(ExperimentalFoundationApi::class)
 @ExperimentalMaterial3Api
 @Composable
 internal fun Carousel(
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Keyline.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/KeylineList.kt
similarity index 82%
rename from compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Keyline.kt
rename to compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/KeylineList.kt
index c445137..653d829 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Keyline.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/KeylineList.kt
@@ -16,101 +16,9 @@
 
 package androidx.compose.material3.carousel
 
-import androidx.compose.ui.unit.Density
 import androidx.compose.ui.util.fastFirstOrNull
 import androidx.compose.ui.util.fastMapIndexed
 import kotlin.math.abs
-import kotlin.math.ceil
-import kotlin.math.floor
-import kotlin.math.max
-import kotlin.math.min
-
-/**
- * Creates a list of keylines that arranges items into a multi-browse configuration.
- *
- * Note that this function may adjust the size of large items. In order to ensure large, medium,
- * and small items fit perfectly into the available space and are numbered/arranged in a
- * visually pleasing and opinionated way, this strategy finds the nearest number of large items that
- * will fit into an approved arrangement that requires the least amount of size adjustment
- * necessary.
- *
- * For more information, see <a href="https://material.io/components/carousel/overview">design
- * guidelines</a>.
- *
- * @param density The [Density] object that provides pixel density information of the device
- * @param carouselMainAxisSize the size of the carousel container, in pixels, in the main
- * scrolling axis
- * @param preferredItemSize the desired size of large items, in pixels, in the main scrolling axis
- * @param itemSpacing the spacing between items in pixels
- * @param minSmallSize the minimum allowable size of small items in pixels
- * @param maxSmallSize the maximum allowable size of small items in pixels
- */
-internal fun multiBrowseKeylineList(
-    density: Density,
-    carouselMainAxisSize: Float,
-    preferredItemSize: Float,
-    itemSpacing: Float,
-    minSmallSize: Float = with(density) { StrategyDefaults.minSmallSize.toPx() },
-    maxSmallSize: Float = with(density) { StrategyDefaults.maxSmallSize.toPx() },
-): KeylineList? {
-    if (carouselMainAxisSize == 0f || preferredItemSize == 0f) {
-        return null
-    }
-
-    var smallCounts: IntArray = intArrayOf(1)
-    val mediumCounts: IntArray = intArrayOf(1, 0)
-
-    val targetLargeSize: Float = min(preferredItemSize + itemSpacing, carouselMainAxisSize)
-    // Ideally we would like to create a balanced arrangement where a small item is 1/3 the size
-    // of the large item and medium items are sized between large and small items. Clamp the
-    // small target size within our min-max range and as close to 1/3 of the target large item
-    // size as possible.
-    val targetSmallSize: Float = (targetLargeSize / 3f + itemSpacing).coerceIn(
-        minSmallSize + itemSpacing,
-        maxSmallSize + itemSpacing
-    )
-    val targetMediumSize = (targetLargeSize + targetSmallSize) / 2f
-
-    if (carouselMainAxisSize < minSmallSize * 2) {
-        // If the available space is too small to fit a large item and small item (where a large
-        // item is bigger than a small item), allow arrangements with
-        // no small items.
-        smallCounts = intArrayOf(0)
-    }
-
-    // Find the minimum space left for large items after filling the carousel with the most
-    // permissible medium and small items to determine a plausible minimum large count.
-    val minAvailableLargeSpace = carouselMainAxisSize - targetMediumSize * mediumCounts.max() -
-        maxSmallSize * smallCounts.max()
-    val minLargeCount = max(
-        1,
-        floor(minAvailableLargeSpace / targetLargeSize).toInt())
-    val maxLargeCount = ceil(carouselMainAxisSize / targetLargeSize).toInt()
-
-    val largeCounts = IntArray(maxLargeCount - minLargeCount + 1) { maxLargeCount - it }
-    val anchorSize = with(density) { StrategyDefaults.anchorSize.toPx() }
-    val arrangement = Arrangement.findLowestCostArrangement(
-        availableSpace = carouselMainAxisSize,
-        targetSmallSize = targetSmallSize,
-        minSmallSize = minSmallSize,
-        maxSmallSize = maxSmallSize,
-        smallCounts = smallCounts,
-        targetMediumSize = targetMediumSize,
-        mediumCounts = mediumCounts,
-        targetLargeSize = targetLargeSize,
-        largeCounts = largeCounts,
-    ) ?: return null
-
-    return keylineListOf(carouselMainAxisSize, CarouselAlignment.Start) {
-        add(anchorSize, isAnchor = true)
-
-        repeat(arrangement.largeCount) { add(arrangement.largeSize) }
-        repeat(arrangement.mediumCount) { add(arrangement.mediumSize) }
-        repeat(arrangement.smallCount) { add(arrangement.smallSize) }
-
-        add(anchorSize, isAnchor = true)
-    }
-}
 
 /**
  * A structure that is fixed at a specific [offset] along a scrolling axis and
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Keylines.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Keylines.kt
new file mode 100644
index 0000000..7d281be
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Keylines.kt
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.material3.carousel
+
+import androidx.compose.ui.unit.Density
+import kotlin.math.ceil
+import kotlin.math.floor
+import kotlin.math.max
+import kotlin.math.min
+
+/**
+ * Creates a list of keylines that arranges items into a multi-browse configuration.
+ *
+ * Note that this function may adjust the size of large items. In order to ensure large, medium,
+ * and small items fit perfectly into the available space and are numbered/arranged in a
+ * visually pleasing and opinionated way, this strategy finds the nearest number of large items that
+ * will fit into an approved arrangement that requires the least amount of size adjustment
+ * necessary.
+ *
+ * For more information, see <a href="https://material.io/components/carousel/overview">design
+ * guidelines</a>.
+ *
+ * @param density The [Density] object that provides pixel density information of the device
+ * @param carouselMainAxisSize The carousel container's pixel size in the main scrolling axis
+ * @param preferredItemSize the desired size of large items, in pixels, in the main scrolling axis
+ * @param itemSpacing the spacing between items in pixels
+ * @param minSmallSize the minimum allowable size of small items in pixels
+ * @param maxSmallSize the maximum allowable size of small items in pixels
+ */
+internal fun multiBrowseKeylineList(
+    density: Density,
+    carouselMainAxisSize: Float,
+    preferredItemSize: Float,
+    itemSpacing: Float,
+    minSmallSize: Float = with(density) { StrategyDefaults.MinSmallSize.toPx() },
+    maxSmallSize: Float = with(density) { StrategyDefaults.MaxSmallSize.toPx() },
+): KeylineList? {
+    if (carouselMainAxisSize == 0f || preferredItemSize == 0f) {
+        return null
+    }
+
+    var smallCounts: IntArray = intArrayOf(1)
+    val mediumCounts: IntArray = intArrayOf(1, 0)
+
+    val targetLargeSize: Float = min(preferredItemSize + itemSpacing, carouselMainAxisSize)
+    // Ideally we would like to create a balanced arrangement where a small item is 1/3 the size
+    // of the large item and medium items are sized between large and small items. Clamp the
+    // small target size within our min-max range and as close to 1/3 of the target large item
+    // size as possible.
+    val targetSmallSize: Float = (targetLargeSize / 3f + itemSpacing).coerceIn(
+        minSmallSize + itemSpacing,
+        maxSmallSize + itemSpacing
+    )
+    val targetMediumSize = (targetLargeSize + targetSmallSize) / 2f
+
+    if (carouselMainAxisSize < minSmallSize * 2) {
+        // If the available space is too small to fit a large item and small item (where a large
+        // item is bigger than a small item), allow arrangements with
+        // no small items.
+        smallCounts = intArrayOf(0)
+    }
+
+    // Find the minimum space left for large items after filling the carousel with the most
+    // permissible medium and small items to determine a plausible minimum large count.
+    val minAvailableLargeSpace = carouselMainAxisSize - targetMediumSize * mediumCounts.max() -
+        maxSmallSize * smallCounts.max()
+    val minLargeCount = max(
+        1,
+        floor(minAvailableLargeSpace / targetLargeSize).toInt())
+    val maxLargeCount = ceil(carouselMainAxisSize / targetLargeSize).toInt()
+
+    val largeCounts = IntArray(maxLargeCount - minLargeCount + 1) { maxLargeCount - it }
+    val anchorSize = with(density) { StrategyDefaults.AnchorSize.toPx() }
+    val arrangement = Arrangement.findLowestCostArrangement(
+        availableSpace = carouselMainAxisSize,
+        targetSmallSize = targetSmallSize,
+        minSmallSize = minSmallSize,
+        maxSmallSize = maxSmallSize,
+        smallCounts = smallCounts,
+        targetMediumSize = targetMediumSize,
+        mediumCounts = mediumCounts,
+        targetLargeSize = targetLargeSize,
+        largeCounts = largeCounts,
+    )
+
+    return if (arrangement == null) {
+        null
+    } else {
+        createStartAlignedKeylineList(
+            carouselMainAxisSize = carouselMainAxisSize,
+            anchorSize = anchorSize,
+            arrangement = arrangement
+        )
+    }
+}
+
+internal fun createStartAlignedKeylineList(
+    carouselMainAxisSize: Float,
+    anchorSize: Float,
+    arrangement: Arrangement
+): KeylineList {
+    return keylineListOf(carouselMainAxisSize, CarouselAlignment.Start) {
+        add(anchorSize, isAnchor = true)
+
+        repeat(arrangement.largeCount) { add(arrangement.largeSize) }
+        repeat(arrangement.mediumCount) { add(arrangement.mediumSize) }
+        repeat(arrangement.smallCount) { add(arrangement.smallSize) }
+
+        add(anchorSize, isAnchor = true)
+    }
+}
+
+/**
+ * Creates a list of keylines that arranges items into the 'uncontained' configuration. This
+ * configuration lays out as many items as it can in the given item size without getting cut off,
+ * and with the remaining space adds a cut off item with size constraints to ensure enough motion
+ * when scrolling off-screen.
+ *
+ * For more information, see <a href="https://material.io/components/carousel/overview">design
+ * guidelines</a>.
+ *
+ * @param density The [Density] object that provides pixel density information of the device
+ * @param carouselMainAxisSize The carousel container's pixel size in the main scrolling axis
+ * @param itemSize the size of large items, in pixels, in the main scrolling axis
+ * @param itemSpacing the spacing between items in pixels
+ */
+internal fun uncontainedKeylineList(
+    density: Density,
+    carouselMainAxisSize: Float,
+    itemSize: Float,
+    itemSpacing: Float,
+): KeylineList? {
+    if (carouselMainAxisSize == 0f || itemSize == 0f) {
+        return null
+    }
+
+    val largeItemSize = min(itemSize + itemSpacing, carouselMainAxisSize)
+    // Calculate how much space there is remaining after squeezing in as many large items as we can.
+    val largeCount = max(1, floor(carouselMainAxisSize / largeItemSize).toInt())
+    val remainingSpace: Float = carouselMainAxisSize - largeCount * largeItemSize
+
+    val mediumCount = if (remainingSpace > 0) 1 else 0
+
+    val defaultAnchorSize = with(density) { StrategyDefaults.AnchorSize.toPx() }
+    val mediumItemSize = calculateMediumChildSize(
+        minimumMediumSize = defaultAnchorSize,
+        largeItemSize = largeItemSize,
+        remainingSpace = remainingSpace)
+    val arrangement = Arrangement(
+        0,
+        0F,
+        0,
+        mediumItemSize,
+        mediumCount,
+        largeItemSize,
+        largeCount
+    )
+
+    val xSmallSize = min(defaultAnchorSize, itemSize)
+    // Make the anchor size half the cut off item size to make the motion at the left closer
+    // to the right where the cut off is.
+    val anchorSize: Float = max(xSmallSize, mediumItemSize * 0.5f)
+    return createStartAlignedKeylineList(
+        carouselMainAxisSize = carouselMainAxisSize,
+        anchorSize = anchorSize,
+        arrangement = arrangement)
+}
+
+/**
+ * Calculates a size of a medium item in the carousel that is not bigger than the large item
+ * size, and arbitrarily chooses a size small enough such that there is a size disparity between
+ * the medium and large sizes, but large enough to have a sufficient percentage cut off.
+ */
+private fun calculateMediumChildSize(
+    minimumMediumSize: Float,
+    largeItemSize: Float,
+    remainingSpace: Float
+): Float {
+    // With the remaining space, we want to add a 'medium' size item that gets sufficiently
+    // cut off. Ideally, it is large enough such that a third of the item is cut off, meaning
+    // that it is 1.5x the remaining space.
+    var mediumItemSize = minimumMediumSize
+    val sizeWithThirdCutOff = remainingSpace * 1.5f
+    mediumItemSize = max(sizeWithThirdCutOff, mediumItemSize)
+
+    // If the medium child is larger than the threshold percentage of the large child size,
+    // it's too similar and won't create sufficient motion when scrolling items between the large
+    // items and the medium item.
+    val largeItemThreshold: Float =
+        largeItemSize * StrategyDefaults.MediumLargeItemDiffThreshold
+    if (mediumItemSize > largeItemThreshold) {
+        // Choose whichever is bigger between the maximum threshold of the medium child size, or
+        // a size such that only 20% of the space is cut off.
+        val sizeWithFifthCutOff = remainingSpace * 1.2f
+        mediumItemSize = max(largeItemThreshold, sizeWithFifthCutOff)
+    }
+    return mediumItemSize
+}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Strategy.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Strategy.kt
index 8ca58e4..cf82756 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Strategy.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/carousel/Strategy.kt
@@ -28,9 +28,10 @@
  * Contains default values used across Strategies
  */
 internal object StrategyDefaults {
-    val minSmallSize = 40.dp
-    val maxSmallSize = 56.dp
-    val anchorSize = 10.dp
+    val MinSmallSize = 40.dp
+    val MaxSmallSize = 56.dp
+    val AnchorSize = 10.dp
+    const val MediumLargeItemDiffThreshold = 0.85f
 }
 
 /**
diff --git a/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/AutoboxingStateCreationDetector.kt b/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/AutoboxingStateCreationDetector.kt
index aeb86fe..50bd616 100644
--- a/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/AutoboxingStateCreationDetector.kt
+++ b/compose/runtime/runtime-lint/src/main/java/androidx/compose/runtime/lint/AutoboxingStateCreationDetector.kt
@@ -143,7 +143,8 @@
         val sourcePsi = invocation.sourcePsi as? KtElement ?: return null
         analyze(sourcePsi) {
             val resolvedCall = sourcePsi.resolveCall()?.singleFunctionCallOrNull() ?: return null
-            val stateType = resolvedCall.typeArgumentsMapping.asIterable().single().value
+            val stateType =
+                resolvedCall.typeArgumentsMapping.asIterable().singleOrNull()?.value ?: return null
             return when {
                 stateType.isMarkedNullable -> null
                 else -> {
diff --git a/compose/runtime/runtime-livedata/build.gradle b/compose/runtime/runtime-livedata/build.gradle
index 1dcfaa9..50cb9c3 100644
--- a/compose/runtime/runtime-livedata/build.gradle
+++ b/compose/runtime/runtime-livedata/build.gradle
@@ -32,7 +32,6 @@
 }
 
 dependencies {
-
     implementation(libs.kotlinStdlib)
 
     api(project(":compose:runtime:runtime"))
diff --git a/compose/runtime/runtime/lint-baseline.xml b/compose/runtime/runtime/lint-baseline.xml
index 2fce8f0..f3284e9 100644
--- a/compose/runtime/runtime/lint-baseline.xml
+++ b/compose/runtime/runtime/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="BanSuppressTag"
@@ -66,24 +66,6 @@
 
     <issue
         id="PrimitiveInCollection"
-        message="field groupInfos with type HashMap&lt;Integer, GroupInfo>: replace with IntObjectMap"
-        errorLine1="    private val groupInfos = run {"
-        errorLine2="    ^">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/runtime/Composer.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="variable result with type HashMap&lt;Integer, GroupInfo>: replace with IntObjectMap"
-        errorLine1="        val result = hashMapOf&lt;Int, GroupInfo>()"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/runtime/Composer.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
         message="field intParams with type List&lt;IntParameter>: replace with IntList"
         errorLine1="        val intParams = List(ints) { index -> IntParameter(index) }"
         errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composition.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composition.kt
index c1f4750..371faae 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composition.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composition.kt
@@ -21,7 +21,6 @@
 import androidx.collection.MutableScatterSet
 import androidx.collection.mutableScatterSetOf
 import androidx.compose.runtime.changelist.ChangeList
-import androidx.compose.runtime.collection.IdentityArraySet
 import androidx.compose.runtime.collection.ScopeMap
 import androidx.compose.runtime.collection.fastForEach
 import androidx.compose.runtime.snapshots.ReaderKind
@@ -826,13 +825,7 @@
     }
 
     override fun observesAnyOf(values: Set<Any>): Boolean {
-        if (values is IdentityArraySet<Any>) {
-            values.fastForEach { value ->
-                if (value in observations || value in derivedStates) return true
-            }
-            return false
-        }
-        for (value in values) {
+        values.fastForEach { value ->
             if (value in observations || value in derivedStates) return true
         }
         return false
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt
index 8ddff07..6a41089 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt
@@ -16,10 +16,11 @@
 
 package androidx.compose.runtime
 
+import androidx.collection.MutableScatterSet
 import androidx.collection.mutableScatterSetOf
-import androidx.compose.runtime.collection.IdentityArraySet
 import androidx.compose.runtime.collection.fastForEach
 import androidx.compose.runtime.collection.mutableVectorOf
+import androidx.compose.runtime.collection.wrapIntoSet
 import androidx.compose.runtime.external.kotlinx.collections.immutable.persistentSetOf
 import androidx.compose.runtime.snapshots.MutableSnapshot
 import androidx.compose.runtime.snapshots.ReaderKind
@@ -211,7 +212,7 @@
         _knownCompositionsCache = newCache
         newCache
     }
-    private var snapshotInvalidations = IdentityArraySet<Any>()
+    private var snapshotInvalidations = MutableScatterSet<Any>()
     private val compositionInvalidations = mutableVectorOf<ControlledComposition>()
     private val compositionsAwaitingApply = mutableListOf<ControlledComposition>()
     private val compositionValuesAwaitingInsert = mutableListOf<MovableContentStateReference>()
@@ -299,7 +300,7 @@
     private fun deriveStateLocked(): CancellableContinuation<Unit>? {
         if (_state.value <= State.ShuttingDown) {
             clearKnownCompositionsLocked()
-            snapshotInvalidations = IdentityArraySet()
+            snapshotInvalidations = MutableScatterSet()
             compositionInvalidations.clear()
             compositionsAwaitingApply.clear()
             compositionValuesAwaitingInsert.clear()
@@ -315,7 +316,7 @@
                 State.Inactive
             }
             runnerJob == null -> {
-                snapshotInvalidations = IdentityArraySet()
+                snapshotInvalidations = MutableScatterSet()
                 compositionInvalidations.clear()
                 if (hasBroadcastFrameClockAwaitersLocked) State.InactivePendingWork
                 else State.Inactive
@@ -437,7 +438,8 @@
     private fun recordComposerModifications(): Boolean {
         val changes = synchronized(stateLock) {
             if (snapshotInvalidations.isEmpty()) return hasFrameWorkLocked
-            snapshotInvalidations.also { snapshotInvalidations = IdentityArraySet() }
+            snapshotInvalidations.wrapIntoSet()
+                .also { snapshotInvalidations = MutableScatterSet() }
         }
         val compositions = synchronized(stateLock) {
             knownCompositions
@@ -453,7 +455,7 @@
                     if (_state.value <= State.ShuttingDown) return@run
                 }
             }
-            snapshotInvalidations = IdentityArraySet()
+            snapshotInvalidations = MutableScatterSet()
             complete = true
         } finally {
             if (!complete) {
@@ -476,12 +478,12 @@
     private inline fun recordComposerModifications(
         onEachInvalidComposition: (ControlledComposition) -> Unit
     ) {
-        val changes = snapshotInvalidations
+        val changes = snapshotInvalidations.wrapIntoSet()
         if (changes.isNotEmpty()) {
             knownCompositions.fastForEach { composition ->
                 composition.recordModificationsOf(changes)
             }
-            snapshotInvalidations = IdentityArraySet()
+            snapshotInvalidations = MutableScatterSet()
         }
         compositionInvalidations.forEach(onEachInvalidComposition)
         compositionInvalidations.clear()
@@ -517,7 +519,8 @@
         val toApply = mutableListOf<ControlledComposition>()
         val toLateApply = mutableScatterSetOf<ControlledComposition>()
         val toComplete = mutableScatterSetOf<ControlledComposition>()
-        val modifiedValues = IdentityArraySet<Any>()
+        val modifiedValues = MutableScatterSet<Any>()
+        val modifiedValuesSet = modifiedValues.wrapIntoSet()
         val alreadyComposed = mutableScatterSetOf<ControlledComposition>()
 
         fun clearRecompositionState() {
@@ -623,7 +626,7 @@
                                 knownCompositions.fastForEach { value ->
                                     if (
                                         value !in alreadyComposed &&
-                                        value.observesAnyOf(modifiedValues)
+                                        value.observesAnyOf(modifiedValuesSet)
                                     ) {
                                         toRecompose += value
                                     }
@@ -741,7 +744,7 @@
 
                 compositionsAwaitingApply.clear()
                 compositionInvalidations.clear()
-                snapshotInvalidations = IdentityArraySet()
+                snapshotInvalidations = MutableScatterSet()
 
                 compositionValuesAwaitingInsert.clear()
                 compositionValuesRemoved.clear()
@@ -941,7 +944,7 @@
                     }
 
                     // Perform recomposition for any invalidated composers
-                    val modifiedValues = IdentityArraySet<Any>()
+                    val modifiedValues = MutableScatterSet<Any>()
                     try {
                         toRecompose.fastForEach { composer ->
                             performRecompose(composer, modifiedValues)?.let {
@@ -1175,7 +1178,7 @@
 
     private fun performRecompose(
         composition: ControlledComposition,
-        modifiedValues: IdentityArraySet<Any>?
+        modifiedValues: MutableScatterSet<Any>?
     ): ControlledComposition? {
         if (composition.isComposing ||
             composition.isDisposed ||
@@ -1187,7 +1190,7 @@
                     // Record write performed by a previous composition as if they happened during
                     // composition.
                     composition.prepareCompose {
-                        modifiedValues.fastForEach { composition.recordWriteOf(it) }
+                        modifiedValues.forEach { composition.recordWriteOf(it) }
                     }
                 }
                 composition.recompose()
@@ -1197,7 +1200,7 @@
 
     private fun performInsertValues(
         references: List<MovableContentStateReference>,
-        modifiedValues: IdentityArraySet<Any>?
+        modifiedValues: MutableScatterSet<Any>?
     ): List<ControlledComposition> {
         val tasks = references.fastGroupBy { it.composition }
         for ((composition, refs) in tasks) {
@@ -1242,7 +1245,7 @@
 
     private fun writeObserverOf(
         composition: ControlledComposition,
-        modifiedValues: IdentityArraySet<Any>?
+        modifiedValues: MutableScatterSet<Any>?
     ): (Any) -> Unit {
         return { value ->
             composition.recordWriteOf(value)
@@ -1252,7 +1255,7 @@
 
     private inline fun <T> composing(
         composition: ControlledComposition,
-        modifiedValues: IdentityArraySet<Any>?,
+        modifiedValues: MutableScatterSet<Any>?,
         block: () -> T
     ): T {
         val snapshot = Snapshot.takeMutableSnapshot(
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SlotTable.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SlotTable.kt
index 16cef80..ab0082f 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SlotTable.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SlotTable.kt
@@ -364,6 +364,14 @@
                         val nearestScope = findEffectiveRecomposeScope(reader.currentGroup)
                         if (nearestScope != null) {
                             scopes.add(nearestScope)
+                            if (nearestScope.anchor?.location == reader.currentGroup) {
+                                // For the group that contains the restart group then, in some
+                                // cases, such as when the parameter names of a function change,
+                                // the restart lambda can be invalid if it is called. To avoid this
+                                // the scope parent scope needs to be invalidated too.
+                                val parentScope = findEffectiveRecomposeScope(reader.parent)
+                                parentScope?.let { scopes.add(it) }
+                            }
                         } else {
                             allScopesFound = false
                             scopes.clear()
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityArraySet.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityArraySet.kt
deleted file mode 100644
index 415a611..0000000
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityArraySet.kt
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Copyright 2020 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.runtime.collection
-
-import androidx.compose.runtime.identityHashCode
-import kotlin.contracts.ExperimentalContracts
-import kotlin.contracts.contract
-
-/**
- * A set of values using an array as the backing store, ordered using [identityHashCode] for
- * both sorting and uniqueness.
- */
-@OptIn(ExperimentalContracts::class)
-internal class IdentityArraySet<T : Any> : Set<T> {
-    override var size = 0
-        private set
-
-    var values: Array<Any?> = arrayOfNulls(16)
-        private set
-
-    /**
-     * Returns true if the set contains [element]
-     */
-    override operator fun contains(element: T) = find(element) >= 0
-
-    /**
-     * Return the item at the given [index].
-     */
-    operator fun get(index: Int): T {
-        checkIndexBounds(index)
-
-        @Suppress("UNCHECKED_CAST")
-        return values[index] as T
-    }
-
-    /**
-     * Add [value] to the set and return `true` if it was added or `false` if it already existed.
-     */
-    fun add(value: T): Boolean {
-        val index: Int
-        val size = size
-        val values = values
-
-        if (size > 0) {
-            index = find(value)
-
-            if (index >= 0) {
-                return false
-            }
-        } else {
-            index = -1
-        }
-
-        val insertIndex = -(index + 1)
-
-        if (size == values.size) {
-            val newSorted = arrayOfNulls<Any>(values.size * 2)
-            values.copyInto(
-                destination = newSorted,
-                destinationOffset = insertIndex + 1,
-                startIndex = insertIndex,
-                endIndex = size
-            )
-            values.copyInto(
-                destination = newSorted,
-                endIndex = insertIndex
-            )
-            this.values = newSorted
-        } else {
-            values.copyInto(
-                destination = values,
-                destinationOffset = insertIndex + 1,
-                startIndex = insertIndex,
-                endIndex = size
-            )
-        }
-        this.values[insertIndex] = value
-        this.size++
-        return true
-    }
-
-    /**
-     * Remove all values from the set.
-     */
-    fun clear() {
-        values.fill(null)
-        size = 0
-    }
-
-    /**
-     * Call [block] for all items in the set.
-     */
-    inline fun fastForEach(block: (T) -> Unit) {
-        contract { callsInPlace(block) }
-        val values = values
-        for (i in 0 until size) {
-            @Suppress("UNCHECKED_CAST")
-            block(values[i] as T)
-        }
-    }
-
-    inline fun fastAny(block: (T) -> Boolean): Boolean {
-        contract { callsInPlace(block) }
-        val size = size
-        if (size == 0) return false
-        val values = values
-        for (i in 0 until size) {
-            @Suppress("UNCHECKED_CAST")
-            if (block(values[i] as T)) return true
-        }
-        return false
-    }
-
-    fun addAll(collection: Collection<T>) {
-        if (collection.isEmpty()) return
-
-        if (collection !is IdentityArraySet<T>) {
-            // Unknown collection, just add repeatedly
-            for (value in collection) {
-                add(value)
-            }
-        } else {
-            // Identity set, merge sorted arrays
-            val thisValues = values
-            val otherValues = collection.values
-            val thisSize = size
-            val otherSize = collection.size
-            val combinedSize = thisSize + otherSize
-
-            val needsResize = values.size < combinedSize
-            val elementsInOrder = thisSize == 0 ||
-                identityHashCode(thisValues[thisSize - 1]) < identityHashCode(otherValues[0])
-
-            if (!needsResize && elementsInOrder) {
-                // fast path, just copy target values
-                otherValues.copyInto(
-                    destination = thisValues,
-                    destinationOffset = thisSize,
-                    startIndex = 0,
-                    endIndex = otherSize
-                )
-                size += otherSize
-            } else {
-                // slow path, merge this and other values
-                val newArray = if (needsResize) {
-                    arrayOfNulls(if (thisSize > otherSize) thisSize * 2 else otherSize * 2)
-                } else {
-                    thisValues
-                }
-                var thisIndex = thisSize - 1
-                var otherIndex = otherSize - 1
-                var nextInsertIndex = combinedSize - 1
-                while (thisIndex >= 0 || otherIndex >= 0) {
-                    val nextValue = when {
-                        thisIndex < 0 -> otherValues[otherIndex--]
-                        otherIndex < 0 -> thisValues[thisIndex--]
-                        else -> {
-                            val thisValue = thisValues[thisIndex]
-                            val otherValue = otherValues[otherIndex]
-
-                            val thisHash = identityHashCode(thisValue)
-                            val otherHash = identityHashCode(otherValue)
-                            when {
-                                thisHash > otherHash -> {
-                                    thisIndex--
-                                    thisValue
-                                }
-                                thisHash < otherHash -> {
-                                    otherIndex--
-                                    otherValue
-                                }
-                                thisValue === otherValue -> {
-                                    // hash and the value are the same, advance both pointers
-                                    thisIndex--
-                                    otherIndex--
-                                    thisValue
-                                }
-                                else -> {
-                                    // collision, lookup if the same item is in the array
-                                    var i = thisIndex - 1
-                                    var foundDuplicate = false
-                                    while (i >= 0) {
-                                        val value = thisValues[i--]
-                                        if (identityHashCode(value) != otherHash) break
-                                        if (otherValue === value) {
-                                            foundDuplicate = true
-                                            break
-                                        }
-                                    }
-
-                                    if (foundDuplicate) {
-                                        // advance pointer and continue next iteration of outer
-                                        // merge loop.
-                                        otherIndex--
-                                        continue
-                                    } else {
-                                        // didn't find the duplicate, put other item in array.
-                                        otherIndex--
-                                        otherValue
-                                    }
-                                }
-                            }
-                        }
-                    }
-
-                    // insert value and continue
-                    newArray[nextInsertIndex--] = nextValue
-                }
-
-                if (nextInsertIndex >= 0) {
-                    // some values were duplicated, copy the merged part
-                    newArray.copyInto(
-                        newArray,
-                        destinationOffset = 0,
-                        startIndex = nextInsertIndex + 1,
-                        endIndex = combinedSize
-                    )
-                }
-                // newSize = endOffset - startOffset of copy above
-                val newSize = combinedSize - (nextInsertIndex + 1)
-                newArray.fill(null, fromIndex = newSize, toIndex = combinedSize)
-
-                values = newArray
-                size = newSize
-            }
-        }
-    }
-
-    /**
-     * Return true if the set is empty.
-     */
-    override fun isEmpty() = size == 0
-
-    /**
-     * Returns true if the set is not empty.
-     */
-    fun isNotEmpty() = size > 0
-
-    /**
-     * Remove [value] from the set.
-     */
-    fun remove(value: T): Boolean {
-        val index = find(value)
-        val values = values
-        val size = size
-
-        if (index >= 0) {
-            if (index < size - 1) {
-                values.copyInto(
-                    destination = values,
-                    destinationOffset = index,
-                    startIndex = index + 1,
-                    endIndex = size
-                )
-            }
-            values[size - 1] = null
-            this.size--
-            return true
-        }
-        return false
-    }
-
-    /**
-     * Removes all values that match [predicate].
-     */
-    inline fun removeValueIf(predicate: (T) -> Boolean) {
-        val values = values
-        val size = size
-
-        var destinationIndex = 0
-        for (i in 0 until size) {
-            @Suppress("UNCHECKED_CAST")
-            val item = values[i] as T
-            if (!predicate(item)) {
-                if (destinationIndex != i) {
-                    values[destinationIndex] = item
-                }
-                destinationIndex++
-            }
-        }
-        for (i in destinationIndex until size) {
-            values[i] = null
-        }
-        this.size = destinationIndex
-    }
-
-    /**
-     * Returns the index of [value] in the set or the negative index - 1 of the location where
-     * it would have been if it had been in the set.
-     */
-    private fun find(value: Any?): Int {
-        var low = 0
-        var high = size - 1
-        val valueIdentity = identityHashCode(value)
-        val values = values
-
-        while (low <= high) {
-            val mid = (low + high).ushr(1)
-            val midVal = values[mid]
-            val midIdentity = identityHashCode(midVal)
-            when {
-                midIdentity < valueIdentity -> low = mid + 1
-                midIdentity > valueIdentity -> high = mid - 1
-                midVal === value -> return mid
-                else -> return findExactIndex(mid, value, valueIdentity)
-            }
-        }
-        return -(low + 1)
-    }
-
-    /**
-     * When multiple items share the same [identityHashCode], then we must find the specific
-     * index of the target item. This method assumes that [midIndex] has already been checked
-     * for an exact match for [value], but will look at nearby values to find the exact item index.
-     * If no match is found, the negative index - 1 of the position in which it would be will
-     * be returned, which is always after the last item with the same [identityHashCode].
-     */
-    private fun findExactIndex(
-        midIndex: Int,
-        value: Any?,
-        valueHash: Int
-    ): Int {
-        val values = values
-        val size = size
-
-        // hunt down first
-        for (i in midIndex - 1 downTo 0) {
-            val v = values[i]
-            if (v === value) {
-                return i
-            }
-            if (identityHashCode(v) != valueHash) {
-                break // we've gone too far
-            }
-        }
-
-        for (i in midIndex + 1 until size) {
-            val v = values[i]
-            if (v === value) {
-                return i
-            }
-            if (identityHashCode(v) != valueHash) {
-                // We've gone too far. We should insert here.
-                return -(i + 1)
-            }
-        }
-
-        // We should insert at the end
-        return -(size + 1)
-    }
-
-    /**
-     * Verifies if index is in bounds
-     */
-    private fun checkIndexBounds(index: Int) {
-        if (index !in 0 until size) {
-            throw IndexOutOfBoundsException("Index $index, size $size")
-        }
-    }
-
-    /**
-     * Return true if all elements of [elements] are in the set.
-     */
-    override fun containsAll(elements: Collection<T>) = elements.all { contains(it) }
-
-    /**
-     * Return an iterator for the set.
-     */
-    @Suppress("UNCHECKED_CAST")
-    override fun iterator(): Iterator<T> = object : Iterator<T> {
-        var index = 0
-        override fun hasNext(): Boolean = index < size
-        override fun next(): T = this@IdentityArraySet.values[index++] as T
-    }
-
-    override fun toString(): String {
-        return joinToString(prefix = "[", postfix = "]") { it.toString() }
-    }
-}
-
-internal inline fun <T : Any> Set<T>.fastForEach(block: (T) -> Unit) {
-    if (this is IdentityArraySet<T>) {
-        fastForEach(block)
-    } else {
-        forEach(block)
-    }
-}
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/ScatterSetWrapper.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/ScatterSetWrapper.kt
new file mode 100644
index 0000000..5854635
--- /dev/null
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/ScatterSetWrapper.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime.collection
+
+import androidx.collection.ScatterSet
+
+/**
+ * A wrapper for [ScatterSet] that implements [Set] APIs. This wrapper allows to use [ScatterSet]
+ * through external APIs and unwrap it back into [Set] for faster iteration / other operations.
+ */
+internal class ScatterSetWrapper<T>(
+    internal val set: ScatterSet<T>
+) : Set<T> {
+    override val size: Int
+        get() = set.size
+
+    override fun isEmpty(): Boolean = set.isEmpty()
+    override fun iterator(): Iterator<T> = iterator {
+        set.forEach {
+            yield(it)
+        }
+    }
+
+    override fun containsAll(elements: Collection<T>): Boolean =
+        elements.all { set.contains(it) }
+
+    override fun contains(element: T): Boolean =
+        set.contains(element)
+}
+
+internal fun <T> ScatterSet<T>.wrapIntoSet(): Set<T> = ScatterSetWrapper(this)
+
+internal inline fun <T : Any> Set<T>.fastForEach(block: (T) -> Unit) =
+    when (this) {
+        is ScatterSetWrapper<T> -> {
+            set.forEach(block)
+        }
+        else -> {
+            forEach(block)
+        }
+    }
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
index d08defb..23e538b 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/Snapshot.kt
@@ -16,6 +16,8 @@
 
 package androidx.compose.runtime.snapshots
 
+import androidx.collection.MutableScatterSet
+import androidx.collection.mutableScatterSetOf
 import androidx.compose.runtime.AtomicInt
 import androidx.compose.runtime.AtomicReference
 import androidx.compose.runtime.Composable
@@ -24,7 +26,7 @@
 import androidx.compose.runtime.InternalComposeApi
 import androidx.compose.runtime.SnapshotThreadLocal
 import androidx.compose.runtime.checkPrecondition
-import androidx.compose.runtime.collection.IdentityArraySet
+import androidx.compose.runtime.collection.wrapIntoSet
 import androidx.compose.runtime.currentThreadId
 import androidx.compose.runtime.internal.JvmDefaultWithCompatibility
 import androidx.compose.runtime.requirePrecondition
@@ -227,7 +229,7 @@
     /**
      * The set of state objects that have been modified in this snapshot.
      */
-    internal abstract val modified: IdentityArraySet<StateObject>?
+    internal abstract val modified: MutableScatterSet<StateObject>?
 
     /**
      * Notify the snapshot that all objects created in this snapshot to this point should be
@@ -816,7 +818,7 @@
         ) else null
 
         var observers = emptyList<(Set<Any>, Snapshot) -> Unit>()
-        var globalModified: IdentityArraySet<StateObject>? = null
+        var globalModified: MutableScatterSet<StateObject>? = null
         sync {
             validateOpen(this)
             if (modified == null || modified.size == 0) {
@@ -824,7 +826,7 @@
                 val previousGlobalSnapshot = currentGlobalSnapshot.get()
                 takeNewGlobalSnapshot(previousGlobalSnapshot, emptyLambda)
                 val previousModified = previousGlobalSnapshot.modified
-                if (!previousModified.isNullOrEmpty()) {
+                if (previousModified != null && previousModified.isNotEmpty()) {
                     observers = applyObservers
                     globalModified = previousModified
                 }
@@ -854,16 +856,19 @@
         applied = true
 
         // Notify any apply observers that changes applied were seen
-        if (!globalModified.isNullOrEmpty()) {
-            val nonNullGlobalModified = globalModified!!
-            observers.fastForEach {
-                it(nonNullGlobalModified, this)
+        if (globalModified != null) {
+            val nonNullGlobalModified = globalModified!!.wrapIntoSet()
+            if (nonNullGlobalModified.isNotEmpty()) {
+                observers.fastForEach {
+                    it(nonNullGlobalModified, this)
+                }
             }
         }
 
-        if (!modified.isNullOrEmpty()) {
+        if (modified != null && modified.isNotEmpty()) {
+            val modifiedSet = modified.wrapIntoSet()
             observers.fastForEach {
-                it(modified, this)
+                it(modifiedSet, this)
             }
         }
 
@@ -873,8 +878,8 @@
         sync {
             releasePinnedSnapshotsForCloseLocked()
             checkAndOverwriteUnusedRecordsLocked()
-            globalModified?.fastForEach { processForUnusedRecordsLocked(it) }
-            modified?.fastForEach { processForUnusedRecordsLocked(it) }
+            globalModified?.forEach { processForUnusedRecordsLocked(it) }
+            modified?.forEach { processForUnusedRecordsLocked(it) }
             merged?.fastForEach { processForUnusedRecordsLocked(it) }
             merged = null
         }
@@ -962,7 +967,7 @@
             // id to be forgotten as no state records will refer to it.
             this.modified = null
             val id = id
-            modified.fastForEach { state ->
+            modified.forEach { state ->
                 var current: StateRecord? = state.firstStateRecord
                 while (current != null) {
                     if (current.snapshotId == id || current.snapshotId in previousIds) {
@@ -997,12 +1002,12 @@
         val start = this.invalid.set(id).or(this.previousIds)
         val modified = modified!!
         var statesToRemove: MutableList<StateObject>? = null
-        modified.fastForEach { state ->
+        modified.forEach { state ->
             val first = state.firstStateRecord
             // If either current or previous cannot be calculated the object was created
             // in a nested snapshot that was committed then changed.
-            val current = readable(first, snapshotId, invalidSnapshots) ?: return@fastForEach
-            val previous = readable(first, id, start) ?: return@fastForEach
+            val current = readable(first, snapshotId, invalidSnapshots) ?: return@forEach
+            val previous = readable(first, id, start) ?: return@forEach
             if (current != previous) {
                 val applied = readable(first, id, this.invalid) ?: readError()
                 val merged = optimisticMerges?.get(current) ?: run {
@@ -1117,12 +1122,12 @@
     }
 
     override fun recordModified(state: StateObject) {
-        (modified ?: IdentityArraySet<StateObject>().also { modified = it }).add(state)
+        (modified ?: mutableScatterSetOf<StateObject>().also { modified = it }).add(state)
     }
 
     override var writeCount: Int = 0
 
-    override var modified: IdentityArraySet<StateObject>? = null
+    override var modified: MutableScatterSet<StateObject>? = null
 
     internal var merged: List<StateObject>? = null
 
@@ -1324,7 +1329,7 @@
     override fun hasPendingChanges(): Boolean = false
     override val writeObserver: ((Any) -> Unit)? get() = null
 
-    override var modified: IdentityArraySet<StateObject>?
+    override var modified: MutableScatterSet<StateObject>?
         get() = null
         @Suppress("UNUSED_PARAMETER")
         set(value) = unsupported()
@@ -1395,7 +1400,7 @@
         }
     }
 
-    override val modified: IdentityArraySet<StateObject>? get() = null
+    override val modified: MutableScatterSet<StateObject>? get() = null
     override val writeObserver: ((Any) -> Unit)? get() = null
     override fun recordModified(state: StateObject) = reportReadonlySnapshotWrite()
 
@@ -1594,7 +1599,7 @@
 
     override fun hasPendingChanges(): Boolean = currentSnapshot.hasPendingChanges()
 
-    override var modified: IdentityArraySet<StateObject>?
+    override var modified: MutableScatterSet<StateObject>?
         get() = currentSnapshot.modified
         @Suppress("UNUSED_PARAMETER")
         set(value) = unsupported()
@@ -1706,7 +1711,7 @@
 
     override fun hasPendingChanges(): Boolean = currentSnapshot.hasPendingChanges()
 
-    override var modified: IdentityArraySet<StateObject>?
+    override var modified: MutableScatterSet<StateObject>?
         get() = currentSnapshot.modified
         @Suppress("UNUSED_PARAMETER")
         set(value) = unsupported()
@@ -1895,7 +1900,7 @@
 private fun <T> advanceGlobalSnapshot(block: (invalid: SnapshotIdSet) -> T): T {
     var previousGlobalSnapshot = snapshotInitializer as GlobalSnapshot
 
-    var modified: IdentityArraySet<StateObject>? = null // Effectively val; can be with contracts
+    var modified: MutableScatterSet<StateObject>? = null // Effectively val; can be with contracts
     val result = sync {
         previousGlobalSnapshot = currentGlobalSnapshot.get()
         modified = previousGlobalSnapshot.modified
@@ -1911,7 +1916,7 @@
         try {
             val observers = applyObservers
             observers.fastForEach { observer ->
-                observer(it, previousGlobalSnapshot)
+                observer(it.wrapIntoSet(), previousGlobalSnapshot)
             }
         } finally {
             pendingApplyObserverCount.add(-1)
@@ -1920,7 +1925,7 @@
 
     sync {
         checkAndOverwriteUnusedRecordsLocked()
-        modified?.fastForEach { processForUnusedRecordsLocked(it) }
+        modified?.forEach { processForUnusedRecordsLocked(it) }
     }
 
     return result
@@ -2324,10 +2329,10 @@
     if (modified == null) return null
     val start = applyingSnapshot.invalid.set(applyingSnapshot.id).or(applyingSnapshot.previousIds)
     var result: MutableMap<StateRecord, StateRecord>? = null
-    modified.fastForEach { state ->
+    modified.forEach { state ->
         val first = state.firstStateRecord
-        val current = readable(first, id, invalidSnapshots) ?: return@fastForEach
-        val previous = readable(first, id, start) ?: return@fastForEach
+        val current = readable(first, id, invalidSnapshots) ?: return@forEach
+        val previous = readable(first, id, start) ?: return@forEach
         if (current != previous) {
             // Try to produce a merged state record
             val applied = readable(first, applyingSnapshot.id, applyingSnapshot.invalid)
diff --git a/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/collection/IdentityArraySetTest.kt b/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/collection/IdentityArraySetTest.kt
deleted file mode 100644
index f9e614a..0000000
--- a/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/collection/IdentityArraySetTest.kt
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright 2020 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.runtime.collection
-
-import androidx.compose.runtime.identityHashCode
-import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.test.assertFailsWith
-import kotlin.test.assertFalse
-import kotlin.test.assertNotEquals
-import kotlin.test.assertNotNull
-import kotlin.test.assertNotSame
-import kotlin.test.assertNull
-import kotlin.test.assertTrue
-
-class IdentityArraySetTest {
-    private val set: IdentityArraySet<Stuff> = IdentityArraySet()
-
-    private val list = listOf(Stuff(10), Stuff(12), Stuff(1), Stuff(30), Stuff(10))
-
-    @Test
-    fun emptyConstruction() {
-        val s = IdentityArraySet<Stuff>()
-        assertEquals(0, s.size)
-    }
-
-    @Test
-    fun get_indexWithinBounds_shouldNotThrow() {
-        list.forEach { set.add(it) }
-
-        assertNotNull(set.get(0))
-    }
-
-    @Test
-    fun get_indexOutOfBounds_shouldThrow() {
-        list.forEach { set.add(it) }
-
-        // Index less than 0
-        assertFailsWith<IndexOutOfBoundsException> {
-            set.get(-1)
-        }
-
-        // Index greater than size
-        assertFailsWith<IndexOutOfBoundsException> {
-            set.get(list.size + 1)
-        }
-    }
-
-    @Test
-    fun addValueForward() {
-        list.forEach { set.add(it) }
-        assertEquals(list.size, set.size)
-        var previousItem = set[0]
-        for (i in 1 until set.size) {
-            val item = set[i]
-            assertTrue(identityHashCode(previousItem) < identityHashCode(item))
-            previousItem = item
-        }
-    }
-
-    @Test
-    fun addValueReversed() {
-        list.asReversed().forEach { set.add(it) }
-        assertEquals(list.size, set.size)
-        var previousItem = set[0]
-        for (i in 1 until set.size) {
-            val item = set[i]
-            assertTrue(identityHashCode(previousItem) < identityHashCode(item))
-            previousItem = item
-        }
-    }
-
-    @Test
-    fun addExistingValue() {
-        list.forEach { set.add(it) }
-        list.asReversed().forEach { set.add(it) }
-
-        assertEquals(list.size, set.size)
-        var previousItem = set[0]
-        for (i in 1 until set.size) {
-            val item = set[i]
-            assertTrue(identityHashCode(previousItem) < identityHashCode(item))
-            previousItem = item
-        }
-    }
-
-    @Test
-    fun clear() {
-        list.forEach { set.add(it) }
-        set.clear()
-
-        assertEquals(0, set.size)
-        set.values.forEach {
-            assertNull(it)
-        }
-    }
-
-    @Test
-    fun remove() {
-        list.forEach { set.add(it) }
-
-        // remove a value that doesn't exist:
-        val removed = set.remove(Stuff(10))
-        assertEquals(list.size, set.size)
-        assertFalse(removed)
-
-        // remove a value in the middle:
-        testRemoveValueAtIndex(set.size / 2)
-
-        // remove the last value
-        testRemoveValueAtIndex(set.size - 1)
-
-        // remove a first value
-        testRemoveValueAtIndex(0)
-    }
-
-    @Test
-    fun removeValueIf() {
-        list.forEach { set.add(it) }
-
-        set.removeValueIf { it.item == 10 }
-
-        // Make sure we've removed both items
-        assertEquals(list.size - 2, set.size)
-        set.fastForEach { assertNotEquals(10, it.item) }
-        assertNull(set.values[set.size])
-        assertNull(set.values[set.size + 1])
-    }
-
-    @Test
-    fun growSet() {
-        val verifierSet = mutableSetOf<Stuff>()
-        repeat(100) {
-            val stuff = Stuff(it)
-            set.add(stuff)
-            verifierSet.add(stuff)
-        }
-        assertEquals(100, set.size)
-        set.fastForEach { verifierSet.remove(it) }
-        assertEquals(0, verifierSet.size)
-    }
-
-    @Test
-    fun canUseAsSetOfT() {
-        val stuff = Array(100) { Stuff(it) }
-        for (i in 0 until 100 step 2) {
-            set.add(stuff[i])
-        }
-        val setOfT: Set<Stuff> = set
-        for (i in 0 until 100) {
-            val expected = i % 2 == 0
-            if (expected) {
-                assertTrue(stuff[i] in set)
-                assertTrue(stuff[i] in setOfT)
-            } else {
-                assertFalse(stuff[i] in set)
-                assertFalse(stuff[i] in setOfT)
-            }
-        }
-        for (element in setOfT) {
-            assertTrue(element.item % 2 == 0)
-            assertEquals(element, stuff[element.item])
-        }
-
-        set.add(stuff[1])
-        assertTrue(stuff[1] in setOfT)
-
-        assertTrue(setOfT.containsAll(listOf(stuff[0], stuff[1], stuff[2])))
-    }
-
-    @Test
-    fun addAll_Collection() {
-        set.addAll(list)
-
-        assertEquals(list.size, set.size)
-        for (value in list) {
-            assertTrue(value in set)
-        }
-    }
-
-    @Test
-    fun addAll_IdentityArraySet() {
-        val anotherSet = IdentityArraySet<Stuff>()
-        anotherSet.addAll(list)
-
-        set.addAll(anotherSet)
-
-        for (value in list) {
-            assertTrue(value in set)
-        }
-
-        set.addAll(anotherSet)
-
-        assertEquals(anotherSet.size, set.size)
-        for (value in list) {
-            assertTrue(value in set)
-        }
-
-        val stuff = Array(100) { Stuff(it) }
-        for (i in 0 until 100 step 2) {
-            anotherSet.add(stuff[i])
-        }
-        set.addAll(anotherSet)
-
-        for (i in stuff.indices) {
-            val value = stuff[i]
-            if (i % 2 == 0) {
-                assertTrue(value in set, "Expected to have element $i in $set")
-            } else {
-                assertFalse(value in set, "Didn't expect to have element $i in $set")
-            }
-        }
-
-        for (value in list) {
-            assertTrue(value in set)
-        }
-    }
-
-    private fun testRemoveValueAtIndex(index: Int) {
-        val value = set[index]
-        val initialSize = set.size
-        val removed = set.remove(value)
-        assertEquals(initialSize - 1, set.size)
-        assertTrue(removed)
-        assertNull(set.values[set.size])
-        set.fastForEach { assertNotSame(value, it) }
-    }
-
-    data class Stuff(val item: Int)
-}
diff --git a/compose/ui/ui-geometry/build.gradle b/compose/ui/ui-geometry/build.gradle
index 1d9fa6a..1d45f14 100644
--- a/compose/ui/ui-geometry/build.gradle
+++ b/compose/ui/ui-geometry/build.gradle
@@ -41,8 +41,7 @@
         commonMain {
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
-
-                implementation("androidx.compose.runtime:runtime:1.2.1")
+                implementation("androidx.compose.runtime:runtime:1.6.0")
                 implementation(project(":compose:ui:ui-util"))
             }
         }
@@ -70,7 +69,6 @@
         desktopMain {
             dependsOn(jvmMain)
             dependencies {
-                implementation(project(":compose:runtime:runtime"))
             }
         }
 
diff --git a/compose/ui/ui-graphics/build.gradle b/compose/ui/ui-graphics/build.gradle
index 3f9cc28..a28e275 100644
--- a/compose/ui/ui-graphics/build.gradle
+++ b/compose/ui/ui-graphics/build.gradle
@@ -43,7 +43,7 @@
                 api(libs.androidx.annotation)
 
                 api(project(":compose:ui:ui-unit"))
-                implementation(project(":compose:runtime:runtime"))
+                implementation("androidx.compose.runtime:runtime:1.6.0")
                 implementation(project(":compose:ui:ui-util"))
                 implementation("androidx.collection:collection:1.4.0")
             }
@@ -59,7 +59,6 @@
             dependsOn(commonMain)
             dependencies {
                 api(libs.skikoCommon)
-                implementation(project(":compose:runtime:runtime"))
             }
         }
 
@@ -73,7 +72,6 @@
             dependsOn(jvmMain)
             dependencies {
                 implementation("androidx.graphics:graphics-path:1.0.0-beta02")
-                api(libs.androidx.annotation)
                 api("androidx.annotation:annotation-experimental:1.4.0")
             }
         }
diff --git a/compose/ui/ui-inspection/lint-baseline.xml b/compose/ui/ui-inspection/lint-baseline.xml
index a1c812d..ae2ee17 100644
--- a/compose/ui/ui-inspection/lint-baseline.xml
+++ b/compose/ui/ui-inspection/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="PrimitiveInCollection"
@@ -19,211 +19,4 @@
             file="src/main/java/androidx/compose/ui/inspection/util/AnchorMap.kt"/>
     </issue>
 
-    <issue
-        id="PrimitiveInCollection"
-        message="field viewsToSkip with type List&lt;Long>: replace with LongList"
-        errorLine1="    val viewsToSkip: List&lt;Long> ="
-        errorLine2="                     ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/compose/AndroidComposeViewWrapper.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="return type List&lt;Long> of getViewsToSkip: replace with LongList"
-        errorLine1="    val viewsToSkip: List&lt;Long> ="
-        errorLine2="                     ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/compose/AndroidComposeViewWrapper.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="return type Map&lt;Long, InspectorNode> of getLookup: replace with LongObjectMap"
-        errorLine1="        val lookup: Map&lt;Long, InspectorNode>"
-        errorLine2="            ~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="variable var785951a with type Map&lt;Long, ? extends InspectorNode>: replace with LongObjectMap"
-        errorLine1="            get() = _lookup ?: trees.flatMap { it.nodes }"
-        errorLine2="                    ^">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="field _lookup with type Map&lt;Long, InspectorNode>: replace with LongObjectMap"
-        errorLine1="        private var _lookup: Map&lt;Long, InspectorNode>? = null"
-        errorLine2="                             ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="constructor CacheTree has parameter viewsToSkip with type List&lt;Long>: replace with LongList"
-        errorLine1="        val viewsToSkip: List&lt;Long>"
-        errorLine2="                         ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="field viewsToSkip with type List&lt;Long>: replace with LongList"
-        errorLine1="        val viewsToSkip: List&lt;Long>"
-        errorLine2="                         ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="return type List&lt;Long> of getViewsToSkip: replace with LongList"
-        errorLine1="        val viewsToSkip: List&lt;Long>"
-        errorLine2="                         ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="field _cachedNodes with type Map&lt;Long, CacheData>: replace with LongObjectMap"
-        errorLine1="    private val _cachedNodes = mutableMapOf&lt;Long, CacheData>()"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="return type Map&lt;Long, CacheData> of getCachedNodes: replace with LongObjectMap"
-        errorLine1="    private val cachedNodes: MutableMap&lt;Long, CacheData>"
-        errorLine2="                ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="variable data with type Map&lt;Long, ? extends CacheData>: replace with LongObjectMap"
-        errorLine1="        val data = ThreadUtils.runOnMainThread {"
-        errorLine2="        ^">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="variable composeViewsByRoot with type Map&lt;Long, ? extends List&lt;? extends AndroidComposeViewWrapper>>: replace with LongObjectMap"
-        errorLine1="            val composeViewsByRoot = composeViews.groupBy { it.rootView.uniqueDrawingId }"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="variable data with type Map&lt;Long, ? extends CacheData>: replace with LongObjectMap"
-        errorLine1="            val data = composeViewsByRoot.mapValues { (_, composeViews) ->"
-        errorLine2="            ^">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/ComposeLayoutInspector.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="method asIntArray has parameter $this$asIntArray with type List&lt;Integer>: replace with IntList"
-        errorLine1="fun List&lt;Int>.asIntArray() ="
-        errorLine2="    ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/util/IntArray.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="field semanticsMap with type Map&lt;Integer, List&lt;RawParameter>>: replace with IntObjectMap"
-        errorLine1="    /** Map from semantics id to a list of merged semantics information */"
-        errorLine2="    ^">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTree.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="field unmergedSemanticsMap with type Map&lt;Integer, List&lt;RawParameter>>: replace with IntObjectMap"
-        errorLine1="    /* Map of seemantics id to a list of unmerged semantics information */"
-        errorLine2="    ^">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTree.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="field found with type Map&lt;Long, InspectorNode>: replace with LongObjectMap"
-        errorLine1="        /**"
-        errorLine2="        ^">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTree.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="constructor NodeParameterReference has parameter indices with type List&lt;Integer>: replace with IntList"
-        errorLine1="        indices: List&lt;Int>"
-        errorLine2="                 ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/inspector/NodeParameterReference.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="field systemPackages with type Set&lt;Integer>: replace with IntSet"
-        errorLine1="val systemPackages = setOf("
-        errorLine2="^">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/inspector/PackageHashes.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="return type Set&lt;Integer> of getSystemPackages: replace with IntSet"
-        errorLine1="val systemPackages = setOf("
-        errorLine2="    ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/inspector/PackageHashes.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="field valueIndex with type List&lt;Integer>: replace with IntList"
-        errorLine1="        private val valueIndex = mutableListOf&lt;Int>()"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/inspector/ParameterFactory.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="field rootValueIndexCache with type Map&lt;Long, IdentityHashMap&lt;Object, NodeParameterReference>>: replace with LongObjectMap"
-        errorLine1="        private val rootValueIndexCache ="
-        errorLine2="        ^">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/inspector/ParameterFactory.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="field innerMap with type Map&lt;String, Integer>: replace with ObjectIntMap"
-        errorLine1="    private val innerMap = mutableMapOf&lt;String, Int>()"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/inspection/proto/StringTable.kt"/>
-    </issue>
-
 </issues>
diff --git a/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/ParameterFactoryTest.kt b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/ParameterFactoryTest.kt
index 450c74f..d3375b6 100644
--- a/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/ParameterFactoryTest.kt
+++ b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/ParameterFactoryTest.kt
@@ -717,6 +717,7 @@
 
     @Test
     fun testWrappedModifier() {
+        @Suppress("DEPRECATION")
         fun Modifier.frame(color: Color) = inspectable(
             debugInspectorInfo {
                 name = "frame"
diff --git a/compose/ui/ui-test-junit4/build.gradle b/compose/ui/ui-test-junit4/build.gradle
index c41faf1..a7b8e52 100644
--- a/compose/ui/ui-test-junit4/build.gradle
+++ b/compose/ui/ui-test-junit4/build.gradle
@@ -62,16 +62,14 @@
             }
         }
 
-
         androidMain {
             dependsOn(jvmMain)
             dependencies {
                 api("androidx.activity:activity:1.2.1")
-                implementation "androidx.activity:activity-compose:1.3.0"
                 api("androidx.test.ext:junit:1.1.5")
-		        implementation("androidx.annotation:annotation:1.1.0")
-
-                implementation(project(":compose:runtime:runtime-saveable"))
+                implementation("androidx.activity:activity-compose:1.3.0")
+                implementation("androidx.annotation:annotation:1.1.0")
+                implementation("androidx.compose.runtime:runtime-saveable:1.6.0")
                 implementation("androidx.lifecycle:lifecycle-common:2.5.1")
                 implementation("androidx.lifecycle:lifecycle-runtime:2.5.1")
                 implementation("androidx.test:core:1.5.0")
diff --git a/compose/ui/ui-test/build.gradle b/compose/ui/ui-test/build.gradle
index 18d3ea7..68eb8e6 100644
--- a/compose/ui/ui-test/build.gradle
+++ b/compose/ui/ui-test/build.gradle
@@ -42,7 +42,7 @@
                 api(project(":compose:ui:ui"))
                 api(project(":compose:ui:ui-text"))
                 api(project(":compose:ui:ui-unit"))
-                api(project(":compose:runtime:runtime"))
+                api("androidx.compose.runtime:runtime:1.6.0")
                 api(libs.kotlinStdlib)
 
                 implementation(project(":compose:ui:ui-util"))
@@ -63,20 +63,17 @@
             }
         }
 
-
         androidMain {
             dependsOn(jvmMain)
             dependencies {
-                implementation "androidx.activity:activity-compose:1.3.0"
-
                 api(project(":compose:ui:ui-graphics"))
-
+                implementation("androidx.activity:activity-compose:1.3.0")
                 implementation("androidx.annotation:annotation:1.1.0")
                 implementation("androidx.core:core-ktx:1.12.0")
                 implementation("androidx.test.espresso:espresso-core:3.5.0")
                 implementation("androidx.test.espresso:espresso-idling-resource:3.5.0")
-            	implementation("androidx.test:monitor:1.6.1")
-	        }
+                implementation("androidx.test:monitor:1.6.1")
+            }
         }
 
         desktopMain {
diff --git a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/GlobalAssertionsTest.kt b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/GlobalAssertionsTest.kt
index 8f2a7d1..6b00a30 100644
--- a/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/GlobalAssertionsTest.kt
+++ b/compose/ui/ui-test/src/androidInstrumentedTest/kotlin/androidx/compose/ui/test/GlobalAssertionsTest.kt
@@ -37,41 +37,44 @@
 @RunWith(AndroidJUnit4::class)
 @OptIn(ExperimentalTestApi::class)
 class GlobalAssertionsTest {
-  @get:Rule val composeTestRule = createComposeRule()
+    @get:Rule
+    val composeTestRule = createComposeRule()
 
-  @Before fun setUp() {}
+    @Before
+    fun setUp() {
+    }
 
-  @Test
-  fun performClick_withGlobalAssertion_triggersGlobalAssertion() {
-    composeTestRule.setContent { CountingButton() }
-    var capturedSni: SemanticsNodeInteraction? = null
+    @Test
+    fun performClick_withGlobalAssertion_triggersGlobalAssertion() {
+        composeTestRule.setContent { CountingButton() }
+        var capturedSni: SemanticsNodeInteraction? = null
 
-    addGlobalAssertion(/* name= */ "Fred") { sni -> capturedSni = sni }
-    composeTestRule.onNodeWithText("Increment counter").performClick()
+        addGlobalAssertion(/* name= */ "Fred") { sni -> capturedSni = sni }
+        composeTestRule.onNodeWithText("Increment counter").performClick()
 
-    composeTestRule.onNodeWithText("Clicks: 1").assertExists()
-    capturedSni!!.assertTextContains("Increment counter")
-  }
+        composeTestRule.onNodeWithText("Clicks: 1").assertExists()
+        capturedSni!!.assertTextContains("Increment counter")
+    }
 
-  @Test
-  fun performClick_withGlobalAssertionRemoved_doesNotTriggersGlobalAssertion() {
-    composeTestRule.setContent { CountingButton() }
-    var capturedSni: SemanticsNodeInteraction? = null
+    @Test
+    fun performClick_withGlobalAssertionRemoved_doesNotTriggersGlobalAssertion() {
+        composeTestRule.setContent { CountingButton() }
+        var capturedSni: SemanticsNodeInteraction? = null
 
-    addGlobalAssertion(/* name= */ "Fred") { sni -> capturedSni = sni }
-    removeGlobalAssertion(/* name= */ "Fred")
-    composeTestRule.onNodeWithText("Increment counter").performClick()
+        addGlobalAssertion(/* name= */ "Fred") { sni -> capturedSni = sni }
+        removeGlobalAssertion(/* name= */ "Fred")
+        composeTestRule.onNodeWithText("Increment counter").performClick()
 
-    composeTestRule.onNodeWithText("Clicks: 1").assertExists()
-    assertThat(capturedSni).isNull()
-  }
+        composeTestRule.onNodeWithText("Clicks: 1").assertExists()
+        assertThat(capturedSni).isNull()
+    }
 }
 
 @Composable
 internal fun CountingButton() {
-  var counter by remember { mutableStateOf(0) }
-  Column {
-    Button( counter++ }) { Text("Increment counter") }
-    Text(text = "Clicks: $counter")
-  }
+    var counter by remember { mutableStateOf(0) }
+    Column {
+        Button( counter++ }) { Text("Increment counter") }
+        Text(text = "Clicks: $counter")
+    }
 }
diff --git a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/GlobalAssertions.kt b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/GlobalAssertions.kt
index 222a3e3..18ebb02 100644
--- a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/GlobalAssertions.kt
+++ b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/GlobalAssertions.kt
@@ -35,7 +35,7 @@
  */
 @ExperimentalTestApi
 fun addGlobalAssertion(name: String, assertion: (SemanticsNodeInteraction) -> Unit) {
-  GlobalAssertionsCollection.put(name, assertion)
+    GlobalAssertionsCollection.put(name, assertion)
 }
 
 /**
@@ -45,7 +45,7 @@
  */
 @ExperimentalTestApi
 fun removeGlobalAssertion(name: String) {
-  GlobalAssertionsCollection.remove(name)
+    GlobalAssertionsCollection.remove(name)
 }
 
 /**
@@ -56,8 +56,8 @@
  */
 @ExperimentalTestApi
 fun SemanticsNodeInteraction.invokeGlobalAssertions(): SemanticsNodeInteraction {
-  GlobalAssertionsCollection.invoke(this)
-  return this
+    GlobalAssertionsCollection.invoke(this)
+    return this
 }
 
 /**
@@ -69,37 +69,37 @@
 @ExperimentalTestApi
 fun SemanticsNodeInteractionCollection.invokeGlobalAssertions():
     SemanticsNodeInteractionCollection {
-  GlobalAssertionsCollection.invoke(this)
-  return this
+    GlobalAssertionsCollection.invoke(this)
+    return this
 }
 
 /** Assertions intended to be executed before test actions. */
 internal object GlobalAssertionsCollection {
-  const val TAG = "GlobalAssertions"
+    const val TAG = "GlobalAssertions"
 
-  /** Map of assertion names to their functions */
-  private val globalAssertions = mutableMapOf<String, (SemanticsNodeInteraction) -> Unit>()
+    /** Map of assertion names to their functions */
+    private val globalAssertions = mutableMapOf<String, (SemanticsNodeInteraction) -> Unit>()
 
-  /** Implementation of [addGlobalAssertion] */
-  internal fun put(name: String, assertion: (SemanticsNodeInteraction) -> Unit) {
-    globalAssertions[name] = assertion
-  }
-
-  /** Implementation of [removeGlobalAssertion] */
-  internal fun remove(name: String) {
-    globalAssertions.remove(name)
-  }
-
-  /** Executes every assertion on the given node. */
-  internal fun invoke(sni: SemanticsNodeInteraction) {
-    for (entry in globalAssertions.entries) {
-      printToLog(TAG, "Executing \"${entry.key}\"")
-      entry.value.invoke(sni)
+    /** Implementation of [addGlobalAssertion] */
+    internal fun put(name: String, assertion: (SemanticsNodeInteraction) -> Unit) {
+        globalAssertions[name] = assertion
     }
-  }
 
-  /** Executes every assertion on the first node of the given collection. */
-  internal fun invoke(snic: SemanticsNodeInteractionCollection) {
-    invoke(snic.onFirst())
-  }
+    /** Implementation of [removeGlobalAssertion] */
+    internal fun remove(name: String) {
+        globalAssertions.remove(name)
+    }
+
+    /** Executes every assertion on the given node. */
+    internal fun invoke(sni: SemanticsNodeInteraction) {
+        for (entry in globalAssertions.entries) {
+            printToLog(TAG, "Executing \"${entry.key}\"")
+            entry.value.invoke(sni)
+        }
+    }
+
+    /** Executes every assertion on the first node of the given collection. */
+    internal fun invoke(snic: SemanticsNodeInteractionCollection) {
+        invoke(snic.onFirst())
+    }
 }
diff --git a/compose/ui/ui-text-google-fonts/build.gradle b/compose/ui/ui-text-google-fonts/build.gradle
index ce24693..1c199e3 100644
--- a/compose/ui/ui-text-google-fonts/build.gradle
+++ b/compose/ui/ui-text-google-fonts/build.gradle
@@ -32,9 +32,7 @@
 }
 
 dependencies {
-
     implementation(libs.kotlinStdlib)
-
     implementation("androidx.compose.runtime:runtime:1.2.1")
     implementation(project(":compose:ui:ui-text"))
     implementation("androidx.core:core:1.8.0")
diff --git a/compose/ui/ui-text/build.gradle b/compose/ui/ui-text/build.gradle
index 0eeb331..6641935 100644
--- a/compose/ui/ui-text/build.gradle
+++ b/compose/ui/ui-text/build.gradle
@@ -47,8 +47,8 @@
                 api(project(":compose:ui:ui-unit"))
 
                 // when updating the runtime version please also update the runtime-saveable version
-                implementation(project(":compose:runtime:runtime"))
-                implementation(project(":compose:runtime:runtime-saveable"))
+                implementation("androidx.compose.runtime:runtime:1.6.0")
+                implementation("androidx.compose.runtime:runtime-saveable:1.6.0")
 
                 implementation(project(":compose:ui:ui-util"))
             }
@@ -63,8 +63,6 @@
             dependsOn(commonMain)
             dependencies {
                 api(libs.skikoCommon)
-                implementation(project(":compose:runtime:runtime"))
-                implementation(project(":compose:runtime:runtime-saveable"))
             }
         }
 
@@ -75,7 +73,6 @@
             }
         }
 
-
         androidMain {
             dependsOn(commonMain)
             dependsOn(jvmMain)
diff --git a/compose/ui/ui-tooling-data/build.gradle b/compose/ui/ui-tooling-data/build.gradle
index 1f20915..ad21576 100644
--- a/compose/ui/ui-tooling-data/build.gradle
+++ b/compose/ui/ui-tooling-data/build.gradle
@@ -41,7 +41,7 @@
             dependencies {
                 implementation(libs.kotlinStdlib)
 
-                api(project(":compose:runtime:runtime"))
+                api("androidx.compose.runtime:runtime:1.6.0")
                 api(project(":compose:ui:ui"))
             }
         }
@@ -62,7 +62,6 @@
         skikoMain {
             dependsOn(commonMain)
             dependencies {
-
             }
         }
 
diff --git a/compose/ui/ui-tooling-preview/build.gradle b/compose/ui/ui-tooling-preview/build.gradle
index 0b81b0c..e48247e 100644
--- a/compose/ui/ui-tooling-preview/build.gradle
+++ b/compose/ui/ui-tooling-preview/build.gradle
@@ -40,7 +40,7 @@
         commonMain {
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
-                api(project(":compose:runtime:runtime"))
+                api("androidx.compose.runtime:runtime:1.6.0")
             }
         }
 
@@ -58,7 +58,6 @@
         skikoMain {
             dependsOn(commonMain)
             dependencies {
-                api(project(":compose:runtime:runtime"))
             }
         }
 
@@ -73,7 +72,6 @@
             dependsOn(skikoMain)
             dependsOn(jvmMain)
             dependencies {
-
             }
         }
 
diff --git a/compose/ui/ui-tooling/build.gradle b/compose/ui/ui-tooling/build.gradle
index 682722e..a8680ca 100644
--- a/compose/ui/ui-tooling/build.gradle
+++ b/compose/ui/ui-tooling/build.gradle
@@ -40,8 +40,8 @@
         commonMain {
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
+                api("androidx.compose.runtime:runtime:1.6.0")
                 api(project(":compose:ui:ui-tooling-preview"))
-                api(project(":compose:runtime:runtime"))
                 api(project(":compose:ui:ui"))
                 api(project(":compose:ui:ui-tooling-data"))
             }
@@ -49,7 +49,6 @@
 
         commonTest {
             dependencies {
-
             }
         }
 
diff --git a/compose/ui/ui-unit/build.gradle b/compose/ui/ui-unit/build.gradle
index b5946c7..7338576 100644
--- a/compose/ui/ui-unit/build.gradle
+++ b/compose/ui/ui-unit/build.gradle
@@ -40,12 +40,11 @@
         commonMain {
             dependencies {
                 implementation(libs.kotlinStdlibCommon)
-                api(project(":compose:ui:ui-geometry"))
-
-                implementation(project(":compose:runtime:runtime"))
-                implementation(project(":compose:ui:ui-util"))
-                implementation("androidx.collection:collection:1.4.0")
                 api("androidx.annotation:annotation:1.1.0")
+                api(project(":compose:ui:ui-geometry"))
+                implementation("androidx.collection:collection:1.4.0")
+                implementation("androidx.compose.runtime:runtime:1.6.0")
+                implementation(project(":compose:ui:ui-util"))
             }
         }
 
@@ -75,7 +74,6 @@
         desktopMain {
             dependsOn(jvmMain)
             dependencies {
-                implementation(project(":compose:runtime:runtime"))
             }
         }
 
diff --git a/compose/ui/ui/api/current.txt b/compose/ui/ui/api/current.txt
index ee3b92f..47724d2 100644
--- a/compose/ui/ui/api/current.txt
+++ b/compose/ui/ui/api/current.txt
@@ -2925,7 +2925,7 @@
   public final class InspectableValueKt {
     method public static inline kotlin.jvm.functions.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> debugInspectorInfo(kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> definitions);
     method public static kotlin.jvm.functions.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> getNoInspectorInfo();
-    method public static inline androidx.compose.ui.Modifier inspectable(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> inspectorInfo, kotlin.jvm.functions.Function1<? super androidx.compose.ui.Modifier,? extends androidx.compose.ui.Modifier> factory);
+    method @Deprecated public static inline androidx.compose.ui.Modifier inspectable(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> inspectorInfo, kotlin.jvm.functions.Function1<? super androidx.compose.ui.Modifier,? extends androidx.compose.ui.Modifier> factory);
     method public static boolean isDebugInspectorInfoEnabled();
     method public static void setDebugInspectorInfoEnabled(boolean);
     property public static final kotlin.jvm.functions.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> NoInspectorInfo;
@@ -3665,6 +3665,7 @@
     ctor public PopupProperties(optional boolean focusable, optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional androidx.compose.ui.window.SecureFlagPolicy securePolicy, optional boolean excludeFromSystemGesture, optional boolean clippingEnabled);
     ctor public PopupProperties(optional boolean focusable, optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional androidx.compose.ui.window.SecureFlagPolicy securePolicy, optional boolean excludeFromSystemGesture, optional boolean clippingEnabled, optional boolean usePlatformDefaultWidth);
     ctor public PopupProperties(optional boolean focusable, optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional boolean clippingEnabled);
+    ctor public PopupProperties(int flags, optional boolean inheritSecurePolicy, optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional boolean excludeFromSystemGesture, optional boolean usePlatformDefaultWidth);
     method public boolean getClippingEnabled();
     method public boolean getDismissOnBackPress();
     method public boolean getDismissOnClickOutside();
diff --git a/compose/ui/ui/api/restricted_current.txt b/compose/ui/ui/api/restricted_current.txt
index 7ede5b9..6a2c2fc 100644
--- a/compose/ui/ui/api/restricted_current.txt
+++ b/compose/ui/ui/api/restricted_current.txt
@@ -2978,7 +2978,7 @@
   public final class InspectableValueKt {
     method public static inline kotlin.jvm.functions.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> debugInspectorInfo(kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> definitions);
     method public static kotlin.jvm.functions.Function1<androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> getNoInspectorInfo();
-    method public static inline androidx.compose.ui.Modifier inspectable(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> inspectorInfo, kotlin.jvm.functions.Function1<? super androidx.compose.ui.Modifier,? extends androidx.compose.ui.Modifier> factory);
+    method @Deprecated public static inline androidx.compose.ui.Modifier inspectable(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> inspectorInfo, kotlin.jvm.functions.Function1<? super androidx.compose.ui.Modifier,? extends androidx.compose.ui.Modifier> factory);
     method @kotlin.PublishedApi internal static androidx.compose.ui.Modifier inspectableWrapper(androidx.compose.ui.Modifier, kotlin.jvm.functions.Function1<? super androidx.compose.ui.platform.InspectorInfo,kotlin.Unit> inspectorInfo, androidx.compose.ui.Modifier wrapped);
     method public static boolean isDebugInspectorInfoEnabled();
     method public static void setDebugInspectorInfoEnabled(boolean);
@@ -3725,6 +3725,7 @@
     ctor public PopupProperties(optional boolean focusable, optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional androidx.compose.ui.window.SecureFlagPolicy securePolicy, optional boolean excludeFromSystemGesture, optional boolean clippingEnabled);
     ctor public PopupProperties(optional boolean focusable, optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional androidx.compose.ui.window.SecureFlagPolicy securePolicy, optional boolean excludeFromSystemGesture, optional boolean clippingEnabled, optional boolean usePlatformDefaultWidth);
     ctor public PopupProperties(optional boolean focusable, optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional boolean clippingEnabled);
+    ctor public PopupProperties(int flags, optional boolean inheritSecurePolicy, optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional boolean excludeFromSystemGesture, optional boolean usePlatformDefaultWidth);
     method public boolean getClippingEnabled();
     method public boolean getDismissOnBackPress();
     method public boolean getDismissOnClickOutside();
diff --git a/compose/ui/ui/build.gradle b/compose/ui/ui/build.gradle
index 69ae2b2..5835d87 100644
--- a/compose/ui/ui/build.gradle
+++ b/compose/ui/ui/build.gradle
@@ -46,14 +46,14 @@
                 api("androidx.annotation:annotation:1.6.0")
                 implementation("androidx.collection:collection:1.4.0")
                 // when updating the runtime version please also update the runtime-saveable version
-                implementation(project(":compose:runtime:runtime"))
-                api(project(":compose:runtime:runtime-saveable"))
+                implementation("androidx.compose.runtime:runtime:1.6.0")
+                api("androidx.compose.runtime:runtime-saveable:1.6.0")
 
-                api project(":compose:ui:ui-geometry")
-                api project(":compose:ui:ui-graphics")
-                api project(":compose:ui:ui-text")
-                api project(":compose:ui:ui-unit")
-                api project(":compose:ui:ui-util")
+                api(project(":compose:ui:ui-geometry"))
+                api(project(":compose:ui:ui-graphics"))
+                api(project(":compose:ui:ui-text"))
+                api(project(":compose:ui:ui-unit"))
+                api(project(":compose:ui:ui-util"))
             }
         }
 
@@ -73,7 +73,6 @@
         skikoMain {
             dependsOn(commonMain)
             dependencies {
-                api(project(":compose:ui:ui-graphics"))
                 api(libs.skikoCommon)
             }
         }
@@ -107,7 +106,6 @@
             dependsOn(jvmMain)
             dependencies {
                 implementation(libs.kotlinStdlib)
-                implementation(libs.kotlinStdlibJdk8)
                 api(libs.kotlinCoroutinesSwing)
             }
         }
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/viewinterop/PointerInputInteropComposeInAndroid.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/viewinterop/PointerInputInteropComposeInAndroid.kt
index 39495d1..5d357f3 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/viewinterop/PointerInputInteropComposeInAndroid.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/viewinterop/PointerInputInteropComposeInAndroid.kt
@@ -232,20 +232,16 @@
 
         myContext = peekAvailableContext()!!
 
-        findViewById<TextView>(R.id.text1).text =
-            "Demonstrates correct interop with simple tapping and a window manager"
-        findViewById<TextView>(R.id.text2).text =
-            "The top/outer text and button are Android, and the button dynamically triggers " +
-                "adding/removing a ComposeView via the WindowManager. The inner ComposeView also " +
-                "contains a button that tracks the number of clicks."
-
         button = findViewById<Button>(R.id.button)
         button.setOnClickListener {
-            viewLoaded = if (viewLoaded != null) {
-                myContext.removeWindow(viewLoaded!!)
-                null
+            if (viewLoaded == null) {
+                viewLoaded = myContext.addWindow()
             } else {
-                myContext.addWindow()
+                if (viewLoaded!!.isAttachedToWindow) {
+                    myContext.removeWindow(viewLoaded!!)
+                } else {
+                    myContext.addWindow(viewLoaded)
+                }
             }
         }
     }
@@ -280,7 +276,9 @@
         get() = mViewModelStore
 }
 
-private fun Context.buildWindowView(content: @Composable (composeView: View) -> Unit): View {
+private fun Context.buildWindowView(
+    content: @Composable (composeView: View) -> Unit
+): View {
     val lifecycleOwner = ComposeViewLifecycleOwner()
 
     lifecycleOwner.performRestore(null)
@@ -307,9 +305,11 @@
     }
 }
 
-private fun Context.addWindow(): View {
+private fun Context.addWindow(passedView: View? = null): View {
     val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
-    val view = buildWindowView { SimpleClickableButton() }
+
+    // Reuse existing view (otherwise, create a new one).
+    val view = passedView ?: buildWindowView { SimpleClickableButton() }
 
     val layoutParas = WindowManager.LayoutParams()
 
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/res/layout/compose_in_android_tap_reload.xml b/compose/ui/ui/integration-tests/ui-demos/src/main/res/layout/compose_in_android_tap_reload.xml
index 6d4d50a..724c966 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/res/layout/compose_in_android_tap_reload.xml
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/res/layout/compose_in_android_tap_reload.xml
@@ -16,24 +16,29 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical">
+    android:orientation="vertical"
+    android:padding="15.dp">
 
     <TextView
         android:id="@+id/text1"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_weight="0"/>
+        android:layout_weight="0"
+        android:text="@string/compose_in_android_dynamically_loading_compose_using_window_manager_title"/>
 
     <TextView
         android:id="@+id/text2"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_weight="0"/>
+        android:layout_weight="0"
+        android:text="@string/compose_in_android_dynamically_loading_compose_using_window_manager_details"/>
 
     <Button
         android:id="@+id/button"
-        android:text="Click to unload/load ComposeView"
+        android:text="@string/compose_in_android_dynamically_loading_compose_using_window_manager_button_text"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_weight="0"/>
+        android:layout_weight="0"
+        android:paddingEnd="10.dp"/>
+
 </LinearLayout>
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/res/values/strings.xml b/compose/ui/ui/integration-tests/ui-demos/src/main/res/values/strings.xml
new file mode 100644
index 0000000..fdf9cc5
--- /dev/null
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright 2024 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="compose_in_android_dynamically_loading_compose_using_window_manager_details">The top/outer text and button are Views. The button adds/removes a ComposeView via the WindowManager. The inner ComposeView also contains a button that tracks the number of clicks.</string>
+    <string name="compose_in_android_dynamically_loading_compose_using_window_manager_title">Demonstrates interop with simple tapping and a window manager</string>
+    <string name="compose_in_android_dynamically_loading_compose_using_window_manager_button_text">Click to unload/load ComposeView</string>
+</resources>
\ No newline at end of file
diff --git a/compose/ui/ui/lint-baseline.xml b/compose/ui/ui/lint-baseline.xml
index a00bbef..4769573 100644
--- a/compose/ui/ui/lint-baseline.xml
+++ b/compose/ui/ui/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="BanThreadSleep"
@@ -93,15 +93,6 @@
 
     <issue
         id="PrimitiveInCollection"
-        message="field alignmentLines with type Map&lt;AlignmentLine, Integer>: replace with ObjectIntMap"
-        errorLine1="            override val alignmentLines = alignmentLines"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/ui/layout/IntermediateLayoutModifierNode.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
         message="field alignmentLineMap with type Map&lt;AlignmentLine, Integer>: replace with ObjectIntMap"
         errorLine1="    private val alignmentLineMap: MutableMap&lt;AlignmentLine, Int> = hashMapOf()"
         errorLine2="                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -183,33 +174,6 @@
 
     <issue
         id="PrimitiveInCollection"
-        message="field alignmentLines with type Map&lt;AlignmentLine, Integer>: replace with ObjectIntMap"
-        errorLine1="        override val alignmentLines = alignmentLines"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/ui/layout/MeasureScope.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="variable oldLines with type Map&lt;AlignmentLine, Integer>: replace with ObjectIntMap"
-        errorLine1="                    val oldLines = oldAlignmentLines"
-        errorLine2="                    ^">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/ui/node/NodeCoordinator.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
-        message="variable var43bc2abb with type Map&lt;AlignmentLine, Integer>: replace with ObjectIntMap"
-        errorLine1="                    val oldLines = oldAlignmentLines"
-        errorLine2="                                   ^">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/ui/node/NodeCoordinator.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInCollection"
         message="field oldAlignmentLines with type Map&lt;AlignmentLine, Integer>: replace with ObjectIntMap"
         errorLine1="    private var oldAlignmentLines: MutableMap&lt;AlignmentLine, Int>? = null"
         errorLine2="                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/InspectableModifierSample.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/InspectableModifierSample.kt
index f0654e5..52df79c 100644
--- a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/InspectableModifierSample.kt
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/InspectableModifierSample.kt
@@ -29,6 +29,7 @@
 
 @Sampled
 @Composable
+@Suppress("DEPRECATION")
 fun InspectableModifierSample() {
 
     /**
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
index d53a555..d594371 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/AndroidPointerInputTest.kt
@@ -80,6 +80,7 @@
 import androidx.compose.ui.viewinterop.AndroidView
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import androidx.testutils.waitForFutureFrame
 import com.google.common.truth.Truth.assertThat
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
@@ -101,9 +102,8 @@
 class AndroidPointerInputTest {
     @Suppress("DEPRECATION")
     @get:Rule
-    val rule = androidx.test.rule.ActivityTestRule(
-        AndroidPointerInputTestActivity::class.java
-    )
+    val rule =
+        androidx.test.rule.ActivityTestRule(AndroidPointerInputTestActivity::class.java)
 
     private lateinit var container: OpenComposeView
 
@@ -1348,6 +1348,10 @@
         pointerEvent = null // Reset before each event
         dispatchMouseEvent(ACTION_HOVER_EXIT, box2LayoutCoordinates!!)
 
+        // Hover exit events in Compose are always delayed two frames to ensure Compose does not
+        // trigger them if they are followed by a press in the next frame. This accounts for that.
+        rule.waitForFutureFrame(2)
+
         rule.runOnUiThread {
             assertThat(exitBox2).isTrue()
             assertThat(pointerEvent).isNotNull()
@@ -1385,6 +1389,367 @@
         assertTrue(totalEventLatch.await(1, TimeUnit.SECONDS))
     }
 
+    /*
+     * Tests that a bad ACTION_HOVER_EXIT MotionEvent is ignored in Compose when it directly
+     * proceeds an ACTION_SCROLL MotionEvent. This happens in some versions of Android Studio when
+     * mirroring is used (b/314269723).
+     *
+     * The event order of MotionEvents:
+     *   - Hover enter on box 1
+     *   - Hover exit on box 1 (bad event)
+     *   - Scroll on box 1
+     */
+    @Test
+    fun scrollMotionEvent_proceededImmediatelyByHoverExit_shouldNotTriggerHoverExit() {
+        // --> Arrange
+        val scrollDelta = Offset(0.35f, 0.65f)
+        var box1LayoutCoordinates: LayoutCoordinates? = null
+
+        val setUpFinishedLatch = CountDownLatch(4)
+
+        // Events for Box 1
+        var enterBox1 = false
+        var scrollBox1 = false
+
+        // All other events that should never be triggered in this test
+        var eventsThatShouldNotTrigger = false
+
+        var pointerEvent: PointerEvent? = null
+
+        rule.runOnUiThread {
+            container.setContent {
+                Column(
+                    Modifier
+                        .fillMaxSize()
+                        .onGloballyPositioned {
+                            setUpFinishedLatch.countDown()
+                        }
+                ) {
+                    // Box 1
+                    Box(
+                        Modifier
+                            .size(50.dp)
+                            .onGloballyPositioned {
+                                box1LayoutCoordinates = it
+                                setUpFinishedLatch.countDown()
+                            }
+                            .pointerInput(Unit) {
+                                awaitPointerEventScope {
+                                    while (true) {
+                                        pointerEvent = awaitPointerEvent()
+
+                                        when (pointerEvent!!.type) {
+                                            PointerEventType.Enter -> {
+                                                enterBox1 = true
+                                            }
+
+                                            PointerEventType.Exit -> {
+                                                enterBox1 = false
+                                            }
+
+                                            PointerEventType.Scroll -> {
+                                                scrollBox1 = true
+                                            }
+
+                                            else -> {
+                                                eventsThatShouldNotTrigger = true
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                    ) { }
+
+                    // Box 2
+                    Box(
+                        Modifier
+                            .size(50.dp)
+                            .onGloballyPositioned {
+                                setUpFinishedLatch.countDown()
+                            }
+                            .pointerInput(Unit) {
+                                awaitPointerEventScope {
+                                    while (true) {
+                                        pointerEvent = awaitPointerEvent()
+                                        // Should never do anything with this UI element.
+                                        eventsThatShouldNotTrigger = true
+                                    }
+                                }
+                            }
+                    ) { }
+
+                    // Box 3
+                    Box(
+                        Modifier
+                            .size(50.dp)
+                            .onGloballyPositioned {
+                                setUpFinishedLatch.countDown()
+                            }
+                            .pointerInput(Unit) {
+                                awaitPointerEventScope {
+                                    while (true) {
+                                        pointerEvent = awaitPointerEvent()
+                                        // Should never do anything with this UI element.
+                                        eventsThatShouldNotTrigger = true
+                                    }
+                                }
+                            }
+                    ) { }
+                }
+            }
+        }
+        // Ensure Arrange (setup) step is finished
+        assertTrue(setUpFinishedLatch.await(2, TimeUnit.SECONDS))
+
+        // --> Act + Assert (interwoven)
+        // Hover Enter on Box 1
+        dispatchMouseEvent(ACTION_HOVER_ENTER, box1LayoutCoordinates!!)
+        rule.runOnUiThread {
+            assertThat(enterBox1).isTrue()
+            assertThat(pointerEvent).isNotNull()
+            assertThat(eventsThatShouldNotTrigger).isFalse()
+            assertHoverEvent(pointerEvent!!, isEnter = true)
+        }
+
+        // We do not use dispatchMouseEvent() to dispatch the following two events, because the
+        // actions need to be executed in immediate succession
+        rule.runOnUiThread {
+            val root = box1LayoutCoordinates!!.findRootCoordinates()
+            val pos = root.localPositionOf(box1LayoutCoordinates!!, Offset.Zero)
+
+            // Bad hover exit event on Box 1
+            val exitMotionEvent = MotionEvent(
+                0,
+                ACTION_HOVER_EXIT,
+                1,
+                0,
+                arrayOf(PointerProperties(0).also { it.toolType = MotionEvent.TOOL_TYPE_MOUSE }),
+                arrayOf(PointerCoords(pos.x, pos.y, Offset.Zero.x, Offset.Zero.y))
+            )
+
+            // Main scroll event on Box 1
+            val scrollMotionEvent = MotionEvent(
+                0,
+                ACTION_SCROLL,
+                1,
+                0,
+                arrayOf(PointerProperties(0).also { it.toolType = MotionEvent.TOOL_TYPE_MOUSE }),
+                arrayOf(PointerCoords(pos.x, pos.y, scrollDelta.x, scrollDelta.y))
+            )
+
+            val androidComposeView = findAndroidComposeView(container) as AndroidComposeView
+            androidComposeView.dispatchHoverEvent(exitMotionEvent)
+            androidComposeView.dispatchGenericMotionEvent(scrollMotionEvent)
+        }
+
+        rule.runOnUiThread {
+            assertThat(enterBox1).isTrue()
+            assertThat(scrollBox1).isTrue()
+            assertThat(pointerEvent).isNotNull()
+            assertThat(eventsThatShouldNotTrigger).isFalse()
+        }
+    }
+
+    /*
+     * Tests an ACTION_HOVER_EXIT MotionEvent is ignored in Compose when it proceeds an
+     * ACTION_DOWN MotionEvent (in a measure of milliseconds only).
+     *
+     * The event order of MotionEvents:
+     *   - Hover enter on box 1
+     *   - Loop 10 times:
+     *     - Hover enter on box 1
+     *     - Down on box 1
+     *     - Up on box 1
+     */
+    @Test
+    fun hoverExitBeforeDownMotionEvent_shortDelayBetweenMotionEvents_shouldNotTriggerHoverExit() {
+        // --> Arrange
+        var box1LayoutCoordinates: LayoutCoordinates? = null
+
+        val setUpFinishedLatch = CountDownLatch(4)
+
+        // Events for Box 1
+        var enterBox1 = false
+        var pressBox1 = false
+
+        // All other events that should never be triggered in this test
+        var eventsThatShouldNotTrigger = false
+
+        var pointerEvent: PointerEvent? = null
+
+        rule.runOnUiThread {
+            container.setContent {
+                Column(
+                    Modifier
+                        .fillMaxSize()
+                        .onGloballyPositioned {
+                            setUpFinishedLatch.countDown()
+                        }
+                ) {
+                    // Box 1
+                    Box(
+                        Modifier
+                            .size(50.dp)
+                            .onGloballyPositioned {
+                                box1LayoutCoordinates = it
+                                setUpFinishedLatch.countDown()
+                            }
+                            .pointerInput(Unit) {
+                                awaitPointerEventScope {
+                                    while (true) {
+                                        pointerEvent = awaitPointerEvent()
+
+                                        when (pointerEvent!!.type) {
+                                            PointerEventType.Enter -> {
+                                                enterBox1 = true
+                                            }
+
+                                            PointerEventType.Exit -> {
+                                                enterBox1 = false
+                                            }
+
+                                            PointerEventType.Press -> {
+                                                pressBox1 = true
+                                            }
+
+                                            PointerEventType.Release -> {
+                                                pressBox1 = false
+                                            }
+
+                                            else -> {
+                                                eventsThatShouldNotTrigger = true
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                    ) { }
+
+                    // Box 2
+                    Box(
+                        Modifier
+                            .size(50.dp)
+                            .onGloballyPositioned {
+                                setUpFinishedLatch.countDown()
+                            }
+                            .pointerInput(Unit) {
+                                awaitPointerEventScope {
+                                    while (true) {
+                                        pointerEvent = awaitPointerEvent()
+                                        // Should never do anything with this UI element.
+                                        eventsThatShouldNotTrigger = true
+                                    }
+                                }
+                            }
+                    ) { }
+
+                    // Box 3
+                    Box(
+                        Modifier
+                            .size(50.dp)
+                            .onGloballyPositioned {
+                                setUpFinishedLatch.countDown()
+                            }
+                            .pointerInput(Unit) {
+                                awaitPointerEventScope {
+                                    while (true) {
+                                        pointerEvent = awaitPointerEvent()
+                                        // Should never do anything with this UI element.
+                                        eventsThatShouldNotTrigger = true
+                                    }
+                                }
+                            }
+                    ) { }
+                }
+            }
+        }
+        // Ensure Arrange (setup) step is finished
+        assertTrue(setUpFinishedLatch.await(2, TimeUnit.SECONDS))
+
+        // --> Act + Assert (interwoven)
+        // Hover Enter on Box 1
+        dispatchMouseEvent(ACTION_HOVER_ENTER, box1LayoutCoordinates!!)
+        rule.runOnUiThread {
+            assertThat(enterBox1).isTrue()
+            assertThat(pointerEvent).isNotNull()
+            assertThat(eventsThatShouldNotTrigger).isFalse()
+            assertHoverEvent(pointerEvent!!, isEnter = true)
+        }
+
+        pointerEvent = null // Reset before each event
+
+        for (index in 0 until 10) {
+            // We do not use dispatchMouseEvent() to dispatch the following two events, because the
+            // actions need to be executed in immediate succession.
+            rule.runOnUiThread {
+                val root = box1LayoutCoordinates!!.findRootCoordinates()
+                val pos = root.localPositionOf(box1LayoutCoordinates!!, Offset.Zero)
+
+                // Exit on Box 1 right before action down. This happens normally on devices, so we
+                // are recreating it here. However, Compose ignores the exit if it is right before
+                // a down (right before meaning within a couple milliseconds). We verify that it
+                // did in fact ignore this exit.
+                val exitMotionEvent = MotionEvent(
+                    0,
+                    ACTION_HOVER_EXIT,
+                    1,
+                    0,
+                    arrayOf(
+                        PointerProperties(0).also { it.toolType = MotionEvent.TOOL_TYPE_MOUSE }
+                    ),
+                    arrayOf(
+                        PointerCoords(pos.x, pos.y, Offset.Zero.x, Offset.Zero.y)
+                    )
+                )
+
+                // Press on Box 1
+                val downMotionEvent = MotionEvent(
+                    0,
+                    ACTION_DOWN,
+                    1,
+                    0,
+                    arrayOf(
+                        PointerProperties(0).also { it.toolType = MotionEvent.TOOL_TYPE_MOUSE }
+                    ),
+                    arrayOf(
+                        PointerCoords(pos.x, pos.y, Offset.Zero.x, Offset.Zero.y)
+                    )
+                )
+
+                val androidComposeView =
+                    findAndroidComposeView(container) as AndroidComposeView
+
+                // Execute events
+                androidComposeView.dispatchHoverEvent(exitMotionEvent)
+                androidComposeView.dispatchTouchEvent(downMotionEvent)
+            }
+
+            // In Compose, a hover exit MotionEvent is ignored if it is quickly followed
+            // by a press.
+            rule.runOnUiThread {
+                assertThat(enterBox1).isTrue()
+                assertThat(pressBox1).isTrue()
+                assertThat(eventsThatShouldNotTrigger).isFalse()
+                assertThat(pointerEvent).isNotNull()
+            }
+
+            // Release on Box 1
+            pointerEvent = null // Reset before each event
+            dispatchTouchEvent(ACTION_UP, box1LayoutCoordinates!!)
+
+            rule.runOnUiThread {
+                assertThat(enterBox1).isTrue()
+                assertThat(pressBox1).isFalse()
+                assertThat(eventsThatShouldNotTrigger).isFalse()
+                assertThat(pointerEvent).isNotNull()
+            }
+        }
+
+        rule.runOnUiThread {
+            assertThat(eventsThatShouldNotTrigger).isFalse()
+        }
+    }
+
     @Test
     fun dispatchHoverMove() {
         var layoutCoordinates: LayoutCoordinates? = null
@@ -2009,6 +2374,10 @@
         dispatchStylusEvents(coords, Offset.Zero, ACTION_HOVER_ENTER)
         dispatchStylusEvents(coords, Offset.Zero, ACTION_HOVER_EXIT)
 
+        // Hover exit events in Compose are always delayed two frames to ensure Compose does not
+        // trigger them if they are followed by a press in the next frame. This accounts for that.
+        rule.waitForFutureFrame(2)
+
         rule.runOnUiThread {
             assertThat(eventLog).hasSize(2)
             assertThat(eventLog[0].type).isEqualTo(PointerEventType.Enter)
@@ -2094,7 +2463,6 @@
         }
     }
 
-    // TODO (jjw): Another option
     @Test
     fun syntheticEventSentAfterUp() {
         val eventLog = mutableListOf<PointerEvent>()
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/platform/InspectableValueTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/platform/InspectableValueTest.kt
index 802339d..1cf6d5c 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/platform/InspectableValueTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/platform/InspectableValueTest.kt
@@ -45,6 +45,7 @@
         isDebugInspectorInfoEnabled = false
     }
 
+    @Suppress("DEPRECATION")
     fun Modifier.simple(padding: Int, border: Dp) = inspectable(
         debugInspectorInfo {
             name = "simple"
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/PopupSecureFlagTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/PopupSecureFlagTest.kt
index f4aec1d..44d7703 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/PopupSecureFlagTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/PopupSecureFlagTest.kt
@@ -114,6 +114,37 @@
         assertThat(isSecureFlagEnabledForPopup()).isEqualTo(setSecureFlagOnActivity)
     }
 
+    @Test
+    fun toggleFlagOnPopup_customFlagsOverload() {
+        var properties: PopupProperties by mutableStateOf(
+            PopupProperties(
+                flags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
+                inheritSecurePolicy = false,
+            )
+        )
+
+        rule.setContent {
+            TestPopup(properties)
+        }
+
+        assertThat(isSecureFlagEnabledForPopup()).isFalse()
+
+        // Toggle flag
+        properties = PopupProperties(
+            flags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or
+                WindowManager.LayoutParams.FLAG_SECURE,
+            inheritSecurePolicy = false,
+        )
+        assertThat(isSecureFlagEnabledForPopup()).isTrue()
+
+        // Set to inherit
+        properties = PopupProperties(
+            flags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
+            inheritSecurePolicy = true,
+        )
+        assertThat(isSecureFlagEnabledForPopup()).isEqualTo(setSecureFlagOnActivity)
+    }
+
     @Composable
     fun TestPopup(popupProperties: PopupProperties) {
         SimpleContainer {
diff --git a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/PopupTest.kt b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/PopupTest.kt
index c8cde80..cf421ef 100644
--- a/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/PopupTest.kt
+++ b/compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/window/PopupTest.kt
@@ -18,6 +18,7 @@
 import android.view.View
 import android.view.View.MEASURED_STATE_TOO_SMALL
 import android.view.ViewGroup
+import android.view.WindowManager
 import android.widget.FrameLayout
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
@@ -417,6 +418,37 @@
     }
 
     @Test
+    fun customFlags() {
+        val flags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH or
+            WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS or
+            WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES or
+            WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+
+        rule.setContent {
+            PopupTestTag(testTag) {
+                Popup(
+                    properties = PopupProperties(
+                        flags = flags,
+                        inheritSecurePolicy = false,
+                    )
+                ) {
+                    Box(Modifier.size(50.dp))
+                }
+            }
+        }
+
+        // Make sure that current measurement/drawing is finished
+        rule.runOnIdle { }
+        val popupMatcher = PopupLayoutMatcher(testTag)
+        Espresso.onView(instanceOf(Owner::class.java))
+            .inRoot(popupMatcher)
+            .check(matches(isDisplayed()))
+        val capturedFlags = popupMatcher.lastSeenWindowParams!!.flags
+
+        assertThat(capturedFlags and flags).isEqualTo(flags)
+    }
+
+    @Test
     fun didNotMeasureTooSmallLast() {
         rule.setContent {
             PopupTestTag(testTag) {
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
index 1b7aae9..4e0daa98 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
@@ -207,6 +207,8 @@
 internal var platformTextInputServiceInterceptor:
         (PlatformTextInputService) -> PlatformTextInputService = { it }
 
+private const val ONE_FRAME_120_HERTZ_IN_MILLISECONDS = 8L
+
 @Suppress("ViewConstructor", "VisibleForTests", "ConstPropertyName", "NullAnnotationGroup")
 @OptIn(ExperimentalComposeUiApi::class, InternalComposeUiApi::class)
 internal class AndroidComposeView(
@@ -1584,17 +1586,32 @@
         )
     }
 
-    override fun dispatchGenericMotionEvent(event: MotionEvent) = when (event.actionMasked) {
-        ACTION_SCROLL -> when {
-            isBadMotionEvent(event) || !isAttachedToWindow ->
-                super.dispatchGenericMotionEvent(event)
-
-            event.isFromSource(SOURCE_ROTARY_ENCODER) -> handleRotaryEvent(event)
-
-            else -> handleMotionEvent(event).dispatchedToAPointerInputModifier
+    override fun dispatchGenericMotionEvent(motionEvent: MotionEvent): Boolean {
+        if (hoverExitReceived) {
+            removeCallbacks(sendHoverExitEvent)
+            // Ignore ACTION_HOVER_EXIT if it is directly followed by an ACTION_SCROLL.
+            // Note: In some versions of Android Studio with screen mirroring, studio will
+            // incorrectly add an ACTION_HOVER_EXIT during a scroll event which causes
+            // issues (b/314269723), so we ignore the exit in that case.
+            if (motionEvent.actionMasked == ACTION_SCROLL) {
+                hoverExitReceived = false
+            } else {
+                sendHoverExitEvent.run()
+            }
         }
 
-        else -> super.dispatchGenericMotionEvent(event)
+        return when (motionEvent.actionMasked) {
+            ACTION_SCROLL -> when {
+                isBadMotionEvent(motionEvent) || !isAttachedToWindow ->
+                    super.dispatchGenericMotionEvent(motionEvent)
+
+                motionEvent.isFromSource(SOURCE_ROTARY_ENCODER) -> handleRotaryEvent(motionEvent)
+
+                else -> handleMotionEvent(motionEvent).dispatchedToAPointerInputModifier
+            }
+
+            else -> super.dispatchGenericMotionEvent(motionEvent)
+        }
     }
 
     // TODO(shepshapard): Test this method.
@@ -1986,7 +2003,11 @@
                     previousMotionEvent?.recycle()
                     previousMotionEvent = MotionEvent.obtainNoHistory(event)
                     hoverExitReceived = true
-                    post(sendHoverExitEvent)
+                    // There are cases where the hover exit will incorrectly trigger because this
+                    // post is called right before the end of the frame and the new frame checks for
+                    // a press/down event (which hasn't occurred yet). Therefore, we delay the post
+                    // call a small amount to account for that.
+                    postDelayed(sendHoverExitEvent, ONE_FRAME_120_HERTZ_IN_MILLISECONDS)
                     return false
                 }
             }
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidPopup.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidPopup.android.kt
index c2879c2..5c2c808 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidPopup.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidPopup.android.kt
@@ -92,34 +92,32 @@
 /**
  * Properties used to customize the behavior of a [Popup].
  *
- * @property focusable Whether the popup is focusable. When true, the popup will receive IME
- * events and key presses, such as when the back button is pressed.
+ * @property flags Behavioral flags of the popup, which will be passed to the popup window's
+ * [WindowManager.LayoutParams]. See [WindowManager.LayoutParams.flags] for customization options.
+ * If [inheritSecurePolicy] is true, the value of the [WindowManager.LayoutParams.FLAG_SECURE]
+ * bit will not be determined until the popup is constructed.
+ * @property inheritSecurePolicy Whether [WindowManager.LayoutParams.FLAG_SECURE] should be set
+ * according to [SecureFlagPolicy.Inherit]. Other [SecureFlagPolicy] behaviors should be set via
+ * [flags] directly.
  * @property dismissOnBackPress Whether the popup can be dismissed by pressing the back button.
- * If true, pressing the back button will call onDismissRequest. Note that [focusable] must be
- * set to true in order to receive key events such as the back button - if the popup is not
- * focusable then this property does nothing.
+ * If true, pressing the back button will call onDismissRequest. Note that the popup must be
+ * [focusable] in order to receive key events such as the back button. If the popup is not
+ * [focusable], then this property does nothing.
  * @property dismissOnClickOutside Whether the popup can be dismissed by clicking outside the
  * popup's bounds. If true, clicking outside the popup will call onDismissRequest.
- * @property securePolicy Policy for setting [WindowManager.LayoutParams.FLAG_SECURE] on the popup's
- * window.
  * @property excludeFromSystemGesture A flag to check whether to set the systemGestureExclusionRects.
  * The default is true.
- * @property clippingEnabled Whether to allow the popup window to extend beyond the bounds of the
- * screen. By default the window is clipped to the screen boundaries. Setting this to false will
- * allow windows to be accurately positioned.
- * The default value is true.
  * @property usePlatformDefaultWidth Whether the width of the popup's content should be limited to
  * the platform default, which is smaller than the screen width.
  */
 @Immutable
 actual class PopupProperties constructor(
-    actual val focusable: Boolean = false,
+    internal val flags: Int,
+    internal val inheritSecurePolicy: Boolean = true,
     actual val dismissOnBackPress: Boolean = true,
     actual val dismissOnClickOutside: Boolean = true,
-    val securePolicy: SecureFlagPolicy = SecureFlagPolicy.Inherit,
     val excludeFromSystemGesture: Boolean = true,
-    actual val clippingEnabled: Boolean = true,
-    val usePlatformDefaultWidth: Boolean = false
+    val usePlatformDefaultWidth: Boolean = false,
 ) {
     actual constructor(
         focusable: Boolean,
@@ -149,32 +147,93 @@
         securePolicy = securePolicy,
         excludeFromSystemGesture = excludeFromSystemGesture,
         clippingEnabled = clippingEnabled,
-        usePlatformDefaultWidth = false
+        usePlatformDefaultWidth = false,
     )
 
+    /**
+     * Constructs a [PopupProperties] with the given behaviors. This constructor is to support
+     * multiplatform and maintain backwards compatibility. Consider the overload that takes a
+     * [flags] parameter if more precise control over the popup flags is desired.
+     *
+     * @param focusable Whether the popup is focusable. When true, the popup will receive IME
+     * events and key presses, such as when the back button is pressed.
+     * @param dismissOnBackPress Whether the popup can be dismissed by pressing the back button.
+     * If true, pressing the back button will call onDismissRequest. Note that [focusable] must be
+     * set to true in order to receive key events such as the back button. If the popup is not
+     * focusable, then this property does nothing.
+     * @param dismissOnClickOutside Whether the popup can be dismissed by clicking outside the
+     * popup's bounds. If true, clicking outside the popup will call onDismissRequest.
+     * @param securePolicy Policy for setting [WindowManager.LayoutParams.FLAG_SECURE] on the
+     * popup's window.
+     * @param excludeFromSystemGesture A flag to check whether to set the
+     * systemGestureExclusionRects. The default is true.
+     * @param clippingEnabled Whether to allow the popup window to extend beyond the bounds of the
+     * screen. By default the window is clipped to the screen boundaries. Setting this to false will
+     * allow windows to be accurately positioned. The default value is true.
+     * @param usePlatformDefaultWidth Whether the width of the popup's content should be limited to
+     * the platform default, which is smaller than the screen width.
+     */
+    constructor(
+        focusable: Boolean = false,
+        dismissOnBackPress: Boolean = true,
+        dismissOnClickOutside: Boolean = true,
+        securePolicy: SecureFlagPolicy = SecureFlagPolicy.Inherit,
+        excludeFromSystemGesture: Boolean = true,
+        clippingEnabled: Boolean = true,
+        usePlatformDefaultWidth: Boolean = false,
+    ) : this (
+        flags = createFlags(focusable, securePolicy, clippingEnabled),
+        inheritSecurePolicy = securePolicy == SecureFlagPolicy.Inherit,
+        dismissOnBackPress = dismissOnBackPress,
+        dismissOnClickOutside = dismissOnClickOutside,
+        excludeFromSystemGesture = excludeFromSystemGesture,
+        usePlatformDefaultWidth = usePlatformDefaultWidth,
+    )
+
+    /**
+     * Whether the popup is focusable. When true, the popup will receive IME events and key
+     * presses, such as when the back button is pressed.
+     */
+    actual val focusable: Boolean
+        get() = (flags and WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0
+
+    /**
+     * Policy for how [WindowManager.LayoutParams.FLAG_SECURE] is set on the popup's window.
+     */
+    val securePolicy: SecureFlagPolicy
+        get() = when {
+            inheritSecurePolicy -> SecureFlagPolicy.Inherit
+            (flags and WindowManager.LayoutParams.FLAG_SECURE) == 0 -> SecureFlagPolicy.SecureOff
+            else -> SecureFlagPolicy.SecureOn
+        }
+
+    /**
+     * Whether the popup window is clipped to the screen boundaries, or allowed to extend beyond
+     * the bounds of the screen.
+     */
+    actual val clippingEnabled: Boolean
+        get() = (flags and WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) == 0
+
     override fun equals(other: Any?): Boolean {
         if (this === other) return true
         if (other !is PopupProperties) return false
 
-        if (focusable != other.focusable) return false
+        if (flags != other.flags) return false
+        if (inheritSecurePolicy != other.inheritSecurePolicy) return false
         if (dismissOnBackPress != other.dismissOnBackPress) return false
         if (dismissOnClickOutside != other.dismissOnClickOutside) return false
-        if (securePolicy != other.securePolicy) return false
         if (excludeFromSystemGesture != other.excludeFromSystemGesture) return false
-        if (clippingEnabled != other.clippingEnabled) return false
         if (usePlatformDefaultWidth != other.usePlatformDefaultWidth) return false
 
         return true
     }
 
     override fun hashCode(): Int {
-        var result = dismissOnBackPress.hashCode()
-        result = 31 * result + focusable.hashCode()
+        var result = flags
+        result = 31 * result + inheritSecurePolicy.hashCode()
         result = 31 * result + dismissOnBackPress.hashCode()
         result = 31 * result + dismissOnClickOutside.hashCode()
-        result = 31 * result + securePolicy.hashCode()
         result = 31 * result + excludeFromSystemGesture.hashCode()
-        result = 31 * result + clippingEnabled.hashCode()
         result = 31 * result + usePlatformDefaultWidth.hashCode()
         return result
     }
@@ -340,6 +399,27 @@
     }
 }
 
+private const val PopupPropertiesBaseFlags: Int =
+    WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+
+private fun createFlags(
+    focusable: Boolean,
+    securePolicy: SecureFlagPolicy,
+    clippingEnabled: Boolean,
+): Int {
+    var flags = PopupPropertiesBaseFlags
+    if (!focusable) {
+        flags = flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+    }
+    if (securePolicy == SecureFlagPolicy.SecureOn) {
+        flags = flags or WindowManager.LayoutParams.FLAG_SECURE
+    }
+    if (!clippingEnabled) {
+        flags = flags or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+    }
+    return flags
+}
+
 // TODO(b/139861182): This is a hack to work around Popups not using Semantics for test tags
 //  We should either remove it, or come up with an abstracted general solution that isn't specific
 //  to Popup
@@ -585,61 +665,31 @@
         backCallback = null
     }
 
-    /**
-     * Set whether the popup can grab a focus and support dismissal.
-     */
-    private fun setIsFocusable(isFocusable: Boolean) = applyNewFlags(
-        if (!isFocusable) {
-            params.flags or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-        } else {
-            params.flags and (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE.inv())
-        }
-    )
-
-    private fun setSecurePolicy(securePolicy: SecureFlagPolicy) {
-        val secureFlagEnabled =
-            securePolicy.shouldApplySecureFlag(composeView.isFlagSecureEnabled())
-        applyNewFlags(
-            if (secureFlagEnabled) {
-                params.flags or WindowManager.LayoutParams.FLAG_SECURE
-            } else {
-                params.flags and (WindowManager.LayoutParams.FLAG_SECURE.inv())
-            }
-        )
-    }
-
-    private fun setClippingEnabled(clippingEnabled: Boolean) = applyNewFlags(
-        if (clippingEnabled) {
-            params.flags and (WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS.inv())
-        } else {
-            params.flags or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
-        }
-    )
-
     fun updateParameters(
         onDismissRequest: (() -> Unit)?,
         properties: PopupProperties,
         testTag: String,
-        layoutDirection: LayoutDirection
+        layoutDirection: LayoutDirection,
     ) {
         this.>
+        this.testTag = testTag
+        updatePopupProperties(properties)
+        superSetLayoutDirection(layoutDirection)
+    }
+
+    private fun updatePopupProperties(properties: PopupProperties) {
+        if (this.properties == properties) return
+
         if (properties.usePlatformDefaultWidth && !this.properties.usePlatformDefaultWidth) {
             // Undo fixed size in internalOnLayout, which would suppress size changes when
             // usePlatformDefaultWidth is true.
             params.width = WindowManager.LayoutParams.WRAP_CONTENT
             params.height = WindowManager.LayoutParams.WRAP_CONTENT
-            popupLayoutHelper.updateViewLayout(windowManager, this, params)
         }
-        this.properties = properties
-        this.testTag = testTag
-        setIsFocusable(properties.focusable)
-        setSecurePolicy(properties.securePolicy)
-        setClippingEnabled(properties.clippingEnabled)
-        superSetLayoutDirection(layoutDirection)
-    }
 
-    private fun applyNewFlags(flags: Int) {
-        params.flags = flags
+        this.properties = properties
+        params.flags = properties.flagsWithSecureFlagInherited(composeView.isFlagSecureEnabled())
+
         popupLayoutHelper.updateViewLayout(windowManager, this, params)
     }
 
@@ -789,17 +839,7 @@
             // Start to position the popup in the top left corner, a new position will be calculated
             gravity = Gravity.START or Gravity.TOP
 
-            // Flags specific to android.widget.PopupWindow
-            flags = flags and (
-                WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES or
-                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
-                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
-                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM or
-                    WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
-                ).inv()
-
-            // Enables us to intercept outside clicks even when popup is not focusable
-            flags = flags or WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+            flags = properties.flagsWithSecureFlagInherited(composeView.isFlagSecureEnabled())
 
             type = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL
 
@@ -909,6 +949,14 @@
     return false
 }
 
+private fun PopupProperties.flagsWithSecureFlagInherited(
+    isParentFlagSecureEnabled: Boolean,
+): Int = if (this.inheritSecurePolicy && isParentFlagSecureEnabled) {
+    this.flags or WindowManager.LayoutParams.FLAG_SECURE
+} else {
+    this.flags
+}
+
 private fun Rect.toIntBounds() = IntRect(
     left = left,
     top = top,
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Expect.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Expect.kt
index e4b50a2..46900a3 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Expect.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Expect.kt
@@ -21,6 +21,8 @@
 
 internal expect fun areObjectsOfSameType(a: Any, b: Any): Boolean
 
+internal expect fun classKeyForObject(a: Any): Any
+
 /**
  * Reflectively resolves the properties and name of [element], and populates it in the receiver.
  * This function is used by [ModifierNodeElement] as a default implementation to provide inspection
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt
index b00cd91..60fc8a6 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeKind.kt
@@ -16,8 +16,10 @@
 
 package androidx.compose.ui.node
 
+import androidx.collection.mutableObjectIntMapOf
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.classKeyForObject
 import androidx.compose.ui.draw.DrawModifier
 import androidx.compose.ui.focus.FocusEventModifierNode
 import androidx.compose.ui.focus.FocusProperties
@@ -152,65 +154,68 @@
     return mask
 }
 
+private val classToKindSetMap = mutableObjectIntMapOf<Any>()
 @OptIn(ExperimentalComposeUiApi::class)
 internal fun calculateNodeKindSetFrom(node: Modifier.Node): Int {
     // This function does not take delegates into account, as a result, the kindSet will never
     // change, so if it is non-zero, it means we've already calculated it and we can just bail
     // early here.
     if (node.kindSet != 0) return node.kindSet
-    var mask = Nodes.Any.mask
-    if (node is LayoutModifierNode) {
-        mask = mask or Nodes.Layout
+    return classToKindSetMap.getOrPut(classKeyForObject(node)) {
+        var mask = Nodes.Any.mask
+        if (node is LayoutModifierNode) {
+            mask = mask or Nodes.Layout
+        }
+        if (node is DrawModifierNode) {
+            mask = mask or Nodes.Draw
+        }
+        if (node is SemanticsModifierNode) {
+            mask = mask or Nodes.Semantics
+        }
+        if (node is PointerInputModifierNode) {
+            mask = mask or Nodes.PointerInput
+        }
+        if (node is ModifierLocalModifierNode) {
+            mask = mask or Nodes.Locals
+        }
+        if (node is ParentDataModifierNode) {
+            mask = mask or Nodes.ParentData
+        }
+        if (node is LayoutAwareModifierNode) {
+            mask = mask or Nodes.LayoutAware
+        }
+        if (node is GlobalPositionAwareModifierNode) {
+            mask = mask or Nodes.GlobalPositionAware
+        }
+        if (node is ApproachLayoutModifierNode) {
+            mask = mask or Nodes.IntermediateMeasure
+        }
+        if (node is FocusTargetNode) {
+            mask = mask or Nodes.FocusTarget
+        }
+        if (node is FocusPropertiesModifierNode) {
+            mask = mask or Nodes.FocusProperties
+        }
+        if (node is FocusEventModifierNode) {
+            mask = mask or Nodes.FocusEvent
+        }
+        if (node is KeyInputModifierNode) {
+            mask = mask or Nodes.KeyInput
+        }
+        if (node is RotaryInputModifierNode) {
+            mask = mask or Nodes.RotaryInput
+        }
+        if (node is CompositionLocalConsumerModifierNode) {
+            mask = mask or Nodes.CompositionLocalConsumer
+        }
+        if (node is SoftKeyboardInterceptionModifierNode) {
+            mask = mask or Nodes.SoftKeyboardKeyInput
+        }
+        if (node is TraversableNode) {
+            mask = mask or Nodes.Traversable
+        }
+        mask
     }
-    if (node is DrawModifierNode) {
-        mask = mask or Nodes.Draw
-    }
-    if (node is SemanticsModifierNode) {
-        mask = mask or Nodes.Semantics
-    }
-    if (node is PointerInputModifierNode) {
-        mask = mask or Nodes.PointerInput
-    }
-    if (node is ModifierLocalModifierNode) {
-        mask = mask or Nodes.Locals
-    }
-    if (node is ParentDataModifierNode) {
-        mask = mask or Nodes.ParentData
-    }
-    if (node is LayoutAwareModifierNode) {
-        mask = mask or Nodes.LayoutAware
-    }
-    if (node is GlobalPositionAwareModifierNode) {
-        mask = mask or Nodes.GlobalPositionAware
-    }
-    if (node is ApproachLayoutModifierNode) {
-        mask = mask or Nodes.IntermediateMeasure
-    }
-    if (node is FocusTargetNode) {
-        mask = mask or Nodes.FocusTarget
-    }
-    if (node is FocusPropertiesModifierNode) {
-        mask = mask or Nodes.FocusProperties
-    }
-    if (node is FocusEventModifierNode) {
-        mask = mask or Nodes.FocusEvent
-    }
-    if (node is KeyInputModifierNode) {
-        mask = mask or Nodes.KeyInput
-    }
-    if (node is RotaryInputModifierNode) {
-        mask = mask or Nodes.RotaryInput
-    }
-    if (node is CompositionLocalConsumerModifierNode) {
-        mask = mask or Nodes.CompositionLocalConsumer
-    }
-    if (node is SoftKeyboardInterceptionModifierNode) {
-        mask = mask or Nodes.SoftKeyboardKeyInput
-    }
-    if (node is TraversableNode) {
-        mask = mask or Nodes.Traversable
-    }
-    return mask
 }
 
 @Suppress("ConstPropertyName")
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/InspectableValue.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/InspectableValue.kt
index 02bedf9..970de2b 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/InspectableValue.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/InspectableValue.kt
@@ -140,6 +140,14 @@
  *
  * @sample androidx.compose.ui.samples.InspectableModifierSample
  */
+@Suppress("DeprecatedCallableAddReplaceWith")
+@Deprecated(
+    "This API will create more invalidations of your modifier than necessary, so it's " +
+        "use is discouraged. Implementing the inspectableProperties method on " +
+        "ModifierNodeElement is the recommended zero-cost alternative to exposing properties " +
+        "on a Modifier to tooling.",
+    level = DeprecationLevel.WARNING,
+)
 inline fun Modifier.inspectable(
     noinline inspectorInfo: InspectorInfo.() -> Unit,
     factory: Modifier.() -> Modifier
diff --git a/compose/ui/ui/src/jvmMain/kotlin/androidx/compose/ui/Actual.jvm.kt b/compose/ui/ui/src/jvmMain/kotlin/androidx/compose/ui/Actual.jvm.kt
index 84f9030..f85672e 100644
--- a/compose/ui/ui/src/jvmMain/kotlin/androidx/compose/ui/Actual.jvm.kt
+++ b/compose/ui/ui/src/jvmMain/kotlin/androidx/compose/ui/Actual.jvm.kt
@@ -24,6 +24,10 @@
     return a::class.java === b::class.java
 }
 
+internal actual fun classKeyForObject(a: Any): Any {
+    return a.javaClass
+}
+
 // TODO: For non-JVM platforms, you can revive the kotlin-reflect implementation from
 //  https://android-review.googlesource.com/c/platform/frameworks/support/+/2441379
 internal actual fun InspectorInfo.tryPopulateReflectively(
diff --git a/core/core/lint-baseline.xml b/core/core/lint-baseline.xml
index 2df4e9c..5544e25 100644
--- a/core/core/lint-baseline.xml
+++ b/core/core/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="NewApi"
@@ -579,15 +579,6 @@
 
     <issue
         id="NewApi"
-        message="Class requires API level 26 (current min is 19): `OreoCallback`"
-        errorLine1="        if (callback instanceof OreoCallback &amp;&amp; Build.VERSION.SDK_INT >= 26) {"
-        errorLine2="                                ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/widget/TextViewCompat.java"/>
-    </issue>
-
-    <issue
-        id="NewApi"
         message="Call requires API level 20 (current min is 19): `android.view.View#requestApplyInsets`"
         errorLine1="    post { requestApplyInsets() }"
         errorLine2="           ~~~~~~~~~~~~~~~~~~">
diff --git a/core/core/src/main/java/androidx/core/content/IntentCompat.java b/core/core/src/main/java/androidx/core/content/IntentCompat.java
index b4f7a2a..4cbd632 100644
--- a/core/core/src/main/java/androidx/core/content/IntentCompat.java
+++ b/core/core/src/main/java/androidx/core/content/IntentCompat.java
@@ -200,7 +200,7 @@
 
     /**
      * Retrieve extended data from the intent.
-     *
+     * <p>
      * Compatibility behavior:
      * <ul>
      *     <li>SDK 34 and later, this method matches platform behavior.
@@ -221,6 +221,7 @@
     public static <T> T getParcelableExtra(@NonNull Intent in, @Nullable String name,
             @NonNull Class<T> clazz) {
         if (Build.VERSION.SDK_INT >= 34) {
+            // Don't call this API on SDK 33 due to b/232589966.
             return Api33Impl.getParcelableExtra(in, name, clazz);
         } else {
             T extra = in.getParcelableExtra(name);
@@ -230,7 +231,7 @@
 
     /**
      * Retrieve extended data from the intent.
-     *
+     * <p>
      * Compatibility behavior:
      * <ul>
      *     <li>SDK 34 and later, this method matches platform behavior.
@@ -252,6 +253,7 @@
     public static Parcelable[] getParcelableArrayExtra(@NonNull Intent in, @Nullable String name,
             @NonNull Class<? extends Parcelable> clazz) {
         if (Build.VERSION.SDK_INT >= 34) {
+            // Don't call this API on SDK 33 due to b/232589966.
             return Api33Impl.getParcelableArrayExtra(in, name, clazz);
         } else {
             return in.getParcelableArrayExtra(name);
@@ -260,7 +262,7 @@
 
     /**
      * Retrieve extended data from the intent.
-     *
+     * <p>
      * Compatibility behavior:
      * <ul>
      *     <li>SDK 34 and later, this method matches platform behavior.
@@ -284,6 +286,7 @@
     public static <T> ArrayList<T> getParcelableArrayListExtra(
             @NonNull Intent in, @Nullable String name, @NonNull Class<? extends T> clazz) {
         if (Build.VERSION.SDK_INT >= 34) {
+            // Don't call this API on SDK 33 due to b/232589966.
             return Api33Impl.getParcelableArrayListExtra(in, name, clazz);
         } else {
             return (ArrayList<T>) in.getParcelableArrayListExtra(name);
@@ -314,6 +317,7 @@
     public static <T extends Serializable> T getSerializableExtra(@NonNull Intent in,
             @Nullable String key, @NonNull Class<T> clazz) {
         if (Build.VERSION.SDK_INT >= 34) {
+            // Don't call this API on SDK 33 due to b/232589966.
             return Api33Impl.getSerializableExtra(in, key, clazz);
         } else {
             Serializable serializable = in.getSerializableExtra(key);
diff --git a/development/build_log_simplifier/messages.ignore b/development/build_log_simplifier/messages.ignore
index 6294b28..0c69500 100644
--- a/development/build_log_simplifier/messages.ignore
+++ b/development/build_log_simplifier/messages.ignore
@@ -405,17 +405,18 @@
 WARN: .*\/unzippedJvmSources\/androidx\/webkit\/WebViewCompat\.java:[0-9]+ Missing @param tag for parameter `webview` in DFunction removeWebMessageListener
 WARN: .*\/unzippedJvmSources\/androidx\/work\/testing\/TestListenableWorkerBuilder\.kt:UnknownLine Missing @param tag for parameter `tags` in DFunction TestListenableWorkerBuilder
 WARN: .*\/unzippedJvmSources\/androidx\/work\/testing\/TestWorkerBuilder\.kt:UnknownLine Missing @param tag for parameter `tags` in DFunction TestWorkerBuilder
-WARN: .*\/unzippedJvmSources\/commonJvmAndroidMain\/androidx\/paging\/ItemKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `placeholdersEnabled` in DFunction LoadInitialParams
-WARN: .*\/unzippedJvmSources\/commonJvmAndroidMain\/androidx\/paging\/ItemKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `requestedInitialKey` in DFunction LoadInitialParams
-WARN: .*\/unzippedJvmSources\/commonJvmAndroidMain\/androidx\/paging\/ItemKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `requestedLoadSize` in DFunction LoadInitialParams
-WARN: .*\/unzippedJvmSources\/commonJvmAndroidMain\/androidx\/paging\/ItemKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `key` in DFunction LoadParams
-WARN: .*\/unzippedJvmSources\/commonJvmAndroidMain\/androidx\/paging\/ItemKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `requestedLoadSize` in DFunction LoadParams
-WARN: .*\/unzipped.*\/commonJvmAndroidMain\/androidx\/paging\/PageKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `nextPageKey` in DFunction onResult
-WARN: .*\/unzipped.*\/commonJvmAndroidMain\/androidx\/paging\/PageKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `previousPageKey` in DFunction onResult
-WARN: .*\/unzippedJvmSources\/commonJvmAndroidMain\/androidx\/paging\/PageKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `placeholdersEnabled` in DFunction LoadInitialParams
-WARN: .*\/unzippedJvmSources\/commonJvmAndroidMain\/androidx\/paging\/PageKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `requestedLoadSize` in DFunction LoadInitialParams
-WARN: .*\/unzippedJvmSources\/commonJvmAndroidMain\/androidx\/paging\/PageKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `key` in DFunction LoadParams
-WARN: .*\/unzippedJvmSources\/commonJvmAndroidMain\/androidx\/paging\/PageKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `requestedLoadSize` in DFunction LoadParams
+WARN: .*\/unzippedMultiplatformSources\/commonJvmAndroidMain\/androidx\/paging\/ItemKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `placeholdersEnabled` in DFunction LoadInitialParams
+WARN: .*\/unzippedMultiplatformSources\/commonJvmAndroidMain\/androidx\/paging\/ItemKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `requestedInitialKey` in DFunction LoadInitialParams
+WARN: .*\/unzippedMultiplatformSources\/commonJvmAndroidMain\/androidx\/paging\/ItemKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `requestedLoadSize` in DFunction LoadInitialParams
+WARN: .*\/unzippedMultiplatformSources\/commonJvmAndroidMain\/androidx\/paging\/ItemKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `key` in DFunction LoadParams
+WARN: .*\/unzippedMultiplatformSources\/commonJvmAndroidMain\/androidx\/paging\/ItemKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `requestedLoadSize` in DFunction LoadParams
+WARN: .*\/unzippedMultiplatformSources\/commonJvmAndroidMain\/androidx\/paging\/PageKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `nextPageKey` in DFunction onResult
+WARN: .*\/unzippedMultiplatformSources\/commonJvmAndroidMain\/androidx\/paging\/PageKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `previousPageKey` in DFunction onResult
+WARN: .*\/unzippedMultiplatformSources\/commonJvmAndroidMain\/androidx\/paging\/PageKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `placeholdersEnabled` in DFunction LoadInitialParams
+WARN: .*\/unzippedMultiplatformSources\/commonJvmAndroidMain\/androidx\/paging\/PageKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `requestedLoadSize` in DFunction LoadInitialParams
+WARN: .*\/unzippedMultiplatformSources\/commonJvmAndroidMain\/androidx\/paging\/PageKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `key` in DFunction LoadParams
+WARN: .*\/unzippedMultiplatformSources\/commonJvmAndroidMain\/androidx\/paging\/PageKeyedDataSource\.jvm\.kt:[0-9]+ Missing @param tag for parameter `requestedLoadSize` in DFunction LoadParams
+WARN: .*\/unzippedMultiplatformSources\/commonMain\/androidx\/paging\/LoadState\.kt:[0-9]+ Failed to resolve See androidx\.paging\.PagedList\.retry in DClass Error\. Did you mean androidx\.paging\.PagedList#retry\?
 WARN: .*\/unzippedMultiplatformSources\/androidMain\/androidx\/compose\/animation\/graphics\/res\/AnimatedVectorPainterResources\.android\.kt:[0-9]+ Missing @param tag for parameter `animatedImageVector` in DFunction rememberAnimatedVectorPainter
 WARN: .*\/unzippedMultiplatformSources\/androidMain\/androidx\/compose\/material\/AndroidMenu\.android\.kt:[0-9]+ Missing @param tag for parameter `content` in DFunction DropdownMenuItem
 WARN: .*\/unzippedMultiplatformSources\/androidMain\/androidx\/compose\/ui\/graphics\/AndroidPath\.android\.kt:[0-9]+ Missing @param tag for parameter `operation` in DFunction op
diff --git a/docs-public/build.gradle b/docs-public/build.gradle
index e5a79a8..d61a894 100644
--- a/docs-public/build.gradle
+++ b/docs-public/build.gradle
@@ -201,7 +201,7 @@
     docs("androidx.graphics:graphics-core:1.0.0-beta01")
     samples("androidx.graphics:graphics-core-samples:1.0.0-beta01")
     docs("androidx.graphics:graphics-path:1.0.0-beta02")
-    docs("androidx.graphics:graphics-shapes:1.0.0-alpha05")
+    kmpDocs("androidx.graphics:graphics-shapes:1.0.0-alpha05")
     docs("androidx.gridlayout:gridlayout:1.1.0-beta01")
     docs("androidx.health.connect:connect-client:1.1.0-alpha07")
     samples("androidx.health.connect:connect-client-samples:1.1.0-alpha07")
@@ -292,7 +292,7 @@
     docs("androidx.navigation:navigation-testing:2.8.0-alpha02")
     docs("androidx.navigation:navigation-ui:2.8.0-alpha02")
     docs("androidx.navigation:navigation-ui-ktx:2.8.0-alpha02")
-    docs("androidx.paging:paging-common:3.3.0-alpha03")
+    kmpDocs("androidx.paging:paging-common:3.3.0-alpha03")
     docs("androidx.paging:paging-common-ktx:3.3.0-alpha03")
     kmpDocs("androidx.paging:paging-compose:3.3.0-alpha03")
     samples("androidx.paging:paging-compose-samples:3.3.0-alpha03")
@@ -303,7 +303,7 @@
     docs("androidx.paging:paging-rxjava2-ktx:3.3.0-alpha03")
     docs("androidx.paging:paging-rxjava3:3.3.0-alpha03")
     samples("androidx.paging:paging-samples:3.3.0-alpha03")
-    docs("androidx.paging:paging-testing:3.3.0-alpha03")
+    kmpDocs("androidx.paging:paging-testing:3.3.0-alpha03")
     docs("androidx.palette:palette:1.0.0")
     docs("androidx.palette:palette-ktx:1.0.0")
     docs("androidx.percentlayout:percentlayout:1.0.1")
@@ -358,7 +358,7 @@
     docs("androidx.sqlite:sqlite-ktx:2.4.0")
     docs("androidx.startup:startup-runtime:1.2.0-alpha02")
     docs("androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01")
-    // androidx.test is not hosted in androidx\
+    // androidx.test is not hosted in androidx
     docsWithoutApiSince("androidx.test:core:1.6.0-alpha05")
     docsWithoutApiSince("androidx.test:core-ktx:1.6.0-alpha05")
     docsWithoutApiSince("androidx.test:monitor:1.7.0-alpha04")
@@ -452,7 +452,7 @@
     docs("androidx.window.extensions.core:core:1.0.0")
     docs("androidx.window:window:1.3.0-alpha02")
     stubs(fileTree(dir: "../window/stubs/", include: ["window-sidecar-release-0.1.0-alpha01.aar"]))
-    docs("androidx.window:window-core:1.3.0-alpha02")
+    kmpDocs("androidx.window:window-core:1.3.0-alpha02")
     stubs("androidx.window:window-extensions:1.0.0-alpha01")
     docs("androidx.window:window-java:1.3.0-alpha02")
     docs("androidx.window:window-rxjava2:1.3.0-alpha02")
diff --git a/docs-tip-of-tree/build.gradle b/docs-tip-of-tree/build.gradle
index d4907e5..a630cd4 100644
--- a/docs-tip-of-tree/build.gradle
+++ b/docs-tip-of-tree/build.gradle
@@ -82,9 +82,11 @@
     kmpDocs(project(":compose:foundation:foundation-layout"))
     samples(project(":compose:foundation:foundation-layout:foundation-layout-samples"))
     samples(project(":compose:foundation:foundation:foundation-samples"))
+    kmpDocs(project(":compose:material3:adaptive:adaptive"))
+    kmpDocs(project(":compose:material3:adaptive:adaptive-layout"))
+    kmpDocs(project(":compose:material3:adaptive:adaptive-navigation"))
+    samples(project(":compose:material3:adaptive:adaptive-samples"))
     kmpDocs(project(":compose:material3:material3"))
-    kmpDocs(project(":compose:material3:material3-adaptive"))
-    samples(project(":compose:material3:material3-adaptive:material3-adaptive-samples"))
     kmpDocs(project(":compose:material3:material3-adaptive-navigation-suite"))
     samples(project(":compose:material3:material3-adaptive-navigation-suite:material3-adaptive-navigation-suite-samples"))
     kmpDocs(project(":compose:material3:material3-common"))
diff --git a/external/paparazzi/paparazzi-agent/build.gradle b/external/paparazzi/paparazzi-agent/build.gradle
deleted file mode 100644
index 802d417..0000000
--- a/external/paparazzi/paparazzi-agent/build.gradle
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.LibraryType
-
-plugins {
-    id("AndroidXPlugin")
-    id("kotlin")
-}
-
-dependencies {
-    api(libs.kotlinStdlib)
-    api(libs.junit)
-    implementation(libs.byteBuddy)
-    implementation(libs.byteBuddyAgent)
-    testImplementation(libs.assertj)
-}
-
-androidx {
-    name = "Paparazzi Agent - AndroidX Fork"
-    type = LibraryType.INTERNAL_HOST_TEST_LIBRARY
-}
diff --git a/external/paparazzi/paparazzi-agent/src/main/java/app/cash/paparazzi/agent/AgentTestRule.kt b/external/paparazzi/paparazzi-agent/src/main/java/app/cash/paparazzi/agent/AgentTestRule.kt
deleted file mode 100644
index b79b5d5..0000000
--- a/external/paparazzi/paparazzi-agent/src/main/java/app/cash/paparazzi/agent/AgentTestRule.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package app.cash.paparazzi.agent
-
-import net.bytebuddy.agent.ByteBuddyAgent
-import org.junit.rules.TestRule
-import org.junit.runner.Description
-import org.junit.runners.model.Statement
-
-class AgentTestRule : TestRule {
-  override fun apply(
-    base: Statement,
-    description: Description
-  ) = object : Statement() {
-    override fun evaluate() {
-      ByteBuddyAgent.install()
-      InterceptorRegistrar.registerMethodInterceptors()
-      // interceptors are statically retained until test process finishes, so no need to cleanup
-      base.evaluate()
-    }
-  }
-}
diff --git a/external/paparazzi/paparazzi-agent/src/main/java/app/cash/paparazzi/agent/InterceptorRegistrar.kt b/external/paparazzi/paparazzi-agent/src/main/java/app/cash/paparazzi/agent/InterceptorRegistrar.kt
deleted file mode 100644
index b436835..0000000
--- a/external/paparazzi/paparazzi-agent/src/main/java/app/cash/paparazzi/agent/InterceptorRegistrar.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package app.cash.paparazzi.agent
-
-import net.bytebuddy.ByteBuddy
-import net.bytebuddy.dynamic.loading.ClassReloadingStrategy
-import net.bytebuddy.implementation.MethodDelegation
-import net.bytebuddy.matcher.ElementMatchers
-
-object InterceptorRegistrar {
-  private val byteBuddy = ByteBuddy()
-  private val methodInterceptors = mutableListOf<() -> Unit>()
-
-  fun addMethodInterceptor(
-    receiver: Class<*>,
-    methodName: String,
-    interceptor: Class<*>
-  ) = addMethodInterceptors(receiver, setOf(methodName to interceptor))
-
-  fun addMethodInterceptors(
-    receiver: Class<*>,
-    methodNamesToInterceptors: Set<Pair<String, Class<*>>>
-  ) {
-    methodInterceptors += {
-      var builder = byteBuddy
-        .redefine(receiver)
-
-      methodNamesToInterceptors.forEach {
-        builder = builder
-          .method(ElementMatchers.named(it.first))
-          .intercept(MethodDelegation.to(it.second))
-      }
-
-      builder
-        .make()
-        .load(receiver.classLoader, ClassReloadingStrategy.fromInstalledAgent())
-    }
-  }
-
-  fun registerMethodInterceptors() {
-    methodInterceptors.forEach { it.invoke() }
-  }
-
-  fun clearMethodInterceptors() {
-    methodInterceptors.clear()
-  }
-}
diff --git a/external/paparazzi/paparazzi-agent/src/test/java/app/cash/paparazzi/agent/InterceptorRegistrarTest.kt b/external/paparazzi/paparazzi-agent/src/test/java/app/cash/paparazzi/agent/InterceptorRegistrarTest.kt
deleted file mode 100644
index 1113073..0000000
--- a/external/paparazzi/paparazzi-agent/src/test/java/app/cash/paparazzi/agent/InterceptorRegistrarTest.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-package app.cash.paparazzi.agent
-
-import net.bytebuddy.agent.ByteBuddyAgent
-import org.assertj.core.api.Assertions.assertThat
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-
-class InterceptorRegistrarTest {
-  @Before
-  fun setup() {
-    InterceptorRegistrar.addMethodInterceptors(
-      Utils::class.java,
-      setOf(
-        "log1" to Interceptor1::class.java,
-        "log2" to Interceptor2::class.java
-      )
-    )
-
-    ByteBuddyAgent.install()
-    InterceptorRegistrar.registerMethodInterceptors()
-  }
-
-  @Test
-  fun test() {
-    Utils.log1()
-    Utils.log2()
-
-    assertThat(logs).containsExactly("intercept1", "intercept2")
-  }
-
-  @After
-  fun teardown() {
-    InterceptorRegistrar.clearMethodInterceptors()
-  }
-
-  object Utils {
-    fun log1() {
-      logs += "original1"
-    }
-
-    fun log2() {
-      logs += "original2"
-    }
-  }
-
-  object Interceptor1 {
-    @Suppress("unused")
-    @JvmStatic
-    fun intercept() {
-      logs += "intercept1"
-    }
-  }
-
-  object Interceptor2 {
-    @Suppress("unused")
-    @JvmStatic
-    fun intercept() {
-      logs += "intercept2"
-    }
-  }
-
-  companion object {
-    private val logs = mutableListOf<String>()
-  }
-}
diff --git a/external/paparazzi/paparazzi/build.gradle b/external/paparazzi/paparazzi/build.gradle
deleted file mode 100644
index bc018ac..0000000
--- a/external/paparazzi/paparazzi/build.gradle
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.LibraryType
-import org.gradle.api.artifacts.transform.TransformParameters.None
-import java.util.zip.ZipInputStream
-
-plugins {
-    id("AndroidXPlugin")
-    id("kotlin")
-    id("com.google.devtools.ksp")
-    id("AndroidXComposePlugin")
-}
-
-androidx.configureAarAsJarForConfiguration("compileOnly")
-androidx.configureAarAsJarForConfiguration("testImplementation")
-
-dependencies {
-    api("androidx.annotation:annotation:1.3.0")
-    api("com.android.tools.layoutlib:layoutlib-api:27.2.2")
-    api("com.android.tools:common:27.1.2")
-    api(libs.androidToolsNinepatch)
-    api("com.android.tools:sdk-common:26.6.4")
-    api(libs.guava)
-    api(libs.junit)
-    api(libs.kotlinStdlib)
-    api(libs.kotlinCoroutinesCore)
-    api(libs.kxml2)
-    api(libs.okio)
-    api(libs.paparazziNativeJvm)
-    constraints {
-        implementation(libs.kotlinReflect) {
-            because("sdk-common depends on an old kotlin-reflect")
-        }
-    }
-
-    implementation(project(":external:paparazzi:paparazzi-agent"))
-    implementation(libs.jcodec)
-    implementation(libs.jcodecJavaSe)
-    implementation(libs.moshi)
-    implementation(libs.moshiAdapters)
-
-    compileOnlyAarAsJar("androidx.compose.runtime:runtime:1.2.1")
-    compileOnlyAarAsJar("androidx.compose.ui:ui:1.2.1")
-    compileOnly(project(":lifecycle:lifecycle-common"))
-    compileOnlyAarAsJar(project(":lifecycle:lifecycle-runtime"))
-    compileOnlyAarAsJar("androidx.savedstate:savedstate:1.2.0")
-
-    ksp(libs.moshiCodeGen)
-
-    testImplementation(libs.assertj)
-    testImplementationAarAsJar("androidx.compose.runtime:runtime:1.2.1")
-}
-
-androidx {
-    name = "Paparazzi - AndroidX Fork"
-    type = LibraryType.INTERNAL_HOST_TEST_LIBRARY
-}
\ No newline at end of file
diff --git a/external/paparazzi/paparazzi/lint-baseline.xml b/external/paparazzi/paparazzi/lint-baseline.xml
deleted file mode 100644
index a53cf10..0000000
--- a/external/paparazzi/paparazzi/lint-baseline.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.0.0-beta03" type="baseline" client="gradle" dependencies="false" name="AGP (8.0.0-beta03)" variant="all" version="8.0.0-beta03">
-
-    <issue
-        id="BanThreadSleep"
-        message="Uses Thread.sleep()"
-        errorLine1="      Thread.sleep(100)"
-        errorLine2="             ~~~~~">
-        <location
-            file="src/test/java/app/cash/paparazzi/HtmlReportWriterTest.kt"/>
-    </issue>
-
-</issues>
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/DeviceConfig.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/DeviceConfig.kt
deleted file mode 100644
index 7345548..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/DeviceConfig.kt
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * Copyright (C) 2014 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 app.cash.paparazzi
-
-import com.android.ide.common.rendering.api.HardwareConfig
-import com.android.ide.common.resources.configuration.CountryCodeQualifier
-import com.android.ide.common.resources.configuration.DensityQualifier
-import com.android.ide.common.resources.configuration.FolderConfiguration
-import com.android.ide.common.resources.configuration.KeyboardStateQualifier
-import com.android.ide.common.resources.configuration.LayoutDirectionQualifier
-import com.android.ide.common.resources.configuration.LocaleQualifier
-import com.android.ide.common.resources.configuration.NavigationMethodQualifier
-import com.android.ide.common.resources.configuration.NetworkCodeQualifier
-import com.android.ide.common.resources.configuration.NightModeQualifier
-import com.android.ide.common.resources.configuration.ScreenDimensionQualifier
-import com.android.ide.common.resources.configuration.ScreenOrientationQualifier
-import com.android.ide.common.resources.configuration.ScreenRatioQualifier
-import com.android.ide.common.resources.configuration.ScreenSizeQualifier
-import com.android.ide.common.resources.configuration.TextInputMethodQualifier
-import com.android.ide.common.resources.configuration.TouchScreenQualifier
-import com.android.ide.common.resources.configuration.UiModeQualifier
-import com.android.ide.common.resources.configuration.VersionQualifier
-import com.android.resources.Density
-import com.android.resources.Keyboard
-import com.android.resources.KeyboardState
-import com.android.resources.LayoutDirection
-import com.android.resources.Navigation
-import com.android.resources.NightMode
-import com.android.resources.NightMode.NOTNIGHT
-import com.android.resources.ScreenOrientation
-import com.android.resources.ScreenRatio
-import com.android.resources.ScreenSize
-import com.android.resources.TouchScreen
-import com.android.resources.UiMode
-import com.google.android.collect.Maps
-import java.io.File
-import java.io.FileInputStream
-import java.io.IOException
-import java.util.Properties
-import org.xmlpull.v1.XmlPullParser
-import org.xmlpull.v1.XmlPullParserException
-import org.xmlpull.v1.XmlPullParserFactory
-
-/**
- * Provides [FolderConfiguration] and [HardwareConfig] for various devices. Also provides utility
- * methods to parse `build.prop` and `attrs.xml` to generate the appropriate maps.
- *
- * Defaults are for a Nexus 4 device.
- */
-data class DeviceConfig(
-  val screenHeight: Int = 1280,
-  val screenWidth: Int = 768,
-  val xdpi: Int = 320,
-  val ydpi: Int = 320,
-  val orientation: ScreenOrientation = ScreenOrientation.PORTRAIT,
-  val nightMode: NightMode = NOTNIGHT,
-  val density: Density = Density.XHIGH,
-  val fontScale: Float = 1f,
-  val layoutDirection: LayoutDirection = LayoutDirection.LTR,
-  val locale: String = "en",
-  val ratio: ScreenRatio = ScreenRatio.NOTLONG,
-  val size: ScreenSize = ScreenSize.NORMAL,
-  val keyboard: Keyboard = Keyboard.NOKEY,
-  val touchScreen: TouchScreen = TouchScreen.FINGER,
-  val keyboardState: KeyboardState = KeyboardState.SOFT,
-  val softButtons: Boolean = true,
-  val navigation: Navigation = Navigation.NONAV,
-  val released: String = "November 13, 2012"
-) {
-  val folderConfiguration: FolderConfiguration
-    get() = FolderConfiguration.createDefault()
-      .apply {
-        densityQualifier = DensityQualifier(density)
-        navigationMethodQualifier = NavigationMethodQualifier(navigation)
-        screenDimensionQualifier = when {
-          screenWidth > screenHeight -> ScreenDimensionQualifier(screenWidth, screenHeight)
-          else -> ScreenDimensionQualifier(screenHeight, screenWidth)
-        }
-        screenRatioQualifier = ScreenRatioQualifier(ratio)
-        screenSizeQualifier = ScreenSizeQualifier(size)
-        textInputMethodQualifier = TextInputMethodQualifier(keyboard)
-        touchTypeQualifier = TouchScreenQualifier(touchScreen)
-        keyboardStateQualifier = KeyboardStateQualifier(keyboardState)
-        screenOrientationQualifier = ScreenOrientationQualifier(orientation)
-
-        updateScreenWidthAndHeight()
-        uiModeQualifier = UiModeQualifier(UiMode.NORMAL)
-        nightModeQualifier = NightModeQualifier(nightMode)
-        countryCodeQualifier = CountryCodeQualifier()
-        layoutDirectionQualifier = LayoutDirectionQualifier(layoutDirection)
-        networkCodeQualifier = NetworkCodeQualifier()
-        localeQualifier = LocaleQualifier.getQualifier(locale)
-        versionQualifier = VersionQualifier()
-      }
-
-  val hardwareConfig: HardwareConfig
-    get() = HardwareConfig(
-      screenWidth, screenHeight, density, xdpi.toFloat(), ydpi.toFloat(), size,
-      orientation, null, softButtons
-    )
-
-  /**
-   * Device specs per:
-   * https://android.googlesource.com/platform/tools/base/+/mirror-goog-studio-master-dev/sdklib/src/main/java/com/android/sdklib/devices/nexus.xml
-   *
-   * Release dates obtained from Wikipedia.
-   */
-
-  companion object {
-    @JvmField
-    val NEXUS_4 = DeviceConfig()
-
-    @JvmField
-    val NEXUS_5 = DeviceConfig(
-      screenHeight = 1920,
-      screenWidth = 1080,
-      xdpi = 445,
-      ydpi = 445,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.XXHIGH,
-      ratio = ScreenRatio.NOTLONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "October 31, 2013"
-    )
-
-    @JvmField
-    val NEXUS_7 = DeviceConfig(
-      screenHeight = 1920,
-      screenWidth = 1200,
-      xdpi = 323,
-      ydpi = 323,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.XHIGH,
-      ratio = ScreenRatio.NOTLONG,
-      size = ScreenSize.LARGE,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "July 26, 2013"
-    )
-
-    @JvmField
-    val NEXUS_10 = DeviceConfig(
-      screenHeight = 1600,
-      screenWidth = 2560,
-      xdpi = 300,
-      ydpi = 300,
-      orientation = ScreenOrientation.LANDSCAPE,
-      density = Density.XHIGH,
-      ratio = ScreenRatio.NOTLONG,
-      size = ScreenSize.XLARGE,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "November 13, 2012"
-    )
-
-    @JvmField
-    val NEXUS_5_LAND = DeviceConfig(
-      screenHeight = 1080,
-      screenWidth = 1920,
-      xdpi = 445,
-      ydpi = 445,
-      orientation = ScreenOrientation.LANDSCAPE,
-      density = Density.XXHIGH,
-      ratio = ScreenRatio.NOTLONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "October 31, 2013"
-    )
-
-    @JvmField
-    val NEXUS_7_2012 = DeviceConfig(
-      screenHeight = 1280,
-      screenWidth = 800,
-      xdpi = 195,
-      ydpi = 200,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.TV,
-      ratio = ScreenRatio.NOTLONG,
-      size = ScreenSize.LARGE,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "July 13, 2012"
-    )
-
-    @JvmField
-    val PIXEL_C = DeviceConfig(
-      screenHeight = 1800,
-      screenWidth = 2560,
-      xdpi = 308,
-      ydpi = 308,
-      orientation = ScreenOrientation.LANDSCAPE,
-      density = Density.XHIGH,
-      ratio = ScreenRatio.NOTLONG,
-      size = ScreenSize.XLARGE,
-      keyboard = Keyboard.QWERTY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "December 8, 2015"
-    )
-
-    @JvmField
-    val PIXEL = DeviceConfig(
-      screenHeight = 1920,
-      screenWidth = 1080,
-      xdpi = 440,
-      ydpi = 440,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_420,
-      ratio = ScreenRatio.NOTLONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "October 20, 2016"
-    )
-
-    @JvmField
-    val PIXEL_XL = DeviceConfig(
-      screenHeight = 2560,
-      screenWidth = 1440,
-      xdpi = 534,
-      ydpi = 534,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_560,
-      ratio = ScreenRatio.NOTLONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "October 20, 2016"
-    )
-
-    @JvmField
-    val PIXEL_2 = DeviceConfig(
-      screenHeight = 1920,
-      screenWidth = 1080,
-      xdpi = 442,
-      ydpi = 443,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_420,
-      ratio = ScreenRatio.NOTLONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "October 19, 2017"
-    )
-
-    @JvmField
-    val PIXEL_2_XL = DeviceConfig(
-      screenHeight = 2880,
-      screenWidth = 1440,
-      xdpi = 537,
-      ydpi = 537,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_560,
-      ratio = ScreenRatio.LONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "October 19, 2017"
-    )
-
-    @JvmField
-    val PIXEL_3 = DeviceConfig(
-      screenHeight = 2160,
-      screenWidth = 1080,
-      xdpi = 442,
-      ydpi = 442,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_440,
-      ratio = ScreenRatio.LONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "October 18, 2018"
-    )
-
-    @JvmField
-    val PIXEL_3_XL = DeviceConfig(
-      screenHeight = 2960,
-      screenWidth = 1440,
-      xdpi = 522,
-      ydpi = 522,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_560,
-      ratio = ScreenRatio.LONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "October 18, 2018"
-    )
-
-    @JvmField
-    val PIXEL_3A = DeviceConfig(
-      screenHeight = 2220,
-      screenWidth = 1080,
-      xdpi = 442,
-      ydpi = 444,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_440,
-      ratio = ScreenRatio.LONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "May 7, 2019"
-    )
-
-    @JvmField
-    val PIXEL_3A_XL = DeviceConfig(
-      screenHeight = 2160,
-      screenWidth = 1080,
-      xdpi = 397,
-      ydpi = 400,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_400,
-      ratio = ScreenRatio.LONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "May 7, 2019"
-    )
-
-    @JvmField
-    val PIXEL_4 = DeviceConfig(
-      screenHeight = 2280,
-      screenWidth = 1080,
-      xdpi = 444,
-      ydpi = 444,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_440,
-      ratio = ScreenRatio.LONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "October 24, 2019"
-    )
-
-    @JvmField
-    val PIXEL_4_XL = DeviceConfig(
-      screenHeight = 3040,
-      screenWidth = 1440,
-      xdpi = 537,
-      ydpi = 537,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_560,
-      ratio = ScreenRatio.LONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "October 24, 2019"
-    )
-
-    @JvmField
-    val PIXEL_4A = DeviceConfig(
-      screenHeight = 2340,
-      screenWidth = 1080,
-      xdpi = 442,
-      ydpi = 444,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_440,
-      ratio = ScreenRatio.LONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "August 20, 2020"
-    )
-
-    @JvmField
-    val PIXEL_5 = DeviceConfig(
-      screenHeight = 2340,
-      screenWidth = 1080,
-      xdpi = 442,
-      ydpi = 444,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_440,
-      ratio = ScreenRatio.LONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "October 15, 2020"
-    )
-
-    @JvmField
-    val PIXEL_6 = DeviceConfig(
-      screenHeight = 2400,
-      screenWidth = 1080,
-      xdpi = 406,
-      ydpi = 411,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_420,
-      ratio = ScreenRatio.LONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "October 28, 2021"
-    )
-
-    @JvmField
-    val PIXEL_6_PRO = DeviceConfig(
-      screenHeight = 3120,
-      screenWidth = 1440,
-      xdpi = 512,
-      ydpi = 512,
-      orientation = ScreenOrientation.PORTRAIT,
-      density = Density.DPI_560,
-      ratio = ScreenRatio.LONG,
-      size = ScreenSize.NORMAL,
-      keyboard = Keyboard.NOKEY,
-      touchScreen = TouchScreen.FINGER,
-      keyboardState = KeyboardState.SOFT,
-      softButtons = true,
-      navigation = Navigation.NONAV,
-      released = "October 28, 2021"
-    )
-
-    private const val TAG_ATTR = "attr"
-    private const val TAG_ENUM = "enum"
-    private const val TAG_FLAG = "flag"
-    private const val ATTR_NAME = "name"
-    private const val ATTR_VALUE = "value"
-
-    @Throws(IOException::class)
-    fun loadProperties(path: File): Map<String, String> {
-      val p = Properties()
-      val map = Maps.newHashMap<String, String>()
-      p.load(FileInputStream(path))
-      for (key in p.stringPropertyNames()) {
-        map[key] = p.getProperty(key)
-      }
-      return map
-    }
-
-    @Throws(IOException::class, XmlPullParserException::class)
-    fun getEnumMap(path: File): Map<String, Map<String, Int>> {
-      val map = mutableMapOf<String, MutableMap<String, Int>>()
-
-      val xmlPullParser = XmlPullParserFactory.newInstance()
-        .newPullParser()
-      xmlPullParser.setInput(FileInputStream(path), null)
-      var eventType = xmlPullParser.eventType
-      var attr: String? = null
-      while (eventType != XmlPullParser.END_DOCUMENT) {
-        if (eventType == XmlPullParser.START_TAG) {
-          if (TAG_ATTR == xmlPullParser.name) {
-            attr = xmlPullParser.getAttributeValue(null, ATTR_NAME)
-          } else if (TAG_ENUM == xmlPullParser.name || TAG_FLAG == xmlPullParser.name) {
-            val name = xmlPullParser.getAttributeValue(null, ATTR_NAME)
-            val value = xmlPullParser.getAttributeValue(null, ATTR_VALUE)
-            // Integer.decode cannot handle "ffffffff", see JDK issue 6624867
-            val i = (java.lang.Long.decode(value) as Long).toInt()
-            require(attr != null)
-            var attributeMap: MutableMap<String, Int>? = map[attr]
-            if (attributeMap == null) {
-              attributeMap = Maps.newHashMap()
-              map[attr] = attributeMap
-            }
-            attributeMap!![name] = i
-          }
-        } else if (eventType == XmlPullParser.END_TAG) {
-          if (TAG_ATTR == xmlPullParser.name) {
-            attr = null
-          }
-        }
-        eventType = xmlPullParser.next()
-      }
-
-      return map
-    }
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Environment.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Environment.kt
deleted file mode 100644
index 8cfae19..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Environment.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2019 Square, Inc.
- *
- * 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 app.cash.paparazzi
-
-import java.io.File
-import java.io.FileNotFoundException
-import java.nio.file.Path
-import java.nio.file.Paths
-import java.util.Locale
-import kotlin.io.path.exists
-
-data class Environment(
-  val platformDir: String,
-  val appTestDir: String,
-  val resDir: String,
-  val assetsDir: String,
-  val compileSdkVersion: Int,
-  val resourcePackageNames: List<String>
-) {
-  init {
-    val platformDirPath = Path.of(platformDir)
-    if (!platformDirPath.exists()) {
-      val elements = platformDirPath.nameCount
-      val platform = platformDirPath.subpath(elements - 1, elements)
-      val platformVersion = platform.toString().split("-").last()
-      throw FileNotFoundException(
-        "Missing platform version $platformVersion. " +
-            "Install with sdkmanager --install \"platforms;$platform\""
-      )
-    }
-  }
-}
-
-@Suppress("unused")
-fun androidHome() = System.getenv("ANDROID_SDK_ROOT")
-  ?: System.getenv("ANDROID_HOME")
-  ?: androidSdkPath()
-
-fun detectEnvironment(): Environment {
-  checkInstalledJvm()
-
-  val resourcesFile = File(System.getProperty("paparazzi.test.resources"))
-  val configLines = resourcesFile.readLines()
-
-  val appTestDir = Paths.get(System.getProperty("user.dir"))
-  val androidHome = Paths.get(androidHome())
-  return Environment(
-    platformDir = androidHome.resolve(configLines[3]).toString(),
-    appTestDir = appTestDir.toString(),
-    resDir = appTestDir.resolve(configLines[1]).toString(),
-    assetsDir = appTestDir.resolve(configLines[4]).toString(),
-    compileSdkVersion = configLines[2].toInt(),
-    resourcePackageNames = configLines[5].split(",")
-  )
-}
-
-private fun androidSdkPath(): String {
-  val osName = System.getProperty("os.name").lowercase(Locale.US)
-  val sdkPathDir = if (osName.startsWith("windows")) {
-    "\\AppData\\Local\\Android\\Sdk"
-  } else if (osName.startsWith("mac")) {
-    "/Library/Android/sdk"
-  } else {
-    "/Android/Sdk"
-  }
-  val homeDir = System.getProperty("user.home")
-  return homeDir + sdkPathDir
-}
-
-private fun checkInstalledJvm() {
-  val feature = try {
-    // Runtime#version() only available as of Java 9.
-    val version = Runtime::class.java.getMethod("version").invoke(null)
-    // Runtime.Version#feature() only available as of Java 10.
-    version.javaClass.getMethod("feature").invoke(version) as Int
-  } catch (e: NoSuchMethodException) {
-    -1
-  }
-
-  if (feature < 11) {
-    throw IllegalStateException(
-      "Unsupported JRE detected! Please install and run Paparazzi test suites on JDK 11+."
-    )
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Flags.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Flags.kt
deleted file mode 100644
index 62c0b62..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Flags.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package app.cash.paparazzi
-
-object Flags {
-  const val DEBUG_LINKED_OBJECTS = "app.cash.paparazzi.debug.linked.objects"
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/HtmlReportWriter.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/HtmlReportWriter.kt
deleted file mode 100644
index c43f4fb..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/HtmlReportWriter.kt
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2019 Square, Inc.
- *
- * 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 app.cash.paparazzi
-
-import app.cash.paparazzi.SnapshotHandler.FrameHandler
-import app.cash.paparazzi.internal.PaparazziJson
-import com.google.common.base.CharMatcher
-import java.awt.image.BufferedImage
-import java.io.File
-import java.text.SimpleDateFormat
-import java.util.Date
-import java.util.Locale
-import java.util.UUID
-import javax.imageio.ImageIO
-import okio.BufferedSink
-import okio.HashingSink
-import okio.blackholeSink
-import okio.buffer
-import okio.sink
-import okio.source
-import org.jcodec.api.awt.AWTSequenceEncoder
-
-/**
- * Creates an HTML report that avoids writing files that have already been written.
- *
- * Images and videos are named by hashes of their contents. Paparazzi won't write two images or videos with the same
- * contents. Note that the images/ directory includes the individual frames of each video.
- *
- * Runs are named by their date.
- *
- * ```
- * images
- *   088c60580f06efa95c37fd8e754074729ee74a06.png
- *   93f9a81cb594280f4b3898d90dfad8c8ea969b01.png
- *   22d37abd0841ba2a8d0bd635954baf7cbfaa269b.png
- *   a4769e43cc5901ef28c0d46c46a44ea6429cbccc.png
- * videos
- *   d1cddc5da2224053f2af51f4e69a76de4e61fc41.mov
- * runs
- *   20190626002322_b9854e.js
- *   20190626002345_b1e882.js
- * index.html
- * index.js
- * paparazzi.js
- * ```
- */
-class HtmlReportWriter @JvmOverloads constructor(
-  private val runName: String = defaultRunName(),
-  private val rootDirectory: File = File("build/reports/paparazzi"),
-  snapshotRootDirectory: File = File("src/test/snapshots")
-) : SnapshotHandler {
-  private val runsDirectory: File = File(rootDirectory, "runs")
-  private val imagesDirectory: File = File(rootDirectory, "images")
-  private val videosDirectory: File = File(rootDirectory, "videos")
-
-  private val goldenImagesDirectory = File(snapshotRootDirectory, "images")
-  private val goldenVideosDirectory = File(snapshotRootDirectory, "videos")
-
-  private val shots = mutableListOf<Snapshot>()
-
-  private val isRecording: Boolean =
-    System.getProperty("paparazzi.test.record")?.toBoolean() == true
-
-  init {
-    runsDirectory.mkdirs()
-    imagesDirectory.mkdirs()
-    videosDirectory.mkdirs()
-    writeStaticFiles()
-    writeRunJs()
-    writeIndexJs()
-  }
-
-  override fun newFrameHandler(
-    snapshot: Snapshot,
-    frameCount: Int,
-    fps: Int
-  ): FrameHandler {
-    return object : FrameHandler {
-      val hashes = mutableListOf<String>()
-
-      override fun handle(image: BufferedImage) {
-        hashes += writeImage(image)
-      }
-
-      override fun close() {
-        if (hashes.isEmpty()) return
-
-        val shot = if (hashes.size == 1) {
-          val original = File(imagesDirectory, "${hashes[0]}.png")
-          if (isRecording) {
-            val goldenFile = File(goldenImagesDirectory, snapshot.toFileName("_", "png"))
-            original.copyTo(goldenFile, overwrite = true)
-          }
-          snapshot.copy(file = original.toJsonPath())
-        } else {
-          val hash = writeVideo(hashes, fps)
-
-          if (isRecording) {
-            for ((index, frameHash) in hashes.withIndex()) {
-              val originalFrame = File(imagesDirectory, "$frameHash.png")
-              val frameSnapshot = snapshot.copy(name = "${snapshot.name} $index")
-              val goldenFile = File(goldenImagesDirectory, frameSnapshot.toFileName("_", "png"))
-              if (!goldenFile.exists()) {
-                originalFrame.copyTo(goldenFile)
-              }
-            }
-          }
-          val original = File(videosDirectory, "$hash.mov")
-          if (isRecording) {
-            val goldenFile = File(goldenVideosDirectory, snapshot.toFileName("_", "mov"))
-            if (!goldenFile.exists()) {
-              original.copyTo(goldenFile)
-            }
-          }
-          snapshot.copy(file = original.toJsonPath())
-        }
-
-        shots += shot
-      }
-    }
-  }
-
-  /** Returns the hash of the image. */
-  private fun writeImage(image: BufferedImage): String {
-    val hash = hash(image)
-    val file = File(imagesDirectory, "$hash.png")
-    if (!file.exists()) {
-      file.writeAtomically(image)
-    }
-    return hash
-  }
-
-  /** Returns a SHA-1 hash of the pixels of [image]. */
-  private fun hash(image: BufferedImage): String {
-    val hashingSink = HashingSink.sha1(blackholeSink())
-    hashingSink.buffer().use { sink ->
-      for (y in 0 until image.height) {
-        for (x in 0 until image.width) {
-          sink.writeInt(image.getRGB(x, y))
-        }
-      }
-    }
-    return hashingSink.hash.hex()
-  }
-
-  private fun writeVideo(
-    frameHashes: List<String>,
-    fps: Int
-  ): String {
-    val hash = hash(frameHashes)
-    val file = File(videosDirectory, "$hash.mov")
-    if (!file.exists()) {
-      val tmpFile = File(videosDirectory, "$hash.mov.tmp")
-      val encoder = AWTSequenceEncoder.createSequenceEncoder(tmpFile, fps)
-      for (frameHash in frameHashes) {
-        val frame = ImageIO.read(File(imagesDirectory, "$frameHash.png"))
-        encoder.encodeImage(frame)
-      }
-      encoder.finish()
-      tmpFile.renameTo(file)
-    }
-    return hash
-  }
-
-  /** Returns a SHA-1 hash of [lines]. */
-  private fun hash(lines: List<String>): String {
-    val hashingSink = HashingSink.sha1(blackholeSink())
-    hashingSink.buffer().use { sink ->
-      for (hash in lines) {
-        sink.writeUtf8(hash)
-        sink.writeUtf8("\n")
-      }
-    }
-    return hashingSink.hash.hex()
-  }
-
-  /** Release all resources and block until everything has been written to the file system. */
-  override fun close() {
-    writeRunJs()
-  }
-
-  /**
-   * Emits the all runs index, which reads like JSON with an executable header.
-   *
-   * ```
-   * window.all_runs = [
-   *   "20190319153912aaab",
-   *   "20190319153917bcfe"
-   * ];
-   * ```
-   */
-  private fun writeIndexJs() {
-    val runNames = mutableListOf<String>()
-    val runs = runsDirectory.list().sorted()
-    for (run in runs) {
-      if (run.endsWith(".js")) {
-        runNames += run.substring(0, run.length - 3)
-      }
-    }
-
-    File(rootDirectory, "index.js").writeAtomically {
-      writeUtf8("window.all_runs = ")
-      PaparazziJson.listOfStringsAdapter.toJson(this, runNames)
-      writeUtf8(";")
-    }
-  }
-
-  /**
-   * Emits a run index, which reads like JSON with an executable header.
-   *
-   * ```
-   * window.runs["20190319153912aaab"] = [
-   *   {
-   *     "name": "loading",
-   *     "testName": "app.cash.CelebrityTest#testSettings",
-   *     "timestamp": "2019-03-20T10:27:43Z",
-   *     "tags": ["redesign"],
-   *     "file": "loading.png"
-   *   },
-   *   {
-   *     "name": "error",
-   *     "testName": "app.cash.CelebrityTest#testSettings",
-   *     "timestamp": "2019-03-20T10:27:43Z",
-   *     "tags": ["redesign"],
-   *     "file": "error.png"
-   *   }
-   * ];
-   * ```
-   */
-  private fun writeRunJs() {
-    val runJs = File(runsDirectory, "${runName.sanitizeForFilename()}.js")
-    runJs.writeAtomically {
-      writeUtf8("window.runs[\"$runName\"] = ")
-      PaparazziJson.listOfShotsAdapter.toJson(this, shots)
-      writeUtf8(";")
-    }
-  }
-
-  private fun writeStaticFiles() {
-    for (staticFile in listOf("index.html", "paparazzi.js")) {
-      File(rootDirectory, staticFile).writeAtomically {
-        writeAll(HtmlReportWriter::class.java.classLoader.getResourceAsStream(staticFile).source())
-      }
-    }
-  }
-
-  private fun File.writeAtomically(bufferedImage: BufferedImage) {
-    val tmpFile = File(parentFile, "$name.tmp")
-    ImageIO.write(bufferedImage, "PNG", tmpFile)
-    delete()
-    tmpFile.renameTo(this)
-  }
-
-  private fun File.writeAtomically(writerAction: BufferedSink.() -> Unit) {
-    val tmpFile = File(parentFile, "$name.tmp")
-    tmpFile.sink()
-      .buffer()
-      .use { sink ->
-        sink.writerAction()
-      }
-    delete()
-    tmpFile.renameTo(this)
-  }
-
-  private fun File.toJsonPath(): String = relativeTo(rootDirectory).invariantSeparatorsPath
-}
-
-internal fun defaultRunName(): String {
-  val now = Date()
-  val timestamp = SimpleDateFormat("yyyyMMddHHmmss", Locale.US).format(now)
-  val token = UUID.randomUUID().toString().substring(0, 6)
-  return "${timestamp}_$token"
-}
-
-internal val filenameSafeChars = CharMatcher.inRange('a', 'z')
-  .or(CharMatcher.inRange('0', '9'))
-  .or(CharMatcher.anyOf("_-.~@^()[]{}:;,"))
-
-internal fun String.sanitizeForFilename(): String? {
-  return filenameSafeChars.negate().replaceFrom(lowercase(Locale.US), '_')
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Paparazzi.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Paparazzi.kt
deleted file mode 100644
index 2c9dec41..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Paparazzi.kt
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * Copyright (C) 2019 Square, Inc.
- *
- * 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 app.cash.paparazzi
-
-import android.animation.AnimationHandler
-import android.content.Context
-import android.content.res.Resources
-import android.graphics.Bitmap
-import android.os.Handler_Delegate
-import android.os.SystemClock_Delegate
-import android.util.AttributeSet
-import android.util.DisplayMetrics
-import android.view.BridgeInflater
-import android.view.Choreographer
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.view.ViewGroup.LayoutParams
-import android.widget.FrameLayout
-import androidx.annotation.LayoutRes
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.platform.ComposeView
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.LifecycleOwner
-import androidx.lifecycle.LifecycleRegistry
-import androidx.lifecycle.setViewTreeLifecycleOwner
-import androidx.savedstate.SavedStateRegistry
-import androidx.savedstate.SavedStateRegistryController
-import androidx.savedstate.SavedStateRegistryOwner
-import androidx.savedstate.setViewTreeSavedStateRegistryOwner
-import app.cash.paparazzi.agent.AgentTestRule
-import app.cash.paparazzi.agent.InterceptorRegistrar
-import app.cash.paparazzi.internal.ChoreographerDelegateInterceptor
-import app.cash.paparazzi.internal.EditModeInterceptor
-import app.cash.paparazzi.internal.IInputMethodManagerInterceptor
-import app.cash.paparazzi.internal.ImageUtils
-import app.cash.paparazzi.internal.MatrixMatrixMultiplicationInterceptor
-import app.cash.paparazzi.internal.MatrixVectorMultiplicationInterceptor
-import app.cash.paparazzi.internal.PaparazziCallback
-import app.cash.paparazzi.internal.PaparazziLogger
-import app.cash.paparazzi.internal.Renderer
-import app.cash.paparazzi.internal.ResourcesInterceptor
-import app.cash.paparazzi.internal.ServiceManagerInterceptor
-import app.cash.paparazzi.internal.SessionParamsBuilder
-import app.cash.paparazzi.internal.parsers.LayoutPullParser
-import com.android.ide.common.rendering.api.RenderSession
-import com.android.ide.common.rendering.api.Result
-import com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN
-import com.android.ide.common.rendering.api.SessionParams
-import com.android.ide.common.rendering.api.SessionParams.RenderingMode
-import com.android.internal.lang.System_Delegate
-import com.android.layoutlib.bridge.Bridge
-import com.android.layoutlib.bridge.Bridge.cleanupThread
-import com.android.layoutlib.bridge.Bridge.prepareThread
-import com.android.layoutlib.bridge.BridgeRenderSession
-import com.android.layoutlib.bridge.impl.RenderAction
-import com.android.layoutlib.bridge.impl.RenderSessionImpl
-import java.awt.image.BufferedImage
-import java.util.Date
-import java.util.concurrent.TimeUnit
-import org.junit.rules.TestRule
-import org.junit.runner.Description
-import org.junit.runners.model.Statement
-
-class Paparazzi @JvmOverloads constructor(
-  private val environment: Environment = detectEnvironment(),
-  private val deviceConfig: DeviceConfig = DeviceConfig.NEXUS_5,
-  private val theme: String = "android:Theme.Material.NoActionBar.Fullscreen",
-  private val renderingMode: RenderingMode = RenderingMode.NORMAL,
-  private val appCompatEnabled: Boolean = true,
-  private val maxPercentDifference: Double = 0.1,
-  private val snapshotHandler: SnapshotHandler = determineHandler(maxPercentDifference),
-  private val renderExtensions: Set<RenderExtension> = setOf()
-) : TestRule {
-  private val logger = PaparazziLogger()
-  private lateinit var renderSession: RenderSessionImpl
-  private lateinit var bridgeRenderSession: RenderSession
-  private var testName: TestName? = null
-
-  val layoutInflater: LayoutInflater
-    get() = RenderAction.getCurrentContext().getSystemService("layout_inflater") as BridgeInflater
-
-  val resources: Resources
-    get() = RenderAction.getCurrentContext().resources
-
-  val context: Context
-    get() = RenderAction.getCurrentContext()
-
-  /**
-   * The root layout that test views will be placed into. The FrameLayout is dynamically set to
-   * `wrap_content` if the `renderMode` is `RenderingMode.SizeAction.SHRINK` in the appropriate
-   * direction, otherwise it is set to `match_parent`.
-   */
-  private val contentRoot = """
-        |<?xml version="1.0" encoding="utf-8"?>
-        |<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        |              android:layout_width="${renderingMode.horizAction.toAttrValue()}"
-        |              android:layout_height="${renderingMode.vertAction.toAttrValue()}"/>
-  """.trimMargin()
-
-  private fun RenderingMode.SizeAction.toAttrValue() =
-    if (this == RenderingMode.SizeAction.SHRINK) "wrap_content" else "match_parent"
-
-  override fun apply(
-    base: Statement,
-    description: Description
-  ): Statement {
-    val statement = object : Statement() {
-      override fun evaluate() {
-        prepare(description)
-        try {
-          base.evaluate()
-        } finally {
-          close()
-          logger.assertNoErrors()
-        }
-      }
-    }
-
-    return if (!isInitialized) {
-      registerFontLookupInterceptionIfResourceCompatDetected()
-      registerViewEditModeInterception()
-      registerMatrixMultiplyInterception()
-      registerChoreographerDelegateInterception()
-      registerServiceManagerInterception()
-      registerIInputMethodManagerInterception()
-
-      val outerRule = AgentTestRule()
-      outerRule.apply(statement, description)
-    } else {
-      statement
-    }
-  }
-
-  fun prepare(description: Description) {
-    forcePlatformSdkVersion(environment.compileSdkVersion)
-
-    val layoutlibCallback = PaparazziCallback(logger, environment.resourcePackageNames)
-    layoutlibCallback.initResources()
-
-    testName = description.toTestName()
-
-    if (!isInitialized) {
-      renderer = Renderer(environment, layoutlibCallback, logger, maxPercentDifference)
-      sessionParamsBuilder = renderer.prepare()
-    }
-
-    sessionParamsBuilder = sessionParamsBuilder
-      .copy(
-        layoutPullParser = LayoutPullParser.createFromString(contentRoot),
-        deviceConfig = deviceConfig,
-        renderingMode = renderingMode
-      )
-      .withTheme(theme)
-
-    val sessionParams = sessionParamsBuilder.build()
-    renderSession = createRenderSession(sessionParams)
-    prepareThread()
-    renderSession.init(sessionParams.timeout)
-    Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEVICE_STABLE)
-
-    // requires LayoutInflater to be created, which is a side-effect of RenderSessionImpl.init()
-    if (appCompatEnabled) {
-      initializeAppCompatIfPresent()
-    }
-
-    bridgeRenderSession = createBridgeSession(renderSession, renderSession.inflate())
-  }
-
-  fun close() {
-    testName = null
-    renderSession.release()
-    bridgeRenderSession.dispose()
-    cleanupThread()
-    snapshotHandler.close()
-
-    renderer.dumpDelegates()
-  }
-
-  @Suppress("UNCHECKED_CAST")
-  fun <V : View> inflate(@LayoutRes layoutId: Int): V =
-    layoutInflater.inflate(layoutId, null) as V
-
-  fun snapshot(name: String? = null, composable: @Composable () -> Unit) {
-    val hostView = ComposeView(context)
-    // During onAttachedToWindow, AbstractComposeView will attempt to resolve its parent's
-    // CompositionContext, which requires first finding the "content view", then using that to
-    // find a root view with a ViewTreeLifecycleOwner
-    val parent = FrameLayout(context).apply { id = android.R.id.content }
-    parent.addView(
-      hostView,
-      renderingMode.horizAction.toLayoutParams(),
-      renderingMode.vertAction.toLayoutParams()
-    )
-    PaparazziComposeOwner.register(parent)
-    hostView.setContent(composable)
-
-    try {
-      snapshot(parent, name)
-    } finally {
-      forceReleaseComposeReferenceLeaks()
-    }
-  }
-
-  private fun RenderingMode.SizeAction.toLayoutParams() =
-    if (this == RenderingMode.SizeAction.SHRINK) {
-      LayoutParams.WRAP_CONTENT
-    } else {
-      LayoutParams.MATCH_PARENT
-    }
-
-  @JvmOverloads
-  fun snapshot(view: View, name: String? = null) {
-    takeSnapshots(view, name, 0, -1, 1)
-  }
-
-  @JvmOverloads
-  fun gif(
-    view: View,
-    name: String? = null,
-    start: Long = 0L,
-    end: Long = 500L,
-    fps: Int = 30
-  ) {
-    // Add one to the frame count so we get the last frame. Otherwise a 1 second, 60 FPS animation
-    // our 60th frame will be at time 983 ms, and we want our last frame to be 1,000 ms. This gets
-    // us 61 frames for a 1 second animation, 121 frames for a 2 second animation, etc.
-    val durationMillis = (end - start).toInt()
-    val frameCount = (durationMillis * fps) / 1000 + 1
-    val startNanos = TimeUnit.MILLISECONDS.toNanos(start)
-    takeSnapshots(view, name, startNanos, fps, frameCount)
-  }
-
-  fun unsafeUpdateConfig(
-    deviceConfig: DeviceConfig? = null,
-    theme: String? = null,
-    renderingMode: RenderingMode? = null
-  ) {
-    require(deviceConfig != null || theme != null || renderingMode != null) {
-      "Calling unsafeUpdateConfig requires at least one non-null argument."
-    }
-
-    renderSession.release()
-    bridgeRenderSession.dispose()
-    cleanupThread()
-
-    sessionParamsBuilder = sessionParamsBuilder
-      .copy(
-        // Required to reset underlying parser stream
-        layoutPullParser = LayoutPullParser.createFromString(contentRoot)
-      )
-
-    if (deviceConfig != null) {
-      sessionParamsBuilder = sessionParamsBuilder.copy(deviceConfig = deviceConfig)
-    }
-
-    if (theme != null) {
-      sessionParamsBuilder = sessionParamsBuilder.withTheme(theme)
-    }
-
-    if (renderingMode != null) {
-      sessionParamsBuilder = sessionParamsBuilder.copy(renderingMode = renderingMode)
-    }
-
-    val sessionParams = sessionParamsBuilder.build()
-    renderSession = createRenderSession(sessionParams)
-    prepareThread()
-    renderSession.init(sessionParams.timeout)
-    Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEVICE_STABLE)
-    bridgeRenderSession = createBridgeSession(renderSession, renderSession.inflate())
-  }
-
-  private fun takeSnapshots(
-    view: View,
-    name: String?,
-    startNanos: Long,
-    fps: Int,
-    frameCount: Int
-  ) {
-    val snapshot = Snapshot(name, testName!!, Date())
-
-    val frameHandler = snapshotHandler.newFrameHandler(snapshot, frameCount, fps)
-    frameHandler.use {
-      val viewGroup = bridgeRenderSession.rootViews[0].viewObject as ViewGroup
-      val modifiedView = renderExtensions.fold(view) { view, renderExtension ->
-        renderExtension.renderView(view)
-      }
-
-      System_Delegate.setBootTimeNanos(0L)
-      try {
-        withTime(0L) {
-          // Initialize the choreographer at time=0.
-        }
-
-        viewGroup.addView(modifiedView)
-        for (frame in 0 until frameCount) {
-          val nowNanos = (startNanos + (frame * 1_000_000_000.0 / fps)).toLong()
-          withTime(nowNanos) {
-            val result = renderSession.render(true)
-            if (result.status == ERROR_UNKNOWN) {
-              throw result.exception
-            }
-
-            val image = bridgeRenderSession.image
-            frameHandler.handle(scaleImage(image))
-          }
-        }
-      } finally {
-        viewGroup.removeView(modifiedView)
-        AnimationHandler.sAnimatorHandler.set(null)
-      }
-    }
-  }
-
-  private fun withTime(
-    timeNanos: Long,
-    block: () -> Unit
-  ) {
-    val frameNanos = TIME_OFFSET_NANOS + timeNanos
-
-    // Execute the block at the requested time.
-    System_Delegate.setNanosTime(frameNanos)
-
-    val choreographer = Choreographer.getInstance()
-    val areCallbacksRunningField = choreographer::class.java.getDeclaredField("mCallbacksRunning")
-    areCallbacksRunningField.isAccessible = true
-
-    try {
-      areCallbacksRunningField.setBoolean(choreographer, true)
-
-      // https://android.googlesource.com/platform/frameworks/layoutlib/+/d58aa4703369e109b24419548f38b422d5a44738/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java#171
-      // BridgeRenderSession.executeCallbacks aggressively tears down the main Looper and BridgeContext, so we call the static delegates ourselves.
-      Handler_Delegate.executeCallbacks()
-      val currentTimeMs = SystemClock_Delegate.uptimeMillis()
-      val choreographerCallbacks =
-        RenderAction.getCurrentContext().sessionInteractiveData.choreographerCallbacks
-      choreographerCallbacks.execute(currentTimeMs, Bridge.getLog())
-
-      block()
-    } catch (e: Throwable) {
-      Bridge.getLog().error("broken", "Failed executing Choreographer#doFrame", e, null, null)
-      throw e
-    } finally {
-      areCallbacksRunningField.setBoolean(choreographer, false)
-    }
-  }
-
-  private fun createRenderSession(sessionParams: SessionParams): RenderSessionImpl {
-    val renderSession = RenderSessionImpl(sessionParams)
-    renderSession.setElapsedFrameTimeNanos(0L)
-    RenderSessionImpl::class.java
-      .getDeclaredField("mFirstFrameExecuted")
-      .apply {
-        isAccessible = true
-        set(renderSession, true)
-      }
-    return renderSession
-  }
-
-  private fun createBridgeSession(
-    renderSession: RenderSessionImpl,
-    result: Result
-  ): BridgeRenderSession {
-    try {
-      val bridgeSessionClass = Class.forName("com.android.layoutlib.bridge.BridgeRenderSession")
-      val constructor =
-        bridgeSessionClass.getDeclaredConstructor(RenderSessionImpl::class.java, Result::class.java)
-      constructor.isAccessible = true
-      return constructor.newInstance(renderSession, result) as BridgeRenderSession
-    } catch (e: Exception) {
-      throw RuntimeException(e)
-    }
-  }
-
-  private fun scaleImage(image: BufferedImage): BufferedImage {
-    val scale = ImageUtils.getThumbnailScale(image)
-    // Only scale images down so we don't waste storage space enlarging smaller layouts.
-    return if (scale < 1f) ImageUtils.scale(image, scale, scale) else image
-  }
-
-  private fun Description.toTestName(): TestName {
-    val fullQualifiedName = className
-    val packageName = fullQualifiedName.substringBeforeLast('.', missingDelimiterValue = "")
-    val className = fullQualifiedName.substringAfterLast('.')
-    return TestName(packageName, className, methodName)
-  }
-
-  private fun forcePlatformSdkVersion(compileSdkVersion: Int) {
-    val buildVersionClass = try {
-      Paparazzi::class.java.classLoader.loadClass("android.os.Build\$VERSION")
-    } catch (e: ClassNotFoundException) {
-      // Project unit tests don't load Android platform code
-      return
-    }
-    buildVersionClass
-      .getFieldReflectively("SDK_INT")
-      .setStaticValue(compileSdkVersion)
-  }
-
-  private fun initializeAppCompatIfPresent() {
-    lateinit var appCompatDelegateClass: Class<*>
-    try {
-      // See androidx.appcompat.widget.AppCompatDrawableManager#preload()
-      val appCompatDrawableManagerClass =
-        Class.forName("androidx.appcompat.widget.AppCompatDrawableManager")
-      val preloadMethod = appCompatDrawableManagerClass.getMethod("preload")
-      preloadMethod.invoke(null)
-
-      appCompatDelegateClass = Class.forName("androidx.appcompat.app.AppCompatDelegate")
-    } catch (e: ClassNotFoundException) {
-      logger.verbose("AppCompat not found on classpath")
-      return
-    }
-
-    // See androidx.appcompat.app.AppCompatDelegateImpl#installViewFactory()
-    if (layoutInflater.factory == null) {
-      layoutInflater.factory2 = object : LayoutInflater.Factory2 {
-        override fun onCreateView(
-          parent: View?,
-          name: String,
-          context: Context,
-          attrs: AttributeSet
-        ): View? {
-          val appCompatViewInflaterClass =
-            Class.forName("androidx.appcompat.app.AppCompatViewInflater")
-
-          val createViewMethod = appCompatViewInflaterClass
-            .getDeclaredMethod(
-              "createView",
-              View::class.java,
-              String::class.java,
-              Context::class.java,
-              AttributeSet::class.java,
-              Boolean::class.javaPrimitiveType,
-              Boolean::class.javaPrimitiveType,
-              Boolean::class.javaPrimitiveType,
-              Boolean::class.javaPrimitiveType
-            )
-            .apply { isAccessible = true }
-
-          val inheritContext = true
-          val readAndroidTheme = true
-          val readAppTheme = true
-          val wrapContext = true
-
-          val newAppCompatViewInflaterInstance = appCompatViewInflaterClass
-            .getConstructor()
-            .newInstance()
-
-          return createViewMethod.invoke(
-            newAppCompatViewInflaterInstance, parent, name, context, attrs,
-            inheritContext, readAndroidTheme, readAppTheme, wrapContext
-          ) as View?
-        }
-
-        override fun onCreateView(
-          name: String,
-          context: Context,
-          attrs: AttributeSet
-        ): View? = onCreateView(null, name, context, attrs)
-      }
-    } else {
-      if (!appCompatDelegateClass.isAssignableFrom(layoutInflater.factory2::class.java)) {
-        throw IllegalStateException(
-          "The LayoutInflater already has a Factory installed so we can not install AppCompat's"
-        )
-      }
-    }
-  }
-
-  /**
-   * Current workaround for supporting custom fonts when constructing views in code. This check
-   * may be used or expanded to support other cases requiring similar method interception
-   * techniques.
-   *
-   * See:
-   * https://github.com/cashapp/paparazzi/issues/119
-   * https://issuetracker.google.com/issues/156065472
-   */
-  private fun registerFontLookupInterceptionIfResourceCompatDetected() {
-    try {
-      val resourcesCompatClass = Class.forName("androidx.core.content.res.ResourcesCompat")
-      InterceptorRegistrar.addMethodInterceptor(
-        resourcesCompatClass,
-        "getFont",
-        ResourcesInterceptor::class.java
-      )
-    } catch (e: ClassNotFoundException) {
-      logger.verbose("ResourceCompat not found on classpath")
-    }
-  }
-
-  private fun registerServiceManagerInterception() {
-    val serviceManager = Class.forName("android.os.ServiceManager")
-    InterceptorRegistrar.addMethodInterceptor(
-      serviceManager,
-      "getServiceOrThrow",
-      ServiceManagerInterceptor::class.java
-    )
-  }
-
-  private fun registerIInputMethodManagerInterception() {
-    val iimm = Class.forName("com.android.internal.view.IInputMethodManager\$Stub")
-    InterceptorRegistrar.addMethodInterceptor(
-      iimm,
-      "asInterface",
-      IInputMethodManagerInterceptor::class.java
-    )
-  }
-
-  private fun registerViewEditModeInterception() {
-    val viewClass = Class.forName("android.view.View")
-    InterceptorRegistrar.addMethodInterceptor(
-      viewClass,
-      "isInEditMode",
-      EditModeInterceptor::class.java
-    )
-  }
-
-  private fun registerMatrixMultiplyInterception() {
-    val matrixClass = Class.forName("android.opengl.Matrix")
-    InterceptorRegistrar.addMethodInterceptors(
-      matrixClass,
-      setOf(
-        "multiplyMM" to MatrixMatrixMultiplicationInterceptor::class.java,
-        "multiplyMV" to MatrixVectorMultiplicationInterceptor::class.java
-      )
-    )
-  }
-
-  private fun registerChoreographerDelegateInterception() {
-    val choreographerDelegateClass = Class.forName("android.view.Choreographer_Delegate")
-    InterceptorRegistrar.addMethodInterceptor(
-      choreographerDelegateClass,
-      "getFrameTimeNanos",
-      ChoreographerDelegateInterceptor::class.java
-    )
-  }
-
-  private fun forceReleaseComposeReferenceLeaks() {
-    // AndroidUiDispatcher is backed by a Handler, by executing one last time
-    // we give the dispatcher the ability to clean-up / release its callbacks.
-    executeHandlerCallbacks()
-  }
-
-  private fun executeHandlerCallbacks() {
-    // Avoid ConcurrentModificationException in
-    // RenderAction.currentContext.sessionInteractiveData.handlerMessageQueue.runnablesMap which is a WeakHashMap
-    // https://android.googlesource.com/platform/tools/adt/idea/+/c331c9b2f4334748c55c29adec3ad1cd67e45df2/designer/src/com/android/tools/idea/uibuilder/scene/LayoutlibSceneManager.java#1558
-    synchronized(this) {
-      // https://android.googlesource.com/platform/frameworks/layoutlib/+/d58aa4703369e109b24419548f38b422d5a44738/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java#171
-      // BridgeRenderSession.executeCallbacks aggressively tears down the main Looper and BridgeContext, so we call the static delegates ourselves.
-      Handler_Delegate.executeCallbacks()
-    }
-  }
-
-  private class PaparazziComposeOwner private constructor() :
-    LifecycleOwner, SavedStateRegistryOwner {
-    private val lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this)
-    private val savedStateRegistryController = SavedStateRegistryController.create(this)
-
-    override val lifecycle: Lifecycle
-      get() = lifecycleRegistry
-    override val savedStateRegistry: SavedStateRegistry =
-      savedStateRegistryController.savedStateRegistry
-
-    companion object {
-      fun register(view: View) {
-        val owner = PaparazziComposeOwner()
-        owner.savedStateRegistryController.performRestore(null)
-        owner.lifecycleRegistry.currentState = Lifecycle.State.CREATED
-        view.setViewTreeLifecycleOwner(owner)
-        view.setViewTreeSavedStateRegistryOwner(owner)
-      }
-    }
-  }
-
-  companion object {
-    /** The choreographer doesn't like 0 as a frame time, so start an hour later. */
-    internal val TIME_OFFSET_NANOS = TimeUnit.HOURS.toNanos(1L)
-
-    internal lateinit var renderer: Renderer
-    internal val isInitialized get() = ::renderer.isInitialized
-
-    internal lateinit var sessionParamsBuilder: SessionParamsBuilder
-
-    private val isVerifying: Boolean =
-      System.getProperty("paparazzi.test.verify")?.toBoolean() == true
-
-    private fun determineHandler(maxPercentDifference: Double): SnapshotHandler =
-      if (isVerifying) {
-        SnapshotVerifier(maxPercentDifference)
-      } else {
-        HtmlReportWriter()
-      }
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Reflections.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Reflections.kt
deleted file mode 100644
index 15617f0..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Reflections.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-package app.cash.paparazzi
-
-import java.lang.reflect.Field
-import java.lang.reflect.Modifier
-import java.security.PrivilegedAction
-import sun.misc.Unsafe
-
-/**
- * Inspired by and ported from:
- * https://github.com/powermock/powermock/commit/fc092c5d7e339d01e079184a2a0e88b5c46fc0e8
- * https://github.com/powermock/powermock/commit/bd92bcc5329c4981cf09dece5c3eafcf92fe49ff
- */
-internal fun Class<*>.getFieldReflectively(fieldName: String): Field =
-  try {
-    this.getDeclaredField(fieldName).also { it.isAccessible = true }
-  } catch (e: NoSuchFieldException) {
-    throw RuntimeException("Field '$fieldName' was not found in class $name.")
-  }
-
-internal fun Field.setStaticValue(value: Any) {
-  try {
-    this.isAccessible = true
-    val isFinalModifierPresent = this.modifiers and Modifier.FINAL == Modifier.FINAL
-    if (isFinalModifierPresent) {
-      @Suppress("DEPRECATION")
-      java.security.AccessController.doPrivileged<Any?>(
-        PrivilegedAction {
-          try {
-            val unsafe = Unsafe::class.java.getFieldReflectively("theUnsafe").get(null) as Unsafe
-            val offset = unsafe.staticFieldOffset(this)
-            val base = unsafe.staticFieldBase(this)
-            unsafe.setFieldValue(this, base, offset, value)
-            null
-          } catch (t: Throwable) {
-            throw RuntimeException(t)
-          }
-        }
-      )
-    } else {
-      this.set(null, value)
-    }
-  } catch (ex: SecurityException) {
-    throw RuntimeException(ex)
-  } catch (ex: IllegalAccessException) {
-    throw RuntimeException(ex)
-  } catch (ex: IllegalArgumentException) {
-    throw RuntimeException(ex)
-  }
-}
-
-internal fun Unsafe.setFieldValue(field: Field, base: Any, offset: Long, value: Any) =
-  when (field.type) {
-    Integer.TYPE -> this.putInt(base, offset, (value as Int))
-    java.lang.Short.TYPE -> this.putShort(base, offset, (value as Short))
-    java.lang.Long.TYPE -> this.putLong(base, offset, (value as Long))
-    java.lang.Byte.TYPE -> this.putByte(base, offset, (value as Byte))
-    java.lang.Boolean.TYPE -> this.putBoolean(base, offset, (value as Boolean))
-    java.lang.Float.TYPE -> this.putFloat(base, offset, (value as Float))
-    java.lang.Double.TYPE -> this.putDouble(base, offset, (value as Double))
-    Character.TYPE -> this.putChar(base, offset, (value as Char))
-    else -> this.putObject(base, offset, value)
-  }
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/RenderExtension.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/RenderExtension.kt
deleted file mode 100644
index d0d12b2..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/RenderExtension.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2021 Square, Inc.
- *
- * 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 app.cash.paparazzi
-
-import android.view.View
-
-/**
- * An extension for overlaying additional information on top of each rendered frame.
- */
-interface RenderExtension {
-  /**
-   * Allows this extension to modify the view hierarchy represented by [contentView].
-   *
-   * Returns the root view of the modified hierarchy.
-   */
-  fun renderView(contentView: View): View
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Snapshot.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Snapshot.kt
deleted file mode 100644
index 85501f7..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/Snapshot.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2019 Square, Inc.
- *
- * 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 app.cash.paparazzi
-
-import com.squareup.moshi.JsonClass
-import java.util.Date
-import java.util.Locale
-
-@JsonClass(generateAdapter = true)
-data class Snapshot(
-  val name: String?,
-  val testName: TestName,
-  val timestamp: Date,
-  val tags: List<String> = listOf(),
-  val file: String? = null
-)
-
-internal fun Snapshot.toFileName(
-  delimiter: String = "_",
-  extension: String
-): String {
-  val formattedLabel = if (name != null) {
-    "$delimiter${name.lowercase(Locale.US).replace("\\s".toRegex(), delimiter)}"
-  } else {
-    ""
-  }
-  return "${testName.packageName}${delimiter}${testName.className}" +
-      "${delimiter}${testName.methodName}$formattedLabel.$extension"
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/SnapshotHandler.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/SnapshotHandler.kt
deleted file mode 100644
index 5067f25..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/SnapshotHandler.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2019 Square, Inc.
- *
- * 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 app.cash.paparazzi
-
-import java.awt.image.BufferedImage
-import java.io.Closeable
-
-interface SnapshotHandler : Closeable {
-  fun newFrameHandler(
-    snapshot: Snapshot,
-    frameCount: Int,
-    fps: Int
-  ): FrameHandler
-
-  interface FrameHandler : Closeable {
-    fun handle(image: BufferedImage)
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/SnapshotVerifier.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/SnapshotVerifier.kt
deleted file mode 100644
index 564cd2e..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/SnapshotVerifier.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2020 Square, Inc.
- *
- * 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 app.cash.paparazzi
-
-import app.cash.paparazzi.SnapshotHandler.FrameHandler
-import app.cash.paparazzi.internal.ImageUtils
-import java.awt.image.BufferedImage
-import java.io.File
-import javax.imageio.ImageIO
-
-class SnapshotVerifier @JvmOverloads constructor(
-  private val maxPercentDifference: Double,
-  rootDirectory: File = File("src/test/snapshots")
-) : SnapshotHandler {
-  private val imagesDirectory: File = File(rootDirectory, "images")
-  private val videosDirectory: File = File(rootDirectory, "videos")
-
-  init {
-    imagesDirectory.mkdirs()
-    videosDirectory.mkdirs()
-  }
-
-  override fun newFrameHandler(
-    snapshot: Snapshot,
-    frameCount: Int,
-    fps: Int
-  ): FrameHandler {
-    return object : FrameHandler {
-      override fun handle(image: BufferedImage) {
-        // Note: does not handle videos or its frames at the moment
-        val expected = File(imagesDirectory, snapshot.toFileName(extension = "png"))
-        if (!expected.exists()) {
-          throw AssertionError("File $expected does not exist")
-        }
-
-        val goldenImage = ImageIO.read(expected)
-        ImageUtils.assertImageSimilar(
-          relativePath = expected.path,
-          image = image,
-          goldenImage = goldenImage,
-          maxPercentDifferent = maxPercentDifference
-        )
-      }
-
-      override fun close() = Unit
-    }
-  }
-
-  override fun close() = Unit
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/TestName.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/TestName.kt
deleted file mode 100644
index 2ab7963..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/TestName.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2019 Square, Inc.
- *
- * 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 app.cash.paparazzi
-
-data class TestName(
-  val packageName: String,
-  val className: String,
-  val methodName: String
-)
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/accessibility/AccessibilityRenderExtension.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/accessibility/AccessibilityRenderExtension.kt
deleted file mode 100644
index f6f16aa..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/accessibility/AccessibilityRenderExtension.kt
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2021 Square, Inc.
- *
- * 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 app.cash.paparazzi.accessibility
-
-import android.graphics.drawable.GradientDrawable
-import android.graphics.drawable.LayerDrawable
-import android.util.TypedValue
-import android.view.View
-import android.view.ViewGroup
-import android.widget.LinearLayout
-import android.widget.TextView
-import app.cash.paparazzi.RenderExtension
-import app.cash.paparazzi.accessibility.RenderSettings.DEFAULT_DESCRIPTION_BACKGROUND_COLOR
-import app.cash.paparazzi.accessibility.RenderSettings.DEFAULT_RECT_SIZE
-import app.cash.paparazzi.accessibility.RenderSettings.DEFAULT_RENDER_ALPHA
-import app.cash.paparazzi.accessibility.RenderSettings.DEFAULT_TEXT_COLOR
-import app.cash.paparazzi.accessibility.RenderSettings.DEFAULT_TEXT_SIZE
-import app.cash.paparazzi.accessibility.RenderSettings.getColor
-import app.cash.paparazzi.accessibility.RenderSettings.toColorInt
-import app.cash.paparazzi.accessibility.RenderSettings.withAlpha
-
-class AccessibilityRenderExtension : RenderExtension {
-  override fun renderView(
-    contentView: View
-  ): View {
-    val accessibilityViews = contentView.findAccessibilityViews()
-    accessibilityViews.forEach { view ->
-      val color = getColor(view)
-      val colorInt = color.toColorInt()
-
-      val colorDrawable = GradientDrawable(
-        GradientDrawable.Orientation.TOP_BOTTOM,
-        intArrayOf(colorInt, colorInt)
-      ).apply {
-        setStroke(2, color.withAlpha(DEFAULT_RENDER_ALPHA * 2).toColorInt())
-      }
-
-      view.foreground = view.foreground?.let { drawable ->
-        // If there is an existing foreground layer the color on top of it.
-        LayerDrawable(arrayOf(drawable, colorDrawable))
-      } ?: colorDrawable
-    }
-
-    return LinearLayout(contentView.context).apply {
-      orientation = LinearLayout.HORIZONTAL
-      weightSum = 2f
-      layoutParams = ViewGroup.LayoutParams(
-        ViewGroup.LayoutParams.MATCH_PARENT,
-        ViewGroup.LayoutParams.MATCH_PARENT
-      )
-
-      val contentLayoutParams = contentView.layoutParams ?: generateLayoutParams(null)
-      addView(
-        contentView,
-        LinearLayout.LayoutParams(
-          contentLayoutParams.width,
-          contentLayoutParams.height,
-          1f
-        )
-      )
-      addView(
-        buildAccessibilityView(contentView),
-        LinearLayout.LayoutParams(
-          ViewGroup.LayoutParams.MATCH_PARENT,
-          ViewGroup.LayoutParams.MATCH_PARENT,
-          1f
-        )
-      )
-    }
-  }
-
-  private fun View.findAccessibilityViews(): List<View> {
-    val accessibilityViews = mutableListOf<View>()
-    if (isImportantForAccessibility && !iterableTextForAccessibility.isNullOrBlank()) {
-      accessibilityViews.add(this)
-    }
-
-    if (this is ViewGroup) {
-      (0 until childCount).forEach {
-        accessibilityViews += getChildAt(it).findAccessibilityViews()
-      }
-    }
-
-    return accessibilityViews
-  }
-
-  private fun buildAccessibilityView(contentView: View): View {
-    val linearLayout = LinearLayout(contentView.context).apply {
-      orientation = LinearLayout.VERTICAL
-      setBackgroundColor(DEFAULT_DESCRIPTION_BACKGROUND_COLOR.toColorInt())
-    }
-
-    fun renderAccessibility(view: View) {
-      if (view.isImportantForAccessibility && !view.iterableTextForAccessibility.isNullOrBlank()) {
-        linearLayout.addView(buildAccessibilityRow(view, view.iterableTextForAccessibility))
-      }
-
-      if (view is ViewGroup) {
-        (0 until view.childCount).forEach {
-          renderAccessibility(view.getChildAt(it))
-        }
-      }
-    }
-
-    renderAccessibility(contentView)
-    return linearLayout
-  }
-
-  private fun buildAccessibilityRow(view: View, iterableTextForAccessibility: CharSequence): View {
-    val context = view.context
-    val color = getColor(view).toColorInt()
-    val margin = view.dip(8)
-    val innerMargin = view.dip(4)
-
-    return LinearLayout(context).apply {
-      orientation = LinearLayout.HORIZONTAL
-      layoutParams = ViewGroup.LayoutParams(
-        ViewGroup.LayoutParams.MATCH_PARENT,
-        ViewGroup.LayoutParams.WRAP_CONTENT
-      )
-      setPaddingRelative(margin, innerMargin, margin, innerMargin)
-
-      addView(
-        View(context).apply {
-          layoutParams = ViewGroup.LayoutParams(dip(DEFAULT_RECT_SIZE), dip(DEFAULT_RECT_SIZE))
-          background = GradientDrawable(
-            GradientDrawable.Orientation.TOP_BOTTOM,
-            intArrayOf(color, color)
-          ).apply {
-            cornerRadius = dip(DEFAULT_RECT_SIZE / 4f)
-          }
-          setPaddingRelative(innerMargin, innerMargin, innerMargin, innerMargin)
-        }
-      )
-      addView(
-        TextView(context).apply {
-          layoutParams = ViewGroup.LayoutParams(
-            ViewGroup.LayoutParams.MATCH_PARENT,
-            ViewGroup.LayoutParams.WRAP_CONTENT
-          )
-          text = iterableTextForAccessibility
-          textSize = DEFAULT_TEXT_SIZE
-          setTextColor(DEFAULT_TEXT_COLOR.toColorInt())
-          setPaddingRelative(innerMargin, 0, innerMargin, 0)
-        }
-      )
-    }
-  }
-}
-
-private fun View.dip(value: Float): Float =
-  TypedValue.applyDimension(
-    TypedValue.COMPLEX_UNIT_DIP,
-    value,
-    resources.displayMetrics
-  )
-
-private fun View.dip(value: Int): Int = dip(value.toFloat()).toInt()
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/accessibility/RenderSettings.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/accessibility/RenderSettings.kt
deleted file mode 100644
index 768fc6e..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/accessibility/RenderSettings.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2021 Square, Inc.
- *
- * 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 app.cash.paparazzi.accessibility
-
-import android.view.View
-import java.awt.Color
-
-internal object RenderSettings {
-  const val DEFAULT_RENDER_ALPHA = 40
-  val DEFAULT_RENDER_COLORS = listOf(
-    Color.RED,
-    Color.GREEN,
-    Color.BLUE,
-    Color.YELLOW,
-    Color.ORANGE,
-    Color.MAGENTA,
-    Color.CYAN,
-    Color.PINK
-  )
-  val DEFAULT_TEXT_COLOR: Color = Color.BLACK
-  val DEFAULT_DESCRIPTION_BACKGROUND_COLOR: Color = Color.WHITE
-  const val DEFAULT_TEXT_SIZE: Float = 10f
-  const val DEFAULT_RECT_SIZE: Int = 16
-
-  private val colorMap = mutableMapOf<Int, Color>()
-
-  fun getColor(view: View): Color {
-    val key = "${view::class.simpleName}(${view.iterableTextForAccessibility})"
-    return getColor(key)
-  }
-
-  private fun getColor(key: String): Color {
-    val hashCode = key.hashCode()
-    return colorMap.getOrPut(hashCode) {
-      nextColor(hashCode).withAlpha(DEFAULT_RENDER_ALPHA)
-    }
-  }
-
-  private fun nextColor(hashCode: Int): Color {
-    return DEFAULT_RENDER_COLORS[colorIndex(hashCode)]
-  }
-
-  private fun colorIndex(hashCode: Int): Int {
-    val size = DEFAULT_RENDER_COLORS.size
-    val i = hashCode % size
-    return if (i < 0) i + size else i
-  }
-
-  internal fun Color.toColorInt(): Int =
-    android.graphics.Color.argb(alpha, red, green, blue)
-
-  internal fun Color.withAlpha(alpha: Int): Color {
-    return Color(red, green, blue, alpha)
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/ChoreographerDelegateInterceptor.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/ChoreographerDelegateInterceptor.kt
deleted file mode 100644
index 57b7bf1..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/ChoreographerDelegateInterceptor.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package app.cash.paparazzi.internal
-
-import android.view.Choreographer
-import com.android.internal.lang.System_Delegate
-
-object ChoreographerDelegateInterceptor {
-  @Suppress("unused")
-  @JvmStatic
-  fun intercept(
-    @Suppress("UNUSED_PARAMETER") choreographer: Choreographer
-  ): Long = System_Delegate.nanoTime()
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/EditModeInterceptor.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/EditModeInterceptor.kt
deleted file mode 100644
index c464a04..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/EditModeInterceptor.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package app.cash.paparazzi.internal
-
-object EditModeInterceptor {
-  @JvmStatic
-  fun intercept(): Boolean = false
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/Gc.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/Gc.kt
deleted file mode 100644
index 5bbd25c..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/Gc.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2016 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 app.cash.paparazzi.internal
-
-import java.lang.ref.WeakReference
-
-internal object Gc {
-  fun gc() {
-    // See RuntimeUtil#gc in jlibs (http://jlibs.in/)
-    var obj: Any? = Any()
-    val ref = WeakReference<Any>(obj)
-
-    @Suppress("UNUSED_VAlUE")
-    obj = null
-    while (ref.get() != null) {
-      System.gc()
-      System.runFinalization()
-    }
-
-    System.gc()
-    System.runFinalization()
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/IInputMethodManagerInterceptor.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/IInputMethodManagerInterceptor.kt
deleted file mode 100644
index 1908949..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/IInputMethodManagerInterceptor.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package app.cash.paparazzi.internal
-
-import android.os.IBinder
-import com.android.internal.view.IInputMethodManager
-
-/**
- * With [ServiceManagerInterceptor] returning null for the service, we must override the logic
- * in [com.android.internal.view.IInputMethodManager.Stub.asInterface] to return the default
- * implementation of [IInputMethodManager].
- */
-object IInputMethodManagerInterceptor {
-  @Suppress("unused")
-  @JvmStatic
-  fun interceptAsInterface(@Suppress("UNUSED_PARAMETER") obj: IBinder?): IInputMethodManager =
-    IInputMethodManager.Default()
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/ImageUtils.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/ImageUtils.kt
deleted file mode 100644
index 8e7111c..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/ImageUtils.kt
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (C) 2016 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 app.cash.paparazzi.internal
-
-import java.awt.AlphaComposite
-import java.awt.Color
-import java.awt.Graphics2D
-import java.awt.RenderingHints.KEY_ANTIALIASING
-import java.awt.RenderingHints.KEY_INTERPOLATION
-import java.awt.RenderingHints.KEY_RENDERING
-import java.awt.RenderingHints.VALUE_ANTIALIAS_ON
-import java.awt.RenderingHints.VALUE_INTERPOLATION_BILINEAR
-import java.awt.RenderingHints.VALUE_RENDER_QUALITY
-import java.awt.image.BufferedImage
-import java.awt.image.BufferedImage.TYPE_INT_ARGB
-import java.io.File
-import java.io.File.separatorChar
-import java.io.IOException
-import javax.imageio.ImageIO
-import kotlin.math.max
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertTrue
-import org.junit.Assert.fail
-
-/**
- * Utilities related to image processing.
- */
-internal object ImageUtils {
-  /**
-   * Normally, this test will fail when there is a missing thumbnail. However, when
-   * you create creating a new test, it's useful to be able to turn this off such that
-   * you can generate all the missing thumbnails in one go, rather than having to run
-   * the test repeatedly to get to each new render assertion generating its thumbnail.
-   */
-  private val FAIL_ON_MISSING_THUMBNAIL = true
-
-  private const val THUMBNAIL_SIZE = 1000
-
-  /** Directory where to write the thumbnails and deltas. */
-  private val failureDir: File
-    get() {
-      val workingDirString = System.getProperty("user.dir")
-      val failureDir = File(workingDirString, "out/failures")
-      failureDir.mkdirs()
-      return failureDir
-    }
-
-  @Throws(IOException::class)
-  fun requireSimilar(
-    relativePath: String,
-    image: BufferedImage,
-    maxPercentDifference: Double
-  ) {
-    val scale = getThumbnailScale(image)
-    val thumbnail = scale(image, scale, scale)
-
-    val `is` = ImageUtils::class.java.classLoader.getResourceAsStream(relativePath)
-    if (`is` ==
-      null
-    ) {
-      var message = "Unable to load golden thumbnail: $relativePath\n"
-      message = saveImageAndAppendMessage(thumbnail, message, relativePath)
-      if (FAIL_ON_MISSING_THUMBNAIL) {
-        fail(message)
-      } else {
-        println(message)
-      }
-    } else {
-      try {
-        val goldenImage = ImageIO.read(`is`)
-        assertImageSimilar(
-          relativePath,
-          goldenImage,
-          thumbnail,
-          maxPercentDifference
-        )
-      } finally {
-        `is`.close()
-      }
-    }
-  }
-
-  @Throws(IOException::class)
-  fun assertImageSimilar(
-    relativePath: String,
-    goldenImage: BufferedImage,
-    image: BufferedImage,
-    maxPercentDifferent: Double
-  ) {
-    @Suppress("NAME_SHADOWING") var goldenImage = goldenImage
-    if (goldenImage.type != TYPE_INT_ARGB) {
-      val temp = BufferedImage(
-        goldenImage.width,
-        goldenImage.height,
-        TYPE_INT_ARGB
-      )
-      temp.graphics.drawImage(goldenImage, 0, 0, null)
-      goldenImage = temp
-    }
-    assertEquals(TYPE_INT_ARGB.toLong(), goldenImage.type.toLong())
-
-    val imageWidth = Math.min(goldenImage.width, image.width)
-    val imageHeight = Math.min(goldenImage.height, image.height)
-
-    // Blur the images to account for the scenarios where there are pixel
-    // differences
-    // in where a sharp edge occurs
-    // goldenImage = blur(goldenImage, 6);
-    // image = blur(image, 6);
-
-    val width = 3 * imageWidth
-    val deltaImage = BufferedImage(width, imageHeight, TYPE_INT_ARGB)
-    val g = deltaImage.graphics
-
-    // Compute delta map
-    var delta: Long = 0
-    for (y in 0 until imageHeight) {
-      for (x in 0 until imageWidth) {
-        val goldenRgb = goldenImage.getRGB(x, y)
-        val rgb = image.getRGB(x, y)
-        if (goldenRgb == rgb) {
-          deltaImage.setRGB(imageWidth + x, y, 0x00808080)
-          continue
-        }
-
-        // If the pixels have no opacity, don't delta colors at all
-        if (goldenRgb and -0x1000000 == 0 && rgb and -0x1000000 == 0) {
-          deltaImage.setRGB(imageWidth + x, y, 0x00808080)
-          continue
-        }
-
-        val deltaR = (rgb and 0xFF0000).ushr(16) - (goldenRgb and 0xFF0000).ushr(16)
-        val newR = 128 + deltaR and 0xFF
-        val deltaG = (rgb and 0x00FF00).ushr(8) - (goldenRgb and 0x00FF00).ushr(8)
-        val newG = 128 + deltaG and 0xFF
-        val deltaB = (rgb and 0x0000FF) - (goldenRgb and 0x0000FF)
-        val newB = 128 + deltaB and 0xFF
-
-        val avgAlpha =
-          ((goldenRgb and -0x1000000).ushr(24) + (rgb and -0x1000000).ushr(24)) / 2 shl 24
-
-        val newRGB = avgAlpha or (newR shl 16) or (newG shl 8) or newB
-        deltaImage.setRGB(imageWidth + x, y, newRGB)
-
-        delta += Math.abs(deltaR)
-          .toLong()
-        delta += Math.abs(deltaG)
-          .toLong()
-        delta += Math.abs(deltaB)
-          .toLong()
-      }
-    }
-
-    // 3 different colors, 256 color levels
-    val total = imageHeight.toLong() * imageWidth.toLong() * 3L * 256L
-    val percentDifference = (delta * 100 / total.toDouble()).toFloat()
-
-    var error: String? = null
-    val imageName = getName(relativePath)
-    if (percentDifference > maxPercentDifferent) {
-      error = String.format("Images differ (by %.1f%%)", percentDifference)
-    } else if (Math.abs(goldenImage.width - image.width) >= 2) {
-      error = "Widths differ too much for " + imageName + ": " +
-        goldenImage.width + "x" + goldenImage.height +
-        "vs" + image.width + "x" + image.height
-    } else if (Math.abs(goldenImage.height - image.height) >= 2) {
-      error = "Heights differ too much for " + imageName + ": " +
-        goldenImage.width + "x" + goldenImage.height +
-        "vs" + image.width + "x" + image.height
-    }
-
-    if (error != null) {
-      // Expected on the left
-      // Golden on the right
-      g.drawImage(goldenImage, 0, 0, null)
-      g.drawImage(image, 2 * imageWidth, 0, null)
-
-      // Labels
-      if (imageWidth > 80) {
-        g.color = Color.RED
-        g.drawString("Expected", 10, 20)
-        g.drawString("Actual", 2 * imageWidth + 10, 20)
-      }
-
-      val output = File(failureDir, "delta-$imageName")
-      if (output.exists()) {
-        val deleted = output.delete()
-        assertTrue(deleted)
-      }
-      ImageIO.write(deltaImage, "PNG", output)
-      error += " - see details in file://" + output.path + "\n"
-      error = saveImageAndAppendMessage(image, error, relativePath)
-      println(error)
-      fail(error)
-    }
-
-    g.dispose()
-  }
-
-  /**
-   * Resize the given image
-   *
-   * @param source the image to be scaled
-   * @param xScale x scale
-   * @param yScale y scale
-   * @return the scaled image
-   */
-  fun scale(
-    source: BufferedImage,
-    xScale: Double,
-    yScale: Double
-  ): BufferedImage {
-    @Suppress("NAME_SHADOWING") var source = source
-
-    var sourceWidth = source.width
-    var sourceHeight = source.height
-    val destWidth = Math.max(1, (xScale * sourceWidth).toInt())
-    val destHeight = Math.max(1, (yScale * sourceHeight).toInt())
-    var imageType = source.type
-    if (imageType == BufferedImage.TYPE_CUSTOM) {
-      imageType = BufferedImage.TYPE_INT_ARGB
-    }
-    if (xScale > 0.5 && yScale > 0.5) {
-      val scaled = BufferedImage(destWidth, destHeight, imageType)
-      val g2 = scaled.createGraphics()
-      g2.composite = AlphaComposite.Src
-      g2.color = Color(0, true)
-      g2.fillRect(0, 0, destWidth, destHeight)
-      if (xScale == 1.0 && yScale == 1.0) {
-        g2.drawImage(source, 0, 0, null)
-      } else {
-        setRenderingHints(g2)
-        g2.drawImage(source, 0, 0, destWidth, destHeight, 0, 0, sourceWidth, sourceHeight, null)
-      }
-      g2.dispose()
-      return scaled
-    } else {
-      // When creating a thumbnail, using the above code doesn't work very well;
-      // you get some visible artifacts, especially for text. Instead use the
-      // technique of repeatedly scaling the image into half; this will cause
-      // proper averaging of neighboring pixels, and will typically (for the kinds
-      // of screen sizes used by this utility method in the layout editor) take
-      // about 3-4 iterations to get the result since we are logarithmically reducing
-      // the size. Besides, each successive pass in operating on much fewer pixels
-      // (a reduction of 4 in each pass).
-      //
-      // However, we may not be resizing to a size that can be reached exactly by
-      // successively diving in half. Therefore, once we're within a factor of 2 of
-      // the final size, we can do a resize to the exact target size.
-      // However, we can get even better results if we perform this final resize
-      // up front. Let's say we're going from width 1000 to a destination width of 85.
-      // The first approach would cause a resize from 1000 to 500 to 250 to 125, and
-      // then a resize from 125 to 85. That last resize can distort/blur a lot.
-      // Instead, we can start with the destination width, 85, and double it
-      // successfully until we're close to the initial size: 85, then 170,
-      // then 340, and finally 680. (The next one, 1360, is larger than 1000).
-      // So, now we *start* the thumbnail operation by resizing from width 1000 to
-      // width 680, which will preserve a lot of visual details such as text.
-      // Then we can successively resize the image in half, 680 to 340 to 170 to 85.
-      // We end up with the expected final size, but we've been doing an exact
-      // divide-in-half resizing operation at the end so there is less distortion.
-
-      var iterations = 0 // Number of halving operations to perform after the initial resize
-      var nearestWidth = destWidth // Width closest to source width that = 2^x, x is integer
-      var nearestHeight = destHeight
-      while (nearestWidth < sourceWidth / 2) {
-        nearestWidth *= 2
-        nearestHeight *= 2
-        iterations++
-      }
-
-      var scaled = BufferedImage(nearestWidth, nearestHeight, imageType)
-
-      var g2 = scaled.createGraphics()
-      setRenderingHints(g2)
-      g2.drawImage(source, 0, 0, nearestWidth, nearestHeight, 0, 0, sourceWidth, sourceHeight, null)
-      g2.dispose()
-
-      sourceWidth = nearestWidth
-      sourceHeight = nearestHeight
-      source = scaled
-
-      for (iteration in iterations - 1 downTo 0) {
-        val halfWidth = sourceWidth / 2
-        val halfHeight = sourceHeight / 2
-        scaled = BufferedImage(halfWidth, halfHeight, imageType)
-        g2 = scaled.createGraphics()
-        setRenderingHints(g2)
-        g2.drawImage(source, 0, 0, halfWidth, halfHeight, 0, 0, sourceWidth, sourceHeight, null)
-        g2.dispose()
-
-        sourceWidth = halfWidth
-        sourceHeight = halfHeight
-        source = scaled
-        iterations--
-      }
-      return scaled
-    }
-  }
-
-  fun getThumbnailScale(image: BufferedImage): Double {
-    val maxDimension = max(image.width, image.height)
-    return THUMBNAIL_SIZE / maxDimension.toDouble()
-  }
-
-  private fun setRenderingHints(g2: Graphics2D) {
-    g2.setRenderingHint(KEY_INTERPOLATION, VALUE_INTERPOLATION_BILINEAR)
-    g2.setRenderingHint(KEY_RENDERING, VALUE_RENDER_QUALITY)
-    g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON)
-  }
-
-  /**
-   * Saves the generated thumbnail image and appends the info message to an initial message
-   */
-  @Throws(IOException::class)
-  private fun saveImageAndAppendMessage(
-    image: BufferedImage,
-    initialMessage: String,
-    relativePath: String
-  ): String {
-    @Suppress("NAME_SHADOWING") var initialMessage = initialMessage
-    val output = File(
-      failureDir,
-      getName(relativePath)
-    )
-    if (output.exists()) {
-      val deleted = output.delete()
-      assertTrue(deleted)
-    }
-    ImageIO.write(image, "PNG", output)
-    initialMessage += "Thumbnail for current rendering stored at file://" + output.path
-    //        initialMessage += "\nRun the following command to accept the changes:\n";
-    //        initialMessage += String.format("mv %1$s %2$s", output.getPath(),
-    //                ImageUtils.class.getResource(relativePath).getPath());
-    // The above has been commented out, since the destination path returned is in out dir
-    // and it makes the tests pass without the code being actually checked in.
-    return initialMessage
-  }
-
-  private fun getName(relativePath: String): String {
-    return relativePath.substring(relativePath.lastIndexOf(separatorChar) + 1)
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/MatrixMatrixMultiplicationInterceptor.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/MatrixMatrixMultiplicationInterceptor.kt
deleted file mode 100644
index 41994c2d..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/MatrixMatrixMultiplicationInterceptor.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-package app.cash.paparazzi.internal
-
-// Sampled from https://cs.android.com/android/platform/superproject/+/master:external/robolectric-shadows/shadows/framework/src/main/java/org/robolectric/shadows/ShadowOpenGLMatrix.java;l=10-67
-object MatrixMatrixMultiplicationInterceptor {
-  @Suppress("unused")
-  @JvmStatic
-  fun intercept(
-    result: FloatArray,
-    resultOffset: Int,
-    lhs: FloatArray,
-    lhsOffset: Int,
-    rhs: FloatArray,
-    rhsOffset: Int
-  ) {
-    require(resultOffset + 16 <= result.size) { "resultOffset + 16 > result.length" }
-    require(lhsOffset + 16 <= lhs.size) { "lhsOffset + 16 > lhs.length" }
-    require(rhsOffset + 16 <= rhs.size) { "rhsOffset + 16 > rhs.length" }
-    for (i in 0..3) {
-      val rhs_i0 = rhs[I(i, 0, rhsOffset)]
-      var ri0 = lhs[I(0, 0, lhsOffset)] * rhs_i0
-      var ri1 = lhs[I(0, 1, lhsOffset)] * rhs_i0
-      var ri2 = lhs[I(0, 2, lhsOffset)] * rhs_i0
-      var ri3 = lhs[I(0, 3, lhsOffset)] * rhs_i0
-      for (j in 1..3) {
-        val rhs_ij = rhs[I(i, j, rhsOffset)]
-        ri0 += lhs[I(j, 0, lhsOffset)] * rhs_ij
-        ri1 += lhs[I(j, 1, lhsOffset)] * rhs_ij
-        ri2 += lhs[I(j, 2, lhsOffset)] * rhs_ij
-        ri3 += lhs[I(j, 3, lhsOffset)] * rhs_ij
-      }
-      result[I(i, 0, resultOffset)] = ri0
-      result[I(i, 1, resultOffset)] = ri1
-      result[I(i, 2, resultOffset)] = ri2
-      result[I(i, 3, resultOffset)] = ri3
-    }
-  }
-
-  @Suppress("FunctionName")
-  private fun I(i: Int, j: Int, offset: Int): Int {
-    // #define I(_i, _j) ((_j)+ 4*(_i))
-    return offset + j + 4 * i
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/MatrixVectorMultiplicationInterceptor.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/MatrixVectorMultiplicationInterceptor.kt
deleted file mode 100644
index 403413e..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/MatrixVectorMultiplicationInterceptor.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package app.cash.paparazzi.internal
-
-// Sampled from https://cs.android.com/android/platform/superproject/+/master:external/robolectric-shadows/shadows/framework/src/main/java/org/robolectric/shadows/ShadowOpenGLMatrix.java;l=69-121
-object MatrixVectorMultiplicationInterceptor {
-  @Suppress("unused")
-  @JvmStatic
-  fun intercept(
-    resultVec: FloatArray,
-    resultVecOffset: Int,
-    lhsMat: FloatArray,
-    lhsMatOffset: Int,
-    rhsVec: FloatArray,
-    rhsVecOffset: Int
-  ) {
-    require(resultVecOffset + 4 <= resultVec.size) { "resultOffset + 4 > result.length" }
-    require(lhsMatOffset + 16 <= lhsMat.size) { "lhsOffset + 16 > lhs.length" }
-    require(rhsVecOffset + 4 <= rhsVec.size) { "rhsOffset + 4 > rhs.length" }
-    val x = rhsVec[rhsVecOffset + 0]
-    val y = rhsVec[rhsVecOffset + 1]
-    val z = rhsVec[rhsVecOffset + 2]
-    val w = rhsVec[rhsVecOffset + 3]
-    resultVec[resultVecOffset + 0] =
-      lhsMat[I(0, 0, lhsMatOffset)] * x + lhsMat[I(1, 0, lhsMatOffset)] * y +
-          lhsMat[I(2, 0, lhsMatOffset)] * z + lhsMat[I(3, 0, lhsMatOffset)] * w
-    resultVec[resultVecOffset + 1] =
-      lhsMat[I(0, 1, lhsMatOffset)] * x + lhsMat[I(1, 1, lhsMatOffset)] * y +
-          lhsMat[I(2, 1, lhsMatOffset)] * z + lhsMat[I(3, 1, lhsMatOffset)] * w
-    resultVec[resultVecOffset + 2] =
-      lhsMat[I(0, 2, lhsMatOffset)] * x + lhsMat[I(1, 2, lhsMatOffset)] * y +
-          lhsMat[I(2, 2, lhsMatOffset)] * z + lhsMat[I(3, 2, lhsMatOffset)] * w
-    resultVec[resultVecOffset + 3] =
-      lhsMat[I(0, 3, lhsMatOffset)] * x + lhsMat[I(1, 3, lhsMatOffset)] * y +
-          lhsMat[I(2, 3, lhsMatOffset)] * z + lhsMat[I(3, 3, lhsMatOffset)] * w
-  }
-
-  @Suppress("FunctionName")
-  private fun I(i: Int, j: Int, offset: Int): Int {
-    // #define I(_i, _j) ((_j)+ 4*(_i))
-    return offset + j + 4 * i
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/PaparazziAssetRepository.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/PaparazziAssetRepository.kt
deleted file mode 100644
index 72bcf85..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/PaparazziAssetRepository.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2017 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 app.cash.paparazzi.internal
-
-import com.android.ide.common.rendering.api.AssetRepository
-import java.io.File
-import java.io.FileInputStream
-import java.io.FileNotFoundException
-import java.io.IOException
-import java.io.InputStream
-
-internal class PaparazziAssetRepository(private val assetPath: String) : AssetRepository() {
-  @Throws(FileNotFoundException::class)
-  private fun open(path: String): InputStream? {
-    val asset = File(path)
-    return when {
-      asset.isFile -> FileInputStream(asset)
-      else -> null
-    }
-  }
-
-  override fun isSupported(): Boolean = true
-
-  @Throws(IOException::class)
-  override fun openAsset(
-    path: String,
-    mode: Int
-  ): InputStream? = open("$assetPath/$path")
-
-  @Throws(IOException::class)
-  override fun openNonAsset(
-    cookie: Int,
-    path: String,
-    mode: Int
-  ): InputStream? = open(path)
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/PaparazziCallback.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/PaparazziCallback.kt
deleted file mode 100644
index 6e2b62e..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/PaparazziCallback.kt
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2014 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 app.cash.paparazzi.internal
-
-import app.cash.paparazzi.internal.parsers.LayoutPullParser
-import app.cash.paparazzi.internal.parsers.TagSnapshot
-import com.android.ide.common.rendering.api.ActionBarCallback
-import com.android.ide.common.rendering.api.AdapterBinding
-import com.android.ide.common.rendering.api.ILayoutPullParser
-import com.android.ide.common.rendering.api.LayoutlibCallback
-import com.android.ide.common.rendering.api.ResourceNamespace.RES_AUTO
-import com.android.ide.common.rendering.api.ResourceReference
-import com.android.ide.common.rendering.api.ResourceValue
-import com.android.ide.common.rendering.api.SessionParams.Key
-import com.android.layoutlib.bridge.android.RenderParamsFlags
-import com.android.resources.ResourceType
-import com.android.resources.ResourceType.STYLE
-import com.google.common.io.ByteStreams
-import java.io.ByteArrayInputStream
-import java.io.ByteArrayOutputStream
-import java.io.File
-import java.io.FileInputStream
-import java.io.FileNotFoundException
-import java.io.IOException
-import java.lang.reflect.Modifier
-import org.kxml2.io.KXmlParser
-import org.xmlpull.v1.XmlPullParser
-import org.xmlpull.v1.XmlPullParserException
-
-internal class PaparazziCallback(
-  private val logger: PaparazziLogger,
-  private val resourcePackageNames: List<String>
-) : LayoutlibCallback() {
-  private val projectResources = mutableMapOf<Int, ResourceReference>()
-  private val resources = mutableMapOf<ResourceReference, Int>()
-  private val actionBarCallback = ActionBarCallback()
-  private val aaptDeclaredResources = mutableMapOf<String, TagSnapshot>()
-
-  private var adaptiveIconMaskPath: String? = null
-  private val loadedClasses = mutableMapOf<String, Class<*>>()
-
-  @Throws(ClassNotFoundException::class)
-  fun initResources() {
-    for (rPackageName in resourcePackageNames) {
-      val rClass = Class.forName("$rPackageName.R")
-      for (resourceClass in rClass.declaredClasses) {
-        val resourceType = ResourceType.fromClassName(resourceClass.simpleName) ?: continue
-
-        for (field in resourceClass.declaredFields) {
-          if (!Modifier.isStatic(field.modifiers)) continue
-
-          // May not be final in library projects.
-          val type = field.type
-          try {
-            if (type == Int::class.javaPrimitiveType) {
-              val value = field.get(null) as Int
-              val reference = ResourceReference(RES_AUTO, resourceType, field.name)
-              projectResources[value] = reference
-              resources[reference] = value
-            } else if (type.isArray && type.componentType == Int::class.javaPrimitiveType) {
-              // Ignore.
-            } else {
-              logger.error(null, "Unknown field type in R class: $type")
-            }
-          } catch (e: IllegalAccessException) {
-            logger.error(e, "Malformed R class: %1\$s", "$rPackageName.R")
-          }
-        }
-      }
-    }
-  }
-
-  @Throws(Exception::class)
-  override fun loadView(
-    name: String,
-    constructorSignature: Array<Class<*>>,
-    constructorArgs: Array<Any>
-  ): Any? {
-    val viewClass = Class.forName(name)
-    val viewConstructor = viewClass.getConstructor(*constructorSignature)
-    viewConstructor.isAccessible = true
-    return viewConstructor.newInstance(*constructorArgs)
-  }
-
-  override fun resolveResourceId(id: Int): ResourceReference? = projectResources[id]
-
-  override fun getOrGenerateResourceId(resource: ResourceReference): Int {
-    // Workaround: We load our resource map from fields in R.class, which are named using Java
-    // class conventions.  Therefore, we need to similarly transform style naming conventions
-    // that contain periods (e.g., Widget.AppCompat.TextView) to avoid false lookup misses.
-    // Long-term: Perhaps parse and load resource names from file system directly?
-    val resourceKey =
-      if (resource.resourceType == STYLE) resource.transformStyleResource() else resource
-    return resources[resourceKey] ?: 0
-  }
-
-  override fun getParser(layoutResource: ResourceValue): ILayoutPullParser? {
-    try {
-      val value = layoutResource.value ?: return null
-      if (aaptDeclaredResources.isNotEmpty() && layoutResource.resourceType == ResourceType.AAPT) {
-        val aaptResource = aaptDeclaredResources.getValue(value)
-        return LayoutPullParser.createFromAaptResource(aaptResource)
-      }
-
-      return LayoutPullParser.createFromFile(File(layoutResource.value))
-        .also {
-          // For parser of elements included in this parser, publish any aapt declared values
-          aaptDeclaredResources.putAll(it.getAaptDeclaredAttrs())
-        }
-    } catch (e: FileNotFoundException) {
-      return null
-    }
-  }
-
-  override fun getAdapterItemValue(
-    adapterView: ResourceReference,
-    adapterCookie: Any,
-    itemRef: ResourceReference,
-    fullPosition: Int,
-    positionPerType: Int,
-    fullParentPosition: Int,
-    parentPositionPerType: Int,
-    viewRef: ResourceReference,
-    viewAttribute: ViewAttribute,
-    defaultValue: Any
-  ): Any? = null
-
-  override fun getAdapterBinding(
-    adapterViewRef: ResourceReference,
-    adapterCookie: Any,
-    viewObject: Any
-  ): AdapterBinding? = null
-
-  override fun getActionBarCallback(): ActionBarCallback = actionBarCallback
-
-  override fun createXmlParserForPsiFile(fileName: String): XmlPullParser? =
-    createXmlParserForFile(fileName)
-
-  override fun createXmlParserForFile(fileName: String): XmlPullParser? {
-    try {
-      FileInputStream(fileName).use { fileStream ->
-        // Read data fully to memory to be able to close the file stream.
-        val byteOutputStream = ByteArrayOutputStream()
-        ByteStreams.copy(fileStream, byteOutputStream)
-        val parser = KXmlParser()
-        parser.setInput(ByteArrayInputStream(byteOutputStream.toByteArray()), null)
-        parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true)
-        return parser
-      }
-    } catch (e: IOException) {
-      return null
-    } catch (e: XmlPullParserException) {
-      return null
-    }
-  }
-
-  override fun createXmlParser(): XmlPullParser = KXmlParser()
-
-  @Suppress("UNCHECKED_CAST")
-  override fun <T> getFlag(key: Key<T>?): T? {
-    return when (key) {
-      RenderParamsFlags.FLAG_KEY_ADAPTIVE_ICON_MASK_PATH -> adaptiveIconMaskPath as T?
-      else -> null
-    }
-  }
-
-  fun setAdaptiveIconMaskPath(adaptiveIconMaskPath: String) {
-    this.adaptiveIconMaskPath = adaptiveIconMaskPath
-  }
-
-  override fun findClass(name: String): Class<*> {
-    val clazz = loadedClasses[name]
-    logger.verbose("loadClassA($name)")
-
-    try {
-      if (clazz != null) {
-        return clazz
-      }
-      val clazz2 = Class.forName(name)
-      logger.verbose("loadClassB($name)")
-      loadedClasses[name] = clazz2
-      return clazz2
-    } catch (e: LinkageError) {
-      throw ClassNotFoundException("error loading class $name", e)
-    } catch (e: ExceptionInInitializerError) {
-      throw ClassNotFoundException("error loading class $name", e)
-    } catch (e: ClassNotFoundException) {
-      throw ClassNotFoundException("error loading class $name", e)
-    }
-  }
-
-  private fun ResourceReference.transformStyleResource() =
-    ResourceReference.style(namespace, name.replace('.', '_'))
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/PaparazziJson.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/PaparazziJson.kt
deleted file mode 100644
index 6739e81..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/PaparazziJson.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2019 Square, Inc.
- *
- * 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 app.cash.paparazzi.internal
-
-import app.cash.paparazzi.Snapshot
-import app.cash.paparazzi.TestName
-import com.squareup.moshi.FromJson
-import com.squareup.moshi.JsonAdapter
-import com.squareup.moshi.Moshi
-import com.squareup.moshi.ToJson
-import com.squareup.moshi.Types
-import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter
-import java.util.Date
-
-internal object PaparazziJson {
-  val moshi = Moshi.Builder()
-    .add(Date::class.java, Rfc3339DateJsonAdapter())
-    .add(this)
-    .build()!!
-
-  val listOfShotsAdapter: JsonAdapter<List<Snapshot>> =
-    moshi
-      .adapter<List<Snapshot>>(
-        Types.newParameterizedType(List::class.java, Snapshot::class.java)
-      )
-      .indent("  ")
-
-  val listOfStringsAdapter: JsonAdapter<List<String>> =
-    moshi
-      .adapter<List<String>>(
-        Types.newParameterizedType(List::class.java, String::class.java)
-      )
-      .indent("  ")
-
-  @ToJson
-  fun testNameToJson(testName: TestName): String {
-    return "${testName.packageName}.${testName.className}#${testName.methodName}"
-  }
-
-  @FromJson
-  fun testNameFromJson(json: String): TestName {
-    val regex = Regex("(.*)\\.([^.]*)#([^.]*)")
-    val (packageName, className, methodName) = regex.matchEntire(json)!!.destructured
-    return TestName(packageName, className, methodName)
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/PaparazziLogger.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/PaparazziLogger.kt
deleted file mode 100644
index 01595f7..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/PaparazziLogger.kt
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2019 Square, Inc.
- *
- * 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 app.cash.paparazzi.internal
-
-import app.cash.paparazzi.Paparazzi
-import com.android.ide.common.rendering.api.ILayoutLog
-import com.android.utils.ILogger
-import java.io.PrintStream
-import java.io.PrintWriter
-import java.util.logging.Level
-import java.util.logging.Logger
-import java.util.logging.Logger.getLogger
-
-/**
- * This logger delegates to java.util.Logging.
- */
-internal class PaparazziLogger : ILayoutLog, ILogger {
-  private val logger: Logger = getLogger(Paparazzi::class.java.name)
-  private val errors = mutableListOf<Throwable>()
-
-  override fun error(
-    throwable: Throwable?,
-    format: String?,
-    vararg args: Any
-  ) {
-    logger.log(Level.SEVERE, format?.format(args), throwable)
-    if (throwable != null) {
-      errors += throwable
-    }
-  }
-
-  override fun warning(
-    format: String,
-    vararg args: Any
-  ) {
-    logger.log(Level.WARNING, format, args)
-  }
-
-  override fun info(
-    format: String,
-    vararg args: Any
-  ) {
-    logger.log(Level.INFO, format, args)
-  }
-
-  override fun verbose(
-    format: String,
-    vararg args: Any
-  ) {
-    logger.log(Level.FINE, format, args)
-  }
-
-  override fun fidelityWarning(
-    tag: String?,
-    message: String?,
-    throwable: Throwable?,
-    cookie: Any?,
-    data: Any?
-  ) {
-    logger.log(Level.WARNING, "$tag: $message", throwable)
-  }
-
-  override fun error(
-    tag: String?,
-    message: String?,
-    viewCookie: Any?,
-    data: Any?
-  ) {
-    logger.log(Level.SEVERE, "$tag: $message")
-  }
-
-  override fun error(
-    tag: String?,
-    message: String?,
-    throwable: Throwable?,
-    viewCookie: Any?,
-    data: Any?
-  ) {
-    logger.log(Level.SEVERE, "$tag: $message", throwable)
-    if (throwable != null) {
-      errors += throwable
-    }
-  }
-
-  override fun warning(
-    tag: String?,
-    message: String?,
-    viewCookie: Any?,
-    data: Any?
-  ) {
-    logger.log(Level.WARNING, "$tag: $message")
-  }
-
-  override fun logAndroidFramework(priority: Int, tag: String?, message: String?) {
-    logger.log(Level.INFO, "$tag [$priority]: $message")
-  }
-
-  fun assertNoErrors() {
-    when (errors.size) {
-      0 -> return
-      1 -> throw errors[0]
-      else -> throw MultipleFailuresException(errors)
-    }
-  }
-
-  internal class MultipleFailuresException(private val causes: List<Throwable>) : Exception() {
-    init {
-      require(causes.isNotEmpty()) { "List of Throwables must not be empty" }
-    }
-
-    override val message: String
-      get() = buildString {
-        appendLine(String.format("There were %d errors:", causes.size))
-        causes.forEach { e ->
-          appendLine(String.format("%n  %s: %s", e.javaClass.name, e.message))
-          e.stackTrace.forEach { traceElement ->
-            appendLine("\tat $traceElement")
-          }
-        }
-      }
-
-    override fun printStackTrace() {
-      causes.forEach { e ->
-        e.printStackTrace()
-      }
-    }
-
-    override fun printStackTrace(s: PrintStream) {
-      causes.forEach { e ->
-        e.printStackTrace(s)
-      }
-    }
-
-    override fun printStackTrace(s: PrintWriter) {
-      causes.forEach { e ->
-        e.printStackTrace(s)
-      }
-    }
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/RenderResult.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/RenderResult.kt
deleted file mode 100644
index cbf05df..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/RenderResult.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2016 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 app.cash.paparazzi.internal
-
-import com.android.ide.common.rendering.api.RenderSession
-import com.android.ide.common.rendering.api.Result
-import com.android.ide.common.rendering.api.ViewInfo
-import java.awt.image.BufferedImage
-
-internal data class RenderResult(
-  val result: Result,
-  val systemViews: List<ViewInfo>,
-  val rootViews: List<ViewInfo>,
-  val image: BufferedImage
-)
-
-internal fun RenderSession.toResult(): RenderResult {
-  return RenderResult(result, systemRootViews.toList(), rootViews.toList(), image)
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/Renderer.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/Renderer.kt
deleted file mode 100644
index 569d1cd..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/Renderer.kt
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2016 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 app.cash.paparazzi.internal
-
-import app.cash.paparazzi.DeviceConfig
-import app.cash.paparazzi.Environment
-import app.cash.paparazzi.Flags
-import app.cash.paparazzi.internal.parsers.LayoutPullParser
-import com.android.ide.common.rendering.api.SessionParams
-import com.android.io.FolderWrapper
-import com.android.layoutlib.bridge.Bridge
-import com.android.layoutlib.bridge.android.RenderParamsFlags
-import com.android.layoutlib.bridge.impl.DelegateManager
-import java.awt.image.BufferedImage
-import java.io.Closeable
-import java.io.File
-import java.io.IOException
-import java.util.Locale
-
-/** View rendering. */
-internal class Renderer(
-  private val environment: Environment,
-  private val layoutlibCallback: PaparazziCallback,
-  private val logger: PaparazziLogger,
-  private val maxPercentDifference: Double
-) : Closeable {
-  private var bridge: Bridge? = null
-  private lateinit var sessionParamsBuilder: SessionParamsBuilder
-
-  /** Initialize the bridge and the resource maps. */
-  fun prepare(): SessionParamsBuilder {
-    val platformDataResDir = File("${environment.platformDir}/data/res")
-
-    @Suppress("DEPRECATION")
-    val frameworkResources = com.android.ide.common.resources.deprecated.FrameworkResources(
-      FolderWrapper(platformDataResDir)
-    ).apply {
-      loadResources()
-      loadPublicResources(logger)
-    }
-
-    @Suppress("DEPRECATION")
-    val projectResources = object : com.android.ide.common.resources.deprecated.ResourceRepository(
-      FolderWrapper(environment.resDir),
-      false
-    ) {
-      override fun createResourceItem(
-        name: String
-      ): com.android.ide.common.resources.deprecated.ResourceItem {
-        return com.android.ide.common.resources.deprecated.ResourceItem(name)
-      }
-    }
-    projectResources.loadResources()
-
-    sessionParamsBuilder = SessionParamsBuilder(
-      layoutlibCallback = layoutlibCallback,
-      logger = logger,
-      frameworkResources = frameworkResources,
-      projectResources = projectResources,
-      assetRepository = PaparazziAssetRepository(environment.assetsDir)
-    )
-      .plusFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE, true)
-      .withTheme("AppTheme", true)
-
-    val platformDataRoot = System.getProperty("paparazzi.platform.data.root")
-      ?: throw RuntimeException("Missing system property for 'paparazzi.platform.data.root'")
-    val platformDataDir = File(platformDataRoot, "data")
-    val fontLocation = File(platformDataDir, "fonts")
-    val nativeLibLocation = File(platformDataDir, getNativeLibDir())
-    val icuLocation = File(platformDataDir, "icu" + File.separator + "icudt70l.dat")
-    val buildProp = File(environment.platformDir, "build.prop")
-    val attrs = File(platformDataResDir, "values" + File.separator + "attrs.xml")
-    val systemProperties = DeviceConfig.loadProperties(buildProp) + mapOf(
-      // We want Choreographer.USE_FRAME_TIME to be false so it uses System_Delegate.nanoTime()
-      "debug.choreographer.frametime" to "false"
-    )
-    bridge = Bridge().apply {
-      check(
-        init(
-          systemProperties,
-          fontLocation,
-          nativeLibLocation.path,
-          icuLocation.path,
-          DeviceConfig.getEnumMap(attrs),
-          logger
-        )
-      ) { "Failed to init Bridge." }
-    }
-    Bridge.getLock()
-      .lock()
-    try {
-      Bridge.setLog(logger)
-    } finally {
-      Bridge.getLock()
-        .unlock()
-    }
-
-    return sessionParamsBuilder
-  }
-
-  private fun getNativeLibDir(): String {
-    val osName = System.getProperty("os.name").lowercase(Locale.US)
-    val osLabel = when {
-      osName.startsWith("windows") -> "win"
-      osName.startsWith("mac") -> {
-        val osArch = System.getProperty("os.arch").lowercase(Locale.US)
-        if (osArch.startsWith("x86")) "mac" else "mac-arm"
-      }
-      else -> "linux"
-    }
-    return "$osLabel/lib64"
-  }
-
-  override fun close() {
-    bridge = null
-
-    Gc.gc()
-
-    dumpDelegates()
-  }
-
-  fun dumpDelegates() {
-    if (System.getProperty(Flags.DEBUG_LINKED_OBJECTS) != null) {
-      println("Objects still linked from the DelegateManager:")
-      DelegateManager.dump(System.out)
-    }
-  }
-
-  fun render(
-    bridge: com.android.ide.common.rendering.api.Bridge,
-    params: SessionParams,
-    frameTimeNanos: Long
-  ): RenderResult {
-    val session = bridge.createSession(params)
-
-    try {
-      if (frameTimeNanos != -1L) {
-        session.setElapsedFrameTimeNanos(frameTimeNanos)
-      }
-
-      if (!session.result.isSuccess) {
-        logger.error(session.result.exception, session.result.errorMessage)
-      } else {
-        // Render the session with a timeout of 50s.
-        val renderResult = session.render(50000)
-        if (!renderResult.isSuccess) {
-          logger.error(session.result.exception, session.result.errorMessage)
-        }
-      }
-
-      return session.toResult()
-    } finally {
-      session.dispose()
-    }
-  }
-
-  /** Compares the golden image with the passed image. */
-  fun verify(
-    goldenImageName: String,
-    image: BufferedImage
-  ) {
-    try {
-      val goldenImagePath = environment.appTestDir + "/golden/" + goldenImageName
-      ImageUtils.requireSimilar(goldenImagePath, image, maxPercentDifference)
-    } catch (e: IOException) {
-      logger.error(e, e.message)
-    }
-  }
-
-  /**
-   * Create a new rendering session and test that rendering the given layout doesn't throw any
-   * exceptions and matches the provided image.
-   *
-   * If frameTimeNanos is >= 0 a frame will be executed during the rendering. The time indicates
-   * how far in the future is.
-   */
-  @JvmOverloads
-  fun renderAndVerify(
-    sessionParams: SessionParams,
-    goldenFileName: String,
-    frameTimeNanos: Long = -1
-  ): RenderResult {
-    val result = render(bridge!!, sessionParams, frameTimeNanos)
-    verify(goldenFileName, result.image)
-    return result
-  }
-
-  fun createParserFromPath(layoutPath: String): LayoutPullParser =
-    LayoutPullParser.createFromPath("${environment.resDir}/layout/$layoutPath")
-
-  /**
-   * Create a new rendering session and test that rendering the given layout on given device
-   * doesn't throw any exceptions and matches the provided image.
-   */
-  @JvmOverloads
-  fun renderAndVerify(
-    layoutFileName: String,
-    goldenFileName: String,
-    deviceConfig: DeviceConfig = DeviceConfig.NEXUS_5
-  ): RenderResult {
-    val sessionParams = sessionParamsBuilder
-      .copy(
-        layoutPullParser = createParserFromPath(layoutFileName),
-        deviceConfig = deviceConfig
-      )
-      .build()
-    return renderAndVerify(sessionParams, goldenFileName)
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/ResourcesInterceptor.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/ResourcesInterceptor.kt
deleted file mode 100644
index a7f14c8..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/ResourcesInterceptor.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package app.cash.paparazzi.internal
-
-import android.content.Context
-import android.graphics.Typeface
-
-object ResourcesInterceptor {
-  @JvmStatic
-  fun intercept(
-    context: Context,
-    resId: Int
-  ): Typeface? {
-    return context.resources.getFont(resId)
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/ServiceManagerInterceptor.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/ServiceManagerInterceptor.kt
deleted file mode 100644
index 4726fad..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/ServiceManagerInterceptor.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package app.cash.paparazzi.internal
-
-import android.os.IBinder
-
-/**
- * The ImeTracing class attempts to initialize its [mService field in its constructor](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/util/imetracing/ImeTracing.java;l=60).
- *
- * Unfortunately, [layoutlib's version of ServiceManager](https://cs.android.com/android/platform/superproject/+/master:frameworks/layoutlib/bridge/src/android/os/ServiceManager.java;l=37)
- * throws an exception immediately.
- *
- * This interceptor overrides ServiceManager.getServiceOrThrow to simply return null instead.
- */
-object ServiceManagerInterceptor {
-  @Suppress("unused")
-  @JvmStatic
-  fun interceptGetServiceOrThrow(@Suppress("UNUSED_PARAMETER") name: String): IBinder? = null
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/SessionParamsBuilder.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/SessionParamsBuilder.kt
deleted file mode 100644
index ea263b6..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/SessionParamsBuilder.kt
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2017 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 app.cash.paparazzi.internal
-
-import app.cash.paparazzi.DeviceConfig
-import app.cash.paparazzi.internal.parsers.LayoutPullParser
-import com.android.SdkConstants
-import com.android.ide.common.rendering.api.AssetRepository
-import com.android.ide.common.rendering.api.ResourceNamespace
-import com.android.ide.common.rendering.api.ResourceReference
-import com.android.ide.common.rendering.api.SessionParams
-import com.android.ide.common.rendering.api.SessionParams.Key
-import com.android.ide.common.rendering.api.SessionParams.RenderingMode
-import com.android.ide.common.resources.ResourceResolver
-import com.android.ide.common.resources.ResourceValueMap
-import com.android.layoutlib.bridge.Bridge
-import com.android.resources.LayoutDirection
-import com.android.resources.ResourceType
-
-/** Creates [SessionParams] objects. */
-internal data class SessionParamsBuilder(
-  private val layoutlibCallback: PaparazziCallback,
-  private val logger: PaparazziLogger,
-  @Suppress("DEPRECATION")
-  private val frameworkResources: com.android.ide.common.resources.deprecated.ResourceRepository,
-  private val assetRepository: AssetRepository,
-  @Suppress("DEPRECATION")
-  private val projectResources: com.android.ide.common.resources.deprecated.ResourceRepository,
-  private val deviceConfig: DeviceConfig = DeviceConfig.NEXUS_5,
-  private val renderingMode: RenderingMode = RenderingMode.NORMAL,
-  private val targetSdk: Int = 22,
-  private val flags: Map<Key<*>, Any> = mapOf(),
-  private val themeName: String? = null,
-  private val isProjectTheme: Boolean = false,
-  private val layoutPullParser: LayoutPullParser? = null,
-  private val projectKey: Any? = null,
-  private val minSdk: Int = 0,
-  private val decor: Boolean = true
-) {
-  fun withTheme(
-    themeName: String,
-    isProjectTheme: Boolean
-  ): SessionParamsBuilder {
-    return copy(themeName = themeName, isProjectTheme = isProjectTheme)
-  }
-
-  fun withTheme(themeName: String): SessionParamsBuilder {
-    return when {
-      themeName.startsWith(SdkConstants.PREFIX_ANDROID) -> {
-        withTheme(themeName.substring(SdkConstants.PREFIX_ANDROID.length), false)
-      }
-      else -> withTheme(themeName, true)
-    }
-  }
-
-  fun plusFlag(
-    flag: SessionParams.Key<*>,
-    value: Any
-  ) = copy(flags = flags + (flag to value))
-
-  fun build(): SessionParams {
-    require(themeName != null)
-
-    val folderConfiguration = deviceConfig.folderConfiguration
-
-    @Suppress("DEPRECATION")
-    val resourceResolver = ResourceResolver.create(
-      mapOf<ResourceNamespace, Map<ResourceType, ResourceValueMap>>(
-        ResourceNamespace.ANDROID to frameworkResources.getConfiguredResources(
-          folderConfiguration
-        ),
-        ResourceNamespace.TODO() to projectResources.getConfiguredResources(
-          folderConfiguration
-        )
-      ),
-      ResourceReference(
-        ResourceNamespace.fromBoolean(!isProjectTheme),
-        ResourceType.STYLE,
-        themeName
-      )
-    )
-
-    val result = SessionParams(
-      layoutPullParser, renderingMode, projectKey /* for caching */,
-      deviceConfig.hardwareConfig, resourceResolver, layoutlibCallback, minSdk, targetSdk, logger
-    )
-    result.fontScale = deviceConfig.fontScale
-
-    val localeQualifier = folderConfiguration.localeQualifier
-    val layoutDirectionQualifier = folderConfiguration.layoutDirectionQualifier
-    // https://cs.android.com/android-studio/platform/tools/adt/idea/+/mirror-goog-studio-main:android/src/com/android/tools/idea/rendering/RenderTask.java;l=645
-    if (
-      LayoutDirection.RTL == layoutDirectionQualifier.value &&
-      !Bridge.isLocaleRtl(localeQualifier.tag)
-    ) {
-      result.locale = "ur"
-    } else {
-      result.locale = localeQualifier.tag
-    }
-    result.setRtlSupport(true)
-
-    for ((key, value) in flags) {
-      @Suppress("UNCHECKED_CAST")
-      result.setFlag(key as Key<Any>, value)
-    }
-    result.setAssetRepository(assetRepository)
-
-    if (!decor) {
-      result.setForceNoDecor()
-    }
-
-    return result
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/AaptAttrParser.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/AaptAttrParser.kt
deleted file mode 100644
index 3c62aa8..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/AaptAttrParser.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2021 Square, Inc.
- *
- * 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 app.cash.paparazzi.internal.parsers
-
-/**
- * Copied from https://cs.android.com/android-studio/platform/tools/adt/idea/+/858f81bb7c350bc7a05daad36edefd21f74c8cef:android/src/com/android/tools/idea/rendering/parsers/AaptAttrParser.java
- *
- * Interface for parsers that support declaration of inlined {@code aapt:attr} attributes
- */
-interface AaptAttrParser {
-  /**
-   * Returns a [Map] that contains all the `aapt:attr` elements declared in this or any
-   * children parsers. This list can be used to resolve `@aapt/_aapt` references into this parser.
-   */
-  fun getAaptDeclaredAttrs(): Map<String, TagSnapshot>
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/AaptAttrSnapshot.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/AaptAttrSnapshot.kt
deleted file mode 100644
index 4105eee..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/AaptAttrSnapshot.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2021 Square, Inc.
- *
- * 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 app.cash.paparazzi.internal.parsers
-
-import com.android.SdkConstants.AAPT_ATTR_PREFIX
-import com.android.SdkConstants.AAPT_PREFIX
-
-/**
- * Derived from https://cs.android.com/android-studio/platform/tools/adt/idea/+/mirror-goog-studio-master-dev:android/src/com/android/tools/idea/rendering/parsers/AaptAttrAttributeSnapshot.java
- *
- * Aapt attributes are attributes that instead of containing a reference, contain the inlined value
- * of the reference. This snapshot will generate a dynamic reference that will be used by the
- * resource resolution to be able to retrieve the inlined value.
- */
-class AaptAttrSnapshot(
-  override val namespace: String,
-  override val prefix: String,
-  override val name: String,
-  val id: String,
-  val bundledTag: TagSnapshot
-) : AttributeSnapshot(namespace, prefix, name, "${AAPT_ATTR_PREFIX}$AAPT_PREFIX$id")
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/AttributeSnapshot.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/AttributeSnapshot.kt
deleted file mode 100644
index 50b658c..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/AttributeSnapshot.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2021 Square, Inc.
- *
- * 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 app.cash.paparazzi.internal.parsers
-
-/**
- * Derived from https://cs.android.com/android-studio/platform/tools/adt/idea/+/mirror-goog-studio-master-dev:android/src/com/android/tools/idea/rendering/parsers/AttributeSnapshot.java
- *
- * A snapshot of an attribute value pulled from an XML resource.
- * Used in conjunction with [TagSnapshot].
- */
-open class AttributeSnapshot(
-  open val namespace: String,
-  open val prefix: String?,
-  open val name: String,
-  open val value: String
-) {
-  override fun toString() = "$name: $value"
-
-  // since data classes can't be subclassed
-  override fun equals(other: Any?): Boolean {
-    if (this === other) return true
-    if (javaClass != other?.javaClass) return false
-
-    other as AttributeSnapshot
-
-    if (namespace != other.namespace) return false
-    if (prefix != other.prefix) return false
-    if (name != other.name) return false
-    if (value != other.value) return false
-
-    return true
-  }
-
-  override fun hashCode(): Int {
-    var result = namespace.hashCode()
-    result = 31 * result + prefix.hashCode()
-    result = 31 * result + name.hashCode()
-    result = 31 * result + value.hashCode()
-    return result
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/InMemoryParser.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/InMemoryParser.kt
deleted file mode 100644
index 5b709fb..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/InMemoryParser.kt
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2021 Square, Inc.
- *
- * 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 app.cash.paparazzi.internal.parsers
-
-import org.kxml2.io.KXmlParser
-import org.xmlpull.v1.XmlPullParserException
-
-/**
- * Derived from https://cs.android.com/android-studio/platform/tools/adt/idea/+/858f81bb7c350bc7a05daad36edefd21f74c8cef:android/src/com/android/tools/idea/rendering/parsers/LayoutPullParser.java;bpv=0;bpt=0
- *
- * A parser implementation that walks an in-memory XML DOM tree.
- */
-abstract class InMemoryParser : KXmlParser() {
-  abstract fun rootTag(): TagSnapshot
-
-  private val nodeStack = mutableListOf<TagSnapshot>()
-  private var parsingState = START_DOCUMENT
-
-  override fun getAttributeCount(): Int {
-    val tag = getCurrentNode() ?: return 0
-    return tag.attributes.size
-  }
-
-  override fun getAttributeName(i: Int): String? {
-    val attribute = getAttribute(i) ?: return null
-    return attribute.name
-  }
-
-  override fun getAttributeNamespace(i: Int): String {
-    val attribute = getAttribute(i) ?: return ""
-    return attribute.namespace
-  }
-
-  override fun getAttributePrefix(i: Int): String? {
-    val attribute = getAttribute(i) ?: return null
-    return attribute.prefix
-  }
-
-  override fun getAttributeValue(i: Int): String? {
-    val attribute = getAttribute(i) ?: return null
-    return attribute.value
-  }
-
-  override fun getAttributeValue(
-    namespace: String?,
-    name: String?
-  ): String? {
-    val tag = getCurrentNode() ?: return null
-    return tag.attributes.find { it.name == name }?.value
-  }
-
-  override fun getDepth(): Int = nodeStack.size
-
-  override fun getName(): String? {
-    if (parsingState == START_TAG || parsingState == END_TAG) {
-      // Should only be called when START_TAG
-      val currentNode = getCurrentNode()!!
-      return currentNode.name
-    }
-    return null
-  }
-
-  @Throws(XmlPullParserException::class)
-  override fun next(): Int {
-    when (parsingState) {
-      END_DOCUMENT -> throw XmlPullParserException("Nothing after the end")
-      START_DOCUMENT -> onNextFromStartDocument()
-      START_TAG -> onNextFromStartTag()
-      END_TAG -> onNextFromEndTag()
-    }
-    return parsingState
-  }
-
-  private fun getCurrentNode(): TagSnapshot? = nodeStack.lastOrNull()
-
-  private fun getAttribute(i: Int): AttributeSnapshot? {
-    if (parsingState != START_TAG) {
-      throw IndexOutOfBoundsException()
-    }
-    val tag = getCurrentNode() ?: return null
-    return tag.attributes[i]
-  }
-
-  private fun push(node: TagSnapshot) {
-    nodeStack.add(node)
-  }
-
-  private fun pop(): TagSnapshot = nodeStack.removeLast()
-
-  private fun onNextFromStartDocument() {
-    val rootTag = rootTag()
-    @Suppress("SENSELESS_COMPARISON")
-    parsingState = if (rootTag != null) {
-      push(rootTag)
-      START_TAG
-    } else {
-      END_DOCUMENT
-    }
-  }
-
-  private fun onNextFromStartTag() {
-    // get the current node, and look for text or children (children first)
-    // Should only be called when START_TAG
-    val node = getCurrentNode()!!
-    val children = node.children
-    parsingState = if (children.isNotEmpty()) {
-      // move to the new child, and don't change the state.
-      push(children[0])
-
-      // in case the current state is CURRENT_DOC, we set the proper state.
-      START_TAG
-    } else {
-      if (parsingState == START_DOCUMENT) {
-        // this handles the case where there's no node.
-        END_DOCUMENT
-      } else {
-        END_TAG
-      }
-    }
-  }
-
-  private fun onNextFromEndTag() {
-    // look for a sibling. if no sibling, go back to the parent
-    // Should only be called when END_TAG
-    var node = getCurrentNode()!!
-    val sibling = node.next
-    if (sibling != null) {
-      node = sibling
-      // to go to the sibling, we need to remove the current node,
-      pop()
-      // and add its sibling.
-      push(node)
-      parsingState = START_TAG
-    } else {
-      // move back to the parent
-      pop()
-
-      // we have only one element left (myRoot), then we're done with the document.
-      parsingState = if (nodeStack.isEmpty()) {
-        END_DOCUMENT
-      } else {
-        END_TAG
-      }
-    }
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/LayoutPullParser.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/LayoutPullParser.kt
deleted file mode 100644
index 8f1a94a..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/LayoutPullParser.kt
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2014 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 app.cash.paparazzi.internal.parsers
-
-import com.android.SdkConstants.ATTR_IGNORE
-import com.android.SdkConstants.EXPANDABLE_LIST_VIEW
-import com.android.SdkConstants.GRID_VIEW
-import com.android.SdkConstants.LIST_VIEW
-import com.android.SdkConstants.SPINNER
-import com.android.SdkConstants.TOOLS_URI
-import com.android.ide.common.rendering.api.ILayoutPullParser
-import com.android.ide.common.rendering.api.ResourceNamespace
-import java.io.ByteArrayInputStream
-import java.io.File
-import java.io.FileInputStream
-import java.io.FileNotFoundException
-import java.io.IOError
-import java.io.InputStream
-import java.nio.charset.Charset
-import okio.buffer
-import okio.source
-import org.xmlpull.v1.XmlPullParserException
-
-/**
- * A layout parser that holds an in-memory tree of a given resource for subsequent traversal
- * during the inflation process
- */
-internal class LayoutPullParser : InMemoryParser, AaptAttrParser, ILayoutPullParser {
-  private constructor(inputStream: InputStream) : super() {
-    try {
-      val buffer = inputStream.source().buffer()
-
-      setFeature(FEATURE_PROCESS_NAMESPACES, true)
-      setInput(buffer.peek().inputStream(), null)
-
-      // IntelliJ uses XmlFile/PsiFile to parse tag snapshots,
-      // leaving XmlPullParser for Android to parse resources as usual
-      // Here, we use the same XmlPullParser approach for both, which means
-      // we need reinitialize the document stream between the two passes.
-      val resourceParser = ResourceParser(buffer.inputStream())
-      root = resourceParser.createTagSnapshot()
-
-      // Obtain a list of all the aapt declared attributes
-      declaredAaptAttrs = findDeclaredAaptAttrs(root)
-    } catch (e: XmlPullParserException) {
-      throw IOError(e)
-    }
-  }
-
-  private constructor(aaptResource: TagSnapshot) : super() {
-    root = aaptResource
-    declaredAaptAttrs = emptyMap()
-  }
-
-  private val root: TagSnapshot
-  private val declaredAaptAttrs: Map<String, TagSnapshot>
-
-  private var layoutNamespace = ResourceNamespace.RES_AUTO
-
-  override fun rootTag() = root
-
-  @Suppress("SENSELESS_COMPARISON")
-  override fun getViewCookie(): Any? {
-    // TODO: Implement this properly.
-    val name = super.getName() ?: return null
-
-    // Store tools attributes if this looks like a layout we'll need adapter view
-    // bindings for in the LayoutlibCallback.
-    if (LIST_VIEW == name || EXPANDABLE_LIST_VIEW == name || GRID_VIEW == name || SPINNER == name) {
-      var map: MutableMap<String, String>? = null
-      val count = attributeCount
-      for (i in 0 until count) {
-        val namespace = getAttributeNamespace(i)
-        if (namespace != null && namespace == TOOLS_URI) {
-          val attribute = getAttributeName(i)!!
-          if (attribute == ATTR_IGNORE) {
-            continue
-          }
-          if (map == null) {
-            map = HashMap(4)
-          }
-          map[attribute] = getAttributeValue(i)!!
-        }
-      }
-
-      return map
-    }
-
-    return null
-  }
-
-  override fun getLayoutNamespace(): ResourceNamespace = layoutNamespace
-
-  override fun getAaptDeclaredAttrs(): Map<String, TagSnapshot> = declaredAaptAttrs
-
-  fun setLayoutNamespace(layoutNamespace: ResourceNamespace) {
-    this.layoutNamespace = layoutNamespace
-  }
-
-  private fun findDeclaredAaptAttrs(tag: TagSnapshot): Map<String, TagSnapshot> {
-    if (!tag.hasDeclaredAaptAttrs) {
-      // Nor tag or any of the children has any aapt:attr declarations, we can stop here.
-      return emptyMap()
-    }
-
-    return buildMap {
-      tag.attributes
-        .filterIsInstance<AaptAttrSnapshot>()
-        .forEach { attr ->
-          val bundledTag = attr.bundledTag
-          put(attr.id, bundledTag)
-          for (child in bundledTag.children) {
-            putAll(findDeclaredAaptAttrs(child))
-          }
-        }
-      for (child in tag.children) {
-        putAll(findDeclaredAaptAttrs(child))
-      }
-    }
-  }
-
-  companion object {
-    @Throws(FileNotFoundException::class)
-    fun createFromFile(layoutFile: File) = LayoutPullParser(FileInputStream(layoutFile))
-
-    /**
-     * @param layoutPath Must start with '/' and be relative to test resources.
-     */
-    fun createFromPath(layoutPath: String): LayoutPullParser {
-      @Suppress("NAME_SHADOWING") var layoutPath = layoutPath
-      if (layoutPath.startsWith("/")) {
-        layoutPath = layoutPath.substring(1)
-      }
-
-      return LayoutPullParser(
-        LayoutPullParser::class.java.classLoader!!.getResourceAsStream(layoutPath)
-      )
-    }
-
-    fun createFromString(contents: String): LayoutPullParser {
-      return LayoutPullParser(
-        ByteArrayInputStream(contents.toByteArray(Charset.forName("UTF-8")))
-      )
-    }
-
-    fun createFromAaptResource(aaptResource: TagSnapshot): LayoutPullParser {
-      return LayoutPullParser(aaptResource)
-    }
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/ResourceParser.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/ResourceParser.kt
deleted file mode 100644
index f90475b..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/ResourceParser.kt
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2021 Square, Inc.
- *
- * 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 app.cash.paparazzi.internal.parsers
-
-import com.android.SdkConstants.AAPT_URI
-import com.android.SdkConstants.TAG_ATTR
-import java.io.InputStream
-import org.kxml2.io.KXmlParser
-
-/**
- * An XML resource parser that creates a tree of [TagSnapshot]s
- */
-class ResourceParser(inputStream: InputStream) : KXmlParser() {
-  init {
-    setFeature(FEATURE_PROCESS_NAMESPACES, true)
-    setInput(inputStream, null)
-
-    require(START_DOCUMENT, null, null)
-    next()
-  }
-
-  fun createTagSnapshot(): TagSnapshot {
-    require(START_TAG, null, null)
-
-    // need to store now, since TagSnapshot is created on end tag after parser mark has moved
-    val tagName = name
-    val tagNamespace = namespace
-    val prefix = prefix
-
-    val attributes = createAttributesForTag()
-
-    var hasDeclaredAaptAttrs = false
-    var last: TagSnapshot? = null
-    val children = mutableListOf<TagSnapshot>()
-    while (eventType != END_DOCUMENT) {
-      when (next()) {
-        START_TAG -> {
-          if (AAPT_URI == namespace) {
-            if (TAG_ATTR == name) {
-              val attrAttribute = createAttrTagSnapshot()
-              if (attrAttribute != null) {
-                attributes += attrAttribute
-                hasDeclaredAaptAttrs = true
-              }
-            }
-            // Since we save the aapt:attr tags as an attribute, we do not save them as a child element. Skip.
-          } else {
-            val child = createTagSnapshot()
-            hasDeclaredAaptAttrs = hasDeclaredAaptAttrs || child.hasDeclaredAaptAttrs
-            children += child
-            if (last != null) {
-              last.next = child
-            }
-            last = child
-          }
-        }
-        END_TAG -> {
-          return TagSnapshot(
-            tagName,
-            tagNamespace,
-            prefix,
-            attributes,
-            children.toList(),
-            hasDeclaredAaptAttrs
-          )
-        }
-      }
-    }
-
-    throw IllegalStateException("We should never reach here")
-  }
-
-  private fun createAttrTagSnapshot(): AaptAttrSnapshot? {
-    require(START_TAG, null, "attr")
-
-    val name = getAttributeValue(null, "name") ?: return null
-    val prefix = findPrefixByQualifiedName(name)
-    val namespace = getNamespace(prefix)
-    val localName = findLocalNameByQualifiedName(name)
-    val id = (++uniqueId).toString()
-
-    var bundleTagSnapshot: TagSnapshot? = null
-    loop@ while (eventType != END_TAG) {
-      when (nextTag()) {
-        START_TAG -> {
-          bundleTagSnapshot = createTagSnapshot()
-        }
-        END_TAG -> {
-          break@loop
-        }
-      }
-    }
-
-    return if (bundleTagSnapshot != null) {
-      // swallow end tag
-      nextTag()
-      require(END_TAG, null, "attr")
-
-      AaptAttrSnapshot(namespace, prefix, localName, id, bundleTagSnapshot)
-    } else {
-      null
-    }
-  }
-
-  private fun findPrefixByQualifiedName(name: String): String {
-    val prefixEnd = name.indexOf(':')
-    return if (prefixEnd > 0) {
-      name.substring(0, prefixEnd)
-    } else ""
-  }
-
-  private fun findLocalNameByQualifiedName(name: String): String {
-    return name.substring(name.indexOf(':') + 1)
-  }
-
-  private fun createAttributesForTag(): MutableList<AttributeSnapshot> {
-    return buildList {
-      for (i in 0 until attributeCount) {
-        add(
-          AttributeSnapshot(
-            getAttributeNamespace(i),
-            getAttributePrefix(i),
-            getAttributeName(i),
-            getAttributeValue(i)
-          )
-        )
-      }
-    }.toMutableList()
-  }
-
-  companion object {
-    private var uniqueId = 0L
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/TagSnapshot.kt b/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/TagSnapshot.kt
deleted file mode 100644
index 19cab20..0000000
--- a/external/paparazzi/paparazzi/src/main/java/app/cash/paparazzi/internal/parsers/TagSnapshot.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2021 Square, Inc.
- *
- * 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 app.cash.paparazzi.internal.parsers
-
-/**
- * Derived from https://cs.android.com/android-studio/platform/tools/adt/idea/+/mirror-goog-studio-master-dev:android/src/com/android/tools/idea/rendering/parsers/TagSnapshot.java
- *
- * A snapshot of the state of an xml tag.
- *
- * Used by the rendering architecture to be able to hold a consistent view of
- * the layout files across a long rendering operation without holding read locks,
- * as well as to for example let the property sheet evaluate and paint the values
- * of properties as they were at the time of rendering, not as they are at the current
- * instant.
- */
-data class TagSnapshot(
-  val name: String,
-  val namespace: String,
-  val prefix: String?,
-  val attributes: List<AttributeSnapshot>,
-  val children: List<TagSnapshot>,
-  val hasDeclaredAaptAttrs: Boolean = false
-) {
-  var next: TagSnapshot? = null
-
-  @Suppress("unused") // Used for debugging
-  fun printFormatted(): String {
-    indent++
-    val output = """
-      |$name:
-      |${pad(indent + 1)}attributes: ${print(attributes)}
-      |${pad(indent + 1)}children: ${print(children)} 
-    """.trimMargin()
-    indent--
-    return output
-  }
-
-  private fun print(children: List<*>): String {
-    if (children.isEmpty()) return children.toString()
-
-    indent++
-    val output = children.joinToString(
-      prefix = "[\n${pad(indent + 1)}",
-      separator = "\n${pad(indent + 1)}",
-      postfix = "\n${pad(indent)}]"
-    )
-    indent--
-    return output
-  }
-
-  private fun pad(length: Int): String = "  ".repeat(length)
-
-  companion object {
-    var indent = -1
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/main/resources/index.html b/external/paparazzi/paparazzi/src/main/resources/index.html
deleted file mode 100644
index 327f8b0..0000000
--- a/external/paparazzi/paparazzi/src/main/resources/index.html
+++ /dev/null
@@ -1,91 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <style type="text/css">
-    body {
-      background: #212121;
-      text-align: center;
-    }
-
-    .screen {
-      margin: 0.2em;
-      display: inline-block;
-      position: relative;
-      overflow: hidden;
-    }
-
-    .screen img, .screen video {
-      width: 300px;
-    }
-
-    div.overlay__hovered {
-        display: block;
-    }
-
-    .overlay {
-      position: absolute;
-      bottom: 0;
-      left: 0;
-      right: 0;
-      background: rgba(25, 0, 237, .68);
-      color: #fff;
-      opacity: 0;
-      display: none;
-      transition: 150ms;
-
-       -webkit-animation-name: slideIn;
-       -webkit-animation-duration: 0.4s;
-      animation-name: slideIn;
-      animation-duration: 0.4s;
-      animation-fill-mode: forwards;
-    }
-
-    @-webkit-keyframes slideIn {
-      from {bottom: -300px; opacity: 0}
-      to {bottom: 0; opacity: 1}
-    }
-
-    @keyframes slideIn {
-      from {bottom: -300px; opacity: 0}
-      to {bottom: 0; opacity: 1}
-    }
-
-    .test__details {
-      text-align: left;
-      padding-left: 1em;
-    }
-
-    .test__details__name,
-    .test__details__class,
-    .test__details__package {
-      line-height: 0.7em;
-    }
-
-    .test__details__timestamp {
-      margin-top: 2em;
-    }
-
-    .test__details__selector {
-      width: 16px;
-      height: 16px;
-      border-radius: 50%;
-      display: inline-block;
-      border: 2px solid #fff;
-      margin: .1em;
-      margin-bottom: 1.3em;
-      margin-top: 1em;
-    }
-
-    .test__details__selector:hover {
-      background-color: white;
-    }
-    </style>
-</head>
-
-<script src="index.js"></script>
-<script src="paparazzi.js"></script>
-
-<body >
-  <span id="rootContainer"/>
-</body>
-</html>
diff --git a/external/paparazzi/paparazzi/src/main/resources/paparazzi.js b/external/paparazzi/paparazzi/src/main/resources/paparazzi.js
deleted file mode 100644
index 5c12ab1..0000000
--- a/external/paparazzi/paparazzi/src/main/resources/paparazzi.js
+++ /dev/null
@@ -1,222 +0,0 @@
-window.runs = {};
-
-class Run {
-  constructor(id, data) {
-    this.id = id;
-    // TODO(oldergod) which entries are required/optional?
-    this.data = data;
-  }
-}
-
-class Shot {
-  constructor(name, test) {
-    this.name = name;
-    this.test = test;
-
-    [, this.package, this.clazz, this.method] = Shot.TestMethodRegex.exec(test);
-
-    this.runs = [];
-  }
-
-  static get TestMethodRegex() {
-    return /^(.*)\.(.*)#(.*)$/;
-  }
-
-  addRun(runId, file, timestamp) {
-    this.runs.push(
-      {
-        'id': runId,
-        'file': file,
-        'timestamp': timestamp
-      }
-    );
-
-    if (file.endsWith('.png')) {
-      this.img.src = file;
-      this.img.style.display = 'inline';
-      this.video.style.display = 'none';
-    } else {
-      this.video.src = file;
-      this.video.style.display = 'inline';
-      this.img.style.display = 'none';
-    }
-    this.timestampP.innerText = timestamp;
-
-    const circle = document.createElement('div');
-    circle.classList.add('test__details__selector', `run-${runId}`);
-    circle. (e) {
-      if (file.endsWith('.png')) {
-        this.img.src = file;
-      } else {
-        this.video.src = file;
-      }
-
-      for (let shot of Object.values(paparazziRenderer.shots)) {
-        let found = false;
-        for (let run of shot.runs) {
-          if (runId == run.id) {
-            shot.img.src = run.file;
-            shot.timestampP.innerText = run.timestamp;
-
-            found = true;
-            break;
-          }
-        }
-        shot.img.style.opacity = found ? "1" : "0.3";
-      }
-    }.bind(this);
-    this.overlayDiv.appendChild(circle);
-  }
-
-  removeRun(runId) {
-    const index = this.runs.indexOf((run) => run.id == runId);
-    if (index == -1) return;
-
-    this.runs.splice(index, 1);
-  }
-
-  inflate() {
-    const screenDiv = document.createElement('div');
-    screenDiv.classList.add('screen');
-
-    document.rootContainer.appendChild(screenDiv);
-
-    const img = document.createElement('img');
-    const video = document.createElement('video');
-    video.autoplay = 'autoplay';
-    video.muted = 'muted';
-    video.loop = 'loop';
-
-    const overlayDiv = document.createElement('div');
-    overlayDiv.classList.add('overlay');
-
-    screenDiv.appendChild(img);
-    screenDiv.appendChild(video);
-    screenDiv.appendChild(overlayDiv);
-    screenDiv. (e) {
-      overlayDiv.classList.add('overlay__hovered');
-    }.bind(this);
-    screenDiv. (e) {
-      overlayDiv.classList.remove('overlay__hovered');
-    }.bind(this);
-
-    const nameP = document.createElement('p');
-    nameP.classList.add('test__details', 'test__details__name');
-
-    const classP = document.createElement('p');
-    classP.classList.add('test__details', 'test__details__class');
-
-    const packageP = document.createElement('p');
-    packageP.classList.add('test__details', 'test__details__package');
-
-    const timestampP = document.createElement('p');
-    timestampP.classList.add('test__details', 'test__details__timestamp');
-
-    overlayDiv.appendChild(nameP);
-    overlayDiv.appendChild(classP);
-    overlayDiv.appendChild(packageP);
-    overlayDiv.appendChild(timestampP);
-
-    nameP.innerText = this.method;
-    if (this.name !== undefined) {
-      nameP.innerText += ` ${this.name}`;
-    }
-    classP.innerText = this.clazz;
-    packageP.innerText = this.package;
-
-    // hold references to the DOM for later updates
-    this.img = img;
-    this.video = video;
-    this.timestampP = timestampP;
-    this.overlayDiv = overlayDiv;
-  }
-}
-
-class PaparazziRenderer {
-  constructor() {
-    // Used for content comparison for we only re-render the updated ones.
-    this.currentRuns = {};
-    // Used to store runs we know won't be updated anymore.
-    this.lockedRunIds = [];
-    this.shots = {}; // Key is `${test}${name}`, Value is a Shot.
-  }
-
-  start() {
-    this.loadRunScript('index.js');
-    for (let runId of window.all_runs) {
-      this.loadRunScript(`runs/${runId}.js`);
-    }
-    setInterval(this.refresh.bind(this), 100);
-  }
-
-  render(run) {
-    if (this.currentRuns[run.id]
-      && JSON.stringify(this.currentRuns[run.id]) == JSON.stringify(run)) {
-      // This run didn't change.
-      return;
-    }
-    this.currentRuns[run.id] = run;
-    console.log('rendering', run);
-
-    for (let datum of run.data) {
-      const key = `${datum.testName}${datum.name}`;
-      let shot = this.shots[key];
-      if (!shot) {
-        console.log('New shot detected', shot);
-        shot = new Shot(datum.name, datum.testName);
-        this.shots[key] = shot;
-        shot.inflate();
-      } else {
-        //shot.removeRun(run.id);
-      }
-
-      console.log('Adding run to shot', shot);
-      shot.addRun(run.id, datum.file, datum.timestamp);
-
-      // TODO setup listeners for filters/hovering, etc
-    }
-  }
-
-  renderAll() {
-    this.loadRunScript('index.js');
-    for (let runId of window.all_runs) {
-      if (this.lockedRunIds.includes(runId)) {
-        continue;
-      }
-      // The js loading is async so the rendering can happen in the next refresh
-      this.loadRunScript(`runs/${runId}.js`);
-
-      this.render(new Run(runId, window.runs[runId]));
-
-      const lastRunId = window.all_runs[window.all_runs.length - 1];
-      if (runId != lastRunId) {
-        // This run isn't the last run so we know it ain't gonna be updated.
-        this.lockedRunIds.push(runId);
-        delete this.currentRuns[runId];
-      }
-    }
-  }
-
-  refresh() {
-    if (window.all_runs.length == 0) return;
-
-    this.renderAll();
-  }
-
-  loadRunScript(js) {
-    const script = document.createElement('script');
-    script.src = js;
-    script. () {
-      this.remove();
-    }
-    document.head.appendChild(script);
-  }
-}
-
-const paparazziRenderer = new PaparazziRenderer();
-console.log(paparazziRenderer);
-
-function bootstrap() {
-  document.rootContainer = document.getElementById('rootContainer');
-  paparazziRenderer.start();
-}
diff --git a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/HtmlReportWriterTest.kt b/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/HtmlReportWriterTest.kt
deleted file mode 100644
index 80979c7..0000000
--- a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/HtmlReportWriterTest.kt
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2019 Square, Inc.
- *
- * 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 app.cash.paparazzi
-
-import java.awt.image.BufferedImage
-import java.io.File
-import java.nio.file.Files
-import java.nio.file.Path
-import java.nio.file.attribute.BasicFileAttributes
-import java.nio.file.attribute.FileTime
-import java.time.Instant
-import java.util.Date
-import org.assertj.core.api.Assertions.assertThat
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.TemporaryFolder
-
-class HtmlReportWriterTest {
-  @get:Rule
-  val reportRoot: TemporaryFolder = TemporaryFolder()
-
-  @get:Rule
-  val snapshotRoot: TemporaryFolder = TemporaryFolder()
-
-  private val anyImage = BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)
-  private val anyImageHash = "9069ca78e7450a285173431b3e52c5c25299e473"
-
-  @Test
-  fun happyPath() {
-    val htmlReportWriter = HtmlReportWriter("run_one", reportRoot.root)
-    htmlReportWriter.use {
-      val frameHandler = htmlReportWriter.newFrameHandler(
-        Snapshot(
-          name = "loading",
-          testName = TestName("app.cash.paparazzi", "CelebrityTest", "testSettings"),
-          timestamp = Instant.parse("2019-03-20T10:27:43Z").toDate(),
-          tags = listOf("redesign")
-        ),
-        1,
-        -1
-      )
-      frameHandler.use {
-        frameHandler.handle(anyImage)
-      }
-    }
-
-    assertThat(File("${reportRoot.root}/index.js")).hasContent(
-      """
-        |window.all_runs = [
-        |  "run_one"
-        |];
-        |
-      """.trimMargin()
-    )
-
-    assertThat(File("${reportRoot.root}/runs/run_one.js")).hasContent(
-      """
-        |window.runs["run_one"] = [
-        |  {
-        |    "name": "loading",
-        |    "testName": "app.cash.paparazzi.CelebrityTest#testSettings",
-        |    "timestamp": "2019-03-20T10:27:43.000Z",
-        |    "tags": [
-        |      "redesign"
-        |    ],
-        |    "file": "images/$anyImageHash.png"
-        |  }
-        |];
-        |
-      """.trimMargin()
-    )
-  }
-
-  @Test
-  fun sanitizeForFilename() {
-    assertThat("0 Dollars".sanitizeForFilename()).isEqualTo("0_dollars")
-    assertThat("`!#$%&*+=|\\'\"<>?/".sanitizeForFilename()).isEqualTo("_________________")
-    assertThat("~@^()[]{}:;,.".sanitizeForFilename()).isEqualTo("~@^()[]{}:;,.")
-  }
-
-  @Test
-  fun noSnapshotOnFailure() {
-    val htmlReportWriter = HtmlReportWriter("run_one", reportRoot.root)
-    htmlReportWriter.use {
-      val frameHandler = htmlReportWriter.newFrameHandler(
-        snapshot = Snapshot(
-          name = "loading",
-          testName = TestName("app.cash.paparazzi", "CelebrityTest", "testSettings"),
-          timestamp = Instant.parse("2019-03-20T10:27:43Z").toDate()
-        ),
-        frameCount = 4,
-        fps = -1
-      )
-      frameHandler.use {
-        // intentionally empty, to simulate no content written on exception
-      }
-    }
-
-    assertThat(File(reportRoot.root, "images")).isEmptyDirectory
-    assertThat(File(reportRoot.root, "videos")).isEmptyDirectory
-  }
-
-  @Test
-  fun alwaysOverwriteOnRecord() {
-    // set record mode
-    System.setProperty("paparazzi.test.record", "true")
-
-    val htmlReportWriter = HtmlReportWriter("record_run", reportRoot.root, snapshotRoot.root)
-    htmlReportWriter.use {
-      val now = Instant.parse("2021-02-23T10:27:43Z")
-      val snapshot = Snapshot(
-        name = "test",
-        testName = TestName("app.cash.paparazzi", "HomeView", "testSettings"),
-        timestamp = now.toDate()
-      )
-      val file =
-        File("${snapshotRoot.root}/images/app.cash.paparazzi_HomeView_testSettings_test.png")
-      val golden = file.toPath()
-
-      // precondition
-      assertThat(golden).doesNotExist()
-
-      // take 1
-      val frameHandler1 = htmlReportWriter.newFrameHandler(
-        snapshot = snapshot,
-        frameCount = 1,
-        fps = -1
-      )
-      frameHandler1.use { frameHandler1.handle(anyImage) }
-      assertThat(golden).exists()
-      val timeFirstWrite = golden.lastModifiedTime()
-
-      // I know....but guarantees writes won't happen in same tick
-      Thread.sleep(100)
-
-      // take 2
-      val frameHandler2 = htmlReportWriter.newFrameHandler(
-        snapshot = snapshot.copy(timestamp = now.plusSeconds(1).toDate()),
-        frameCount = 1,
-        fps = -1
-      )
-      frameHandler2.use { frameHandler2.handle(anyImage) }
-      assertThat(golden).exists()
-      val timeOverwrite = golden.lastModifiedTime()
-
-      // should always overwrite
-      assertThat(timeOverwrite).isGreaterThan(timeFirstWrite)
-    }
-  }
-
-  private fun Instant.toDate() = Date(toEpochMilli())
-
-  private fun Path.lastModifiedTime(): FileTime {
-    return Files.readAttributes(this, BasicFileAttributes::class.java).lastModifiedTime()
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/PaparazziTest.kt b/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/PaparazziTest.kt
deleted file mode 100644
index 356a6c8..0000000
--- a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/PaparazziTest.kt
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) 2019 Square, Inc.
- *
- * 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 app.cash.paparazzi
-
-import android.animation.AnimationHandler
-import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
-import android.animation.ValueAnimator
-import android.graphics.Canvas
-import android.graphics.Color
-import android.view.Choreographer
-import android.view.Choreographer.CALLBACK_ANIMATION
-import android.view.View
-import android.view.animation.LinearInterpolator
-import android.widget.Button
-import com.android.internal.lang.System_Delegate
-import java.util.concurrent.TimeUnit
-import org.assertj.core.api.Assertions.assertThat
-import org.junit.Ignore
-import org.junit.Rule
-import org.junit.Test
-
-class PaparazziTest {
-  @get:Rule
-  val paparazzi = Paparazzi()
-
-  @Ignore("b/245941625")
-  @Test
-  fun drawCalls() {
-    val log = mutableListOf<String>()
-
-    val view = object : View(paparazzi.context) {
-      override fun onDraw(canvas: Canvas) {
-        log += "onDraw time=$time"
-      }
-    }
-
-    paparazzi.snapshot(view)
-
-    assertThat(log).containsExactly("onDraw time=0")
-  }
-
-  @Ignore("b/245941625")
-  @Test
-  fun resetsAnimationHandler() {
-    assertThat(AnimationHandler.sAnimatorHandler.get()).isNull()
-
-    // Why Button?  Because it sets a StateListAnimator on window attach
-    // See https://github.com/cashapp/paparazzi/pull/319
-    paparazzi.snapshot(Button(paparazzi.context))
-
-    assertThat(AnimationHandler.sAnimatorHandler.get()).isNull()
-  }
-
-  @Ignore("b/245941625")
-  @Test
-  fun animationEvents() {
-    val log = mutableListOf<String>()
-
-    val animator = ValueAnimator.ofFloat(0.0f, 1.0f)
-    animator.addListener(object : AnimatorListenerAdapter() {
-      override fun onAnimationStart(animation: Animator) {
-        log += "onAnimationStart time=$time animationElapsed=${animator.animatedValue}"
-      }
-
-      override fun onAnimationEnd(animation: Animator) {
-        log += "onAnimationEnd time=$time animationElapsed=${animator.animatedValue}"
-      }
-    })
-
-    val view = object : View(paparazzi.context) {
-      override fun onDraw(canvas: Canvas) {
-        log += "onDraw time=$time animationElapsed=${animator.animatedValue}"
-      }
-    }
-
-    animator.addUpdateListener {
-      log += "onAnimationUpdate time=$time animationElapsed=${animator.animatedValue}"
-
-      val colorComponent = it.animatedFraction
-      view.setBackgroundColor(Color.argb(1f, colorComponent, colorComponent, colorComponent))
-    }
-
-    animator.startDelay = 2_000L
-    animator.duration = 1_000L
-    animator.interpolator = LinearInterpolator()
-    animator.start()
-
-    paparazzi.gif(view, start = 1_000L, end = 4_000L, fps = 4)
-
-    assertThat(log).containsExactly(
-      "onDraw time=1000 animationElapsed=0.0",
-      "onAnimationStart time=2000 animationElapsed=0.0",
-      "onAnimationUpdate time=2000 animationElapsed=0.0",
-      "onDraw time=2000 animationElapsed=0.0",
-      "onAnimationUpdate time=2250 animationElapsed=0.25",
-      "onDraw time=2250 animationElapsed=0.25",
-      "onAnimationUpdate time=2500 animationElapsed=0.5",
-      "onDraw time=2500 animationElapsed=0.5",
-      "onAnimationUpdate time=2750 animationElapsed=0.75",
-      "onDraw time=2750 animationElapsed=0.75",
-      "onAnimationUpdate time=3000 animationElapsed=1.0",
-      "onAnimationEnd time=3000 animationElapsed=1.0",
-      "onDraw time=3000 animationElapsed=1.0"
-    )
-  }
-
-  @Test
-  @Ignore
-  fun frameCallbacksExecutedAfterLayout() {
-    val log = mutableListOf<String>()
-
-    val view = object : View(paparazzi.context) {
-      override fun onAttachedToWindow() {
-        super.onAttachedToWindow()
-        Choreographer.getInstance()
-          .postCallback(
-            CALLBACK_ANIMATION,
-            { log += "view width=$width height=$height" },
-            false
-          )
-      }
-    }
-
-    paparazzi.snapshot(view)
-
-    assertThat(log).containsExactly("view width=1080 height=1776")
-  }
-
-  @Ignore("b/245941625")
-  @Test
-  fun throwsRenderingExceptions() {
-    val view = object : View(paparazzi.context) {
-      override fun onAttachedToWindow() {
-        throw Throwable("Oops")
-      }
-    }
-
-    val thrown = try {
-      paparazzi.snapshot(view)
-      false
-    } catch (exception: Throwable) {
-      true
-    }
-
-    assertThat(thrown).isTrue
-  }
-
-  private val time: Long
-    get() {
-      return TimeUnit.NANOSECONDS.toMillis(System_Delegate.nanoTime() - Paparazzi.TIME_OFFSET_NANOS)
-    }
-}
diff --git a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/R.kt b/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/R.kt
deleted file mode 100644
index 5827e33..0000000
--- a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/R.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2019 Square, Inc.
- *
- * 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 app.cash.paparazzi
-
-/** Simulate an empty R.java for this package. */
-class R
diff --git a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/RenderingModeTest.kt b/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/RenderingModeTest.kt
deleted file mode 100644
index d774099..0000000
--- a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/RenderingModeTest.kt
+++ /dev/null
@@ -1,166 +0,0 @@
-package app.cash.paparazzi
-
-import android.content.Context
-import android.graphics.Color
-import android.graphics.drawable.GradientDrawable
-import android.view.Gravity
-import android.view.View
-import android.view.ViewGroup
-import android.widget.Button
-import android.widget.LinearLayout
-import android.widget.TextView
-import app.cash.paparazzi.internal.ImageUtils
-import com.android.ide.common.rendering.api.SessionParams
-import java.awt.image.BufferedImage
-import java.io.File
-import javax.imageio.ImageIO
-import org.junit.Ignore
-import org.junit.Test
-import org.junit.runner.Description
-
-class RenderingModeTest {
-
-  @Ignore("b/245941625")
-  @Test
-  fun `shrinks to wrap view`() {
-    Paparazzi(
-      snapshotHandler = TestSnapshotVerifier(),
-      deviceConfig = DeviceConfig.NEXUS_5.copy(
-        softButtons = false
-      ),
-      renderingMode = SessionParams.RenderingMode.SHRINK
-    ).runTest("shrinks to wrap view") {
-      val view = buildView(
-        context,
-        ViewGroup.LayoutParams(
-          ViewGroup.LayoutParams.WRAP_CONTENT,
-          ViewGroup.LayoutParams.WRAP_CONTENT
-        )
-      )
-      snapshot(view, "rendering-mode-shrink")
-    }
-  }
-
-  @Ignore("b/245941625")
-  @Test
-  fun `renders full device with RenderingMode NORMAL`() {
-    Paparazzi(
-      snapshotHandler = TestSnapshotVerifier(true),
-      deviceConfig = DeviceConfig.NEXUS_5.copy(
-        softButtons = false
-      ),
-      renderingMode = SessionParams.RenderingMode.NORMAL
-    ).runTest("renders full device with RenderingMode NORMAL") {
-      val view = buildView(
-        context,
-        ViewGroup.LayoutParams(
-          ViewGroup.LayoutParams.WRAP_CONTENT,
-          ViewGroup.LayoutParams.WRAP_CONTENT
-        )
-      )
-      snapshot(view, "rendering-mode-normal")
-    }
-  }
-
-  private fun Paparazzi.runTest(name: String, body: Paparazzi.() -> Unit) {
-    try {
-      prepare(Description.createTestDescription(this@RenderingModeTest::class.java, name))
-      body()
-    } finally {
-      close()
-    }
-  }
-
-  private fun buildView(
-    context: Context,
-    rootLayoutParams: ViewGroup.LayoutParams? = ViewGroup.LayoutParams(
-      ViewGroup.LayoutParams.MATCH_PARENT,
-      ViewGroup.LayoutParams.MATCH_PARENT
-    )
-  ) =
-    LinearLayout(context).apply {
-      orientation = LinearLayout.VERTICAL
-      rootLayoutParams?.let { layoutParams = it }
-      addView(
-        TextView(context).apply {
-          id = 1
-          text = "Text View Sample"
-        }
-      )
-
-      addView(
-        View(context).apply {
-          id = 2
-          layoutParams = LinearLayout.LayoutParams(100, 100)
-          contentDescription = "Content Description Sample"
-        }
-      )
-
-      addView(
-        View(context).apply {
-          id = 3
-          layoutParams = LinearLayout.LayoutParams(100, 100).apply {
-            setMarginsRelative(20, 20, 20, 20)
-          }
-          contentDescription = "Margin Sample"
-        }
-      )
-
-      addView(
-        View(context).apply {
-          id = 4
-          layoutParams = LinearLayout.LayoutParams(100, 100).apply {
-            setMarginsRelative(20, 20, 20, 20)
-          }
-          foreground = GradientDrawable(
-            GradientDrawable.Orientation.TL_BR,
-            intArrayOf(Color.YELLOW, Color.BLUE)
-          ).apply {
-            shape = GradientDrawable.OVAL
-          }
-          contentDescription = "Foreground Drawable"
-        }
-      )
-
-      addView(
-        Button(context).apply {
-          id = 5
-          layoutParams = LinearLayout.LayoutParams(
-            ViewGroup.LayoutParams.WRAP_CONTENT,
-            ViewGroup.LayoutParams.WRAP_CONTENT
-          ).apply {
-            gravity = Gravity.CENTER
-          }
-          text = "Button Sample"
-        }
-      )
-    }
-}
-
-private class TestSnapshotVerifier(val writeImages: Boolean = false) : SnapshotHandler {
-  override fun newFrameHandler(
-    snapshot: Snapshot,
-    frameCount: Int,
-    fps: Int
-  ): SnapshotHandler.FrameHandler {
-    return object : SnapshotHandler.FrameHandler {
-      override fun handle(image: BufferedImage) {
-        val expected = File("src/test/resources/${snapshot.name}.png")
-        if (writeImages) {
-          ImageIO.write(image, "png", expected)
-        } else {
-          ImageUtils.assertImageSimilar(
-            relativePath = expected.path,
-            image = image,
-            goldenImage = ImageIO.read(expected),
-            maxPercentDifferent = 0.1
-          )
-        }
-      }
-
-      override fun close() = Unit
-    }
-  }
-
-  override fun close() = Unit
-}
diff --git a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/accessibility/AccessibilityRenderExtensionTest.kt b/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/accessibility/AccessibilityRenderExtensionTest.kt
deleted file mode 100644
index b9afe6e..0000000
--- a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/accessibility/AccessibilityRenderExtensionTest.kt
+++ /dev/null
@@ -1,152 +0,0 @@
-package app.cash.paparazzi.accessibility
-
-import android.content.Context
-import android.graphics.Color
-import android.graphics.drawable.GradientDrawable
-import android.graphics.drawable.GradientDrawable.OVAL
-import android.graphics.drawable.GradientDrawable.Orientation.TL_BR
-import android.view.Gravity
-import android.view.View
-import android.view.ViewGroup
-import android.widget.Button
-import android.widget.LinearLayout
-import android.widget.TextView
-import app.cash.paparazzi.DeviceConfig
-import app.cash.paparazzi.Paparazzi
-import app.cash.paparazzi.Snapshot
-import app.cash.paparazzi.SnapshotHandler
-import app.cash.paparazzi.internal.ImageUtils
-import java.awt.image.BufferedImage
-import java.io.File
-import javax.imageio.ImageIO
-import org.junit.Ignore
-import org.junit.Rule
-import org.junit.Test
-
-class AccessibilityRenderExtensionTest {
-  private val snapshotHandler = TestSnapshotVerifier()
-
-  @get:Rule
-  val paparazzi = Paparazzi(
-    deviceConfig = DeviceConfig.NEXUS_5.copy(
-      // Needed to render accessibility content next to main content.
-      screenWidth = DeviceConfig.NEXUS_5.screenWidth * 2,
-      softButtons = false
-    ),
-    snapshotHandler = snapshotHandler,
-    renderExtensions = setOf(AccessibilityRenderExtension())
-  )
-
-  @Ignore("b/245941625")
-  @Test
-  fun `verify baseline`() {
-    val view = buildView(paparazzi.context)
-    paparazzi.snapshot(view, name = "accessibility")
-  }
-
-  @Ignore("b/245941625")
-  @Test
-  fun `test without layout params set`() {
-    val view = buildView(paparazzi.context, null)
-    paparazzi.snapshot(view, name = "without-layout-params")
-  }
-
-  @Ignore("b/245941625")
-  @Test
-  fun `verify changing view hierarchy order doesn't change accessibility colors`() {
-    val view = buildView(paparazzi.context).apply {
-      addView(
-        View(context).apply { contentDescription = "Empty View" },
-        0,
-        LinearLayout.LayoutParams(0, 0)
-      )
-    }
-    paparazzi.snapshot(view, name = "accessibility-new-view")
-  }
-
-  private fun buildView(
-    context: Context,
-    rootLayoutParams: ViewGroup.LayoutParams? = ViewGroup.LayoutParams(
-      ViewGroup.LayoutParams.MATCH_PARENT,
-      ViewGroup.LayoutParams.MATCH_PARENT
-    )
-  ) =
-    LinearLayout(context).apply {
-      orientation = LinearLayout.VERTICAL
-      rootLayoutParams?.let { layoutParams = it }
-      addView(
-        TextView(context).apply {
-          id = 1
-          text = "Text View Sample"
-        }
-      )
-
-      addView(
-        View(context).apply {
-          id = 2
-          layoutParams = LinearLayout.LayoutParams(100, 100)
-          contentDescription = "Content Description Sample"
-        }
-      )
-
-      addView(
-        View(context).apply {
-          id = 3
-          layoutParams = LinearLayout.LayoutParams(100, 100).apply {
-            setMarginsRelative(20, 20, 20, 20)
-          }
-          contentDescription = "Margin Sample"
-        }
-      )
-
-      addView(
-        View(context).apply {
-          id = 4
-          layoutParams = LinearLayout.LayoutParams(100, 100).apply {
-            setMarginsRelative(20, 20, 20, 20)
-          }
-          foreground = GradientDrawable(TL_BR, intArrayOf(Color.YELLOW, Color.BLUE)).apply {
-            shape = OVAL
-          }
-          contentDescription = "Foreground Drawable"
-        }
-      )
-
-      addView(
-        Button(context).apply {
-          id = 5
-          layoutParams = LinearLayout.LayoutParams(
-            ViewGroup.LayoutParams.WRAP_CONTENT,
-            ViewGroup.LayoutParams.WRAP_CONTENT
-          ).apply {
-            gravity = Gravity.CENTER
-          }
-          text = "Button Sample"
-        }
-      )
-    }
-
-  private class TestSnapshotVerifier : SnapshotHandler {
-    override fun newFrameHandler(
-      snapshot: Snapshot,
-      frameCount: Int,
-      fps: Int
-    ): SnapshotHandler.FrameHandler {
-      return object : SnapshotHandler.FrameHandler {
-        override fun handle(image: BufferedImage) {
-          val expected = File("src/test/resources/${snapshot.name}.png")
-          ImageUtils.assertImageSimilar(
-            relativePath = expected.path,
-            image = image,
-            goldenImage = ImageIO.read(expected),
-            maxPercentDifferent = 0.1
-          )
-        }
-
-        override fun close() = Unit
-      }
-    }
-
-    override fun close() = Unit
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/internal/PaparazziJsonTest.kt b/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/internal/PaparazziJsonTest.kt
deleted file mode 100644
index 9752037..0000000
--- a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/internal/PaparazziJsonTest.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2019 Square, Inc.
- *
- * 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 app.cash.paparazzi.internal
-
-import app.cash.paparazzi.TestName
-import org.assertj.core.api.Assertions.assertThat
-import org.junit.Test
-
-class PaparazziJsonTest {
-  @Test
-  fun testName() {
-    val adapter = PaparazziJson.moshi.adapter(TestName::class.java)
-    val testName = TestName("app.cash.paparazzi", "CelebrityTest", "testSettings")
-    val json = "\"app.cash.paparazzi.CelebrityTest#testSettings\""
-    assertThat(adapter.toJson(testName)).isEqualTo(json)
-    assertThat(adapter.fromJson(json)).isEqualTo(testName)
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/internal/PaparazziLoggerTest.kt b/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/internal/PaparazziLoggerTest.kt
deleted file mode 100644
index 89d7823..0000000
--- a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/internal/PaparazziLoggerTest.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-package app.cash.paparazzi.internal
-
-import app.cash.paparazzi.internal.PaparazziLogger.MultipleFailuresException
-import java.io.FileNotFoundException
-import org.assertj.core.api.Assertions.assertThat
-import org.assertj.core.api.Assertions.fail
-import org.junit.Test
-
-class PaparazziLoggerTest {
-  @Test
-  fun testNoErrors() {
-    val logger = PaparazziLogger()
-
-    try {
-      logger.assertNoErrors()
-    } catch (ignored: Exception) {
-      fail("Did not expect exception to be thrown: $ignored")
-    }
-  }
-
-  @Test
-  fun testSingleError() {
-    val logger = PaparazziLogger()
-    logger.error(FileNotFoundException("error1"), null)
-
-    try {
-      logger.assertNoErrors()
-      fail("Expected exception to be thrown")
-    } catch (ignored: Exception) {
-      assertThat(ignored).isInstanceOf(FileNotFoundException::class.java)
-    }
-  }
-
-  @Test
-  fun testMultipleErrors() {
-    val logger = PaparazziLogger()
-    logger.error(FileNotFoundException("error1"), null)
-    logger.error("tag", null, IllegalStateException("error2"), null, null)
-
-    try {
-      logger.assertNoErrors()
-      fail("Expected exceptions to be thrown")
-    } catch (ignored: Exception) {
-      assertThat(ignored).isInstanceOf(MultipleFailuresException::class.java)
-      assertThat(ignored.message).contains("There were 2 errors:")
-      assertThat(ignored.message).contains("java.io.FileNotFoundException: error1")
-      assertThat(ignored.message).contains("java.lang.IllegalStateException: error2")
-    }
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/internal/parsers/InMemoryParserTest.kt b/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/internal/parsers/InMemoryParserTest.kt
deleted file mode 100644
index 9a032e3..0000000
--- a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/internal/parsers/InMemoryParserTest.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-package app.cash.paparazzi.internal.parsers
-
-import org.assertj.core.api.Assertions.assertThat
-import org.junit.Test
-import org.xmlpull.v1.XmlPullParserException
-
-class InMemoryParserTest {
-  @Test
-  fun parse() {
-    val root = parseResourceTree("plus_sign.xml")
-    val parser = RealInMemoryParser(root)
-
-    assertThat(parser.name).isNull() // START_DOCUMENT
-    assertThat(parser.depth).isEqualTo(0)
-
-    parser.next() // START_TAG = "vector"
-
-    assertThat(parser.name).isEqualTo(VECTOR_TAG_NAME)
-    assertThat(parser.depth).isEqualTo(1)
-    assertThat(parser.attributeCount).isEqualTo(4)
-
-    assertThat(parser.getAttributeName(0)).isEqualTo("height")
-    assertThat(parser.getAttributeName(1)).isEqualTo("viewportHeight")
-    assertThat(parser.getAttributeName(2)).isEqualTo("viewportWidth")
-    assertThat(parser.getAttributeName(3)).isEqualTo("width")
-
-    assertThat(parser.getAttributeNamespace(0)).isEqualTo(ANDROID_NAMESPACE)
-    assertThat(parser.getAttributeNamespace(1)).isEqualTo(ANDROID_NAMESPACE)
-    assertThat(parser.getAttributeNamespace(2)).isEqualTo(ANDROID_NAMESPACE)
-    assertThat(parser.getAttributeNamespace(3)).isEqualTo(ANDROID_NAMESPACE)
-
-    assertThat(parser.getAttributePrefix(0)).isEqualTo(ANDROID_PREFIX)
-    assertThat(parser.getAttributePrefix(1)).isEqualTo(ANDROID_PREFIX)
-    assertThat(parser.getAttributePrefix(2)).isEqualTo(ANDROID_PREFIX)
-    assertThat(parser.getAttributePrefix(3)).isEqualTo(ANDROID_PREFIX)
-
-    assertThat(parser.getAttributeValue(0)).isEqualTo("24dp")
-    assertThat(parser.getAttributeValue(1)).isEqualTo("40")
-    assertThat(parser.getAttributeValue(2)).isEqualTo("40")
-    assertThat(parser.getAttributeValue(3)).isEqualTo("24dp")
-
-    parser.next() // START_TAG = "path"
-
-    assertThat(parser.name).isEqualTo(PATH_TAG_NAME)
-    assertThat(parser.depth).isEqualTo(2)
-    assertThat(parser.attributeCount).isEqualTo(2)
-
-    assertThat(parser.getAttributeName(0)).isEqualTo(FILL_COLOR_ATTR_NAME)
-    assertThat(parser.getAttributeName(1)).isEqualTo(PATH_DATA_ATTR_NAME)
-
-    assertThat(parser.getAttributeNamespace(0)).isEqualTo(ANDROID_NAMESPACE)
-    assertThat(parser.getAttributeNamespace(1)).isEqualTo(ANDROID_NAMESPACE)
-
-    assertThat(parser.getAttributePrefix(0)).isEqualTo(ANDROID_PREFIX)
-    assertThat(parser.getAttributePrefix(1)).isEqualTo(ANDROID_PREFIX)
-
-    assertThat(parser.getAttributeValue(0)).isEqualTo("#999999")
-    assertThat(parser.getAttributeValue(1)).isNotNull // pathData
-
-    parser.next() // END_TAG = "path"
-
-    assertThat(parser.name).isEqualTo(PATH_TAG_NAME)
-    assertThat(parser.depth).isEqualTo(2)
-
-    parser.next() // END_TAG = "vector"
-
-    assertThat(parser.name).isEqualTo(VECTOR_TAG_NAME)
-    assertThat(parser.depth).isEqualTo(1)
-
-    parser.next() // END_DOCUMENT
-    assertThat(parser.name).isNull() // START_DOCUMENT
-    assertThat(parser.depth).isEqualTo(0)
-
-    try {
-      parser.next()
-    } catch (expected: XmlPullParserException) {
-    }
-  }
-
-  private fun parseResourceTree(resourceId: String): TagSnapshot {
-    val resourceInputStream = javaClass.classLoader.getResourceAsStream(resourceId)!!
-    return ResourceParser(resourceInputStream).createTagSnapshot()
-  }
-
-  class RealInMemoryParser(private val root: TagSnapshot) : InMemoryParser() {
-    override fun rootTag(): TagSnapshot = root
-  }
-
-  companion object {
-    const val ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android"
-    const val ANDROID_PREFIX = "android"
-
-    const val VECTOR_TAG_NAME = "vector"
-    const val PATH_TAG_NAME = "path"
-    const val PATH_DATA_ATTR_NAME = "pathData"
-    const val FILL_COLOR_ATTR_NAME = "fillColor"
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/internal/parsers/ResourceParserTest.kt b/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/internal/parsers/ResourceParserTest.kt
deleted file mode 100644
index 67402f9..0000000
--- a/external/paparazzi/paparazzi/src/test/java/app/cash/paparazzi/internal/parsers/ResourceParserTest.kt
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2021 Square, Inc.
- *
- * 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 app.cash.paparazzi.internal.parsers
-
-import org.assertj.core.api.Assertions.assertThat
-import org.junit.Test
-
-class ResourceParserTest {
-  @Test
-  fun parseResource() {
-    val root = parseResourceTree("plus_sign.xml")
-    assertThat(root.namespace).isEmpty()
-    assertThat(root.prefix).isNull()
-    assertThat(root.name).isEqualTo(VECTOR_TAG_NAME)
-    assertThat(root.hasDeclaredAaptAttrs).isEqualTo(false)
-    assertThat(root.next).isNull()
-    assertThat(root.attributes).containsExactly(
-      AttributeSnapshot(ANDROID_NAMESPACE, ANDROID_PREFIX, "height", "24dp"),
-      AttributeSnapshot(ANDROID_NAMESPACE, ANDROID_PREFIX, "viewportHeight", "40"),
-      AttributeSnapshot(ANDROID_NAMESPACE, ANDROID_PREFIX, "viewportWidth", "40"),
-      AttributeSnapshot(ANDROID_NAMESPACE, ANDROID_PREFIX, "width", "24dp")
-    )
-
-    val pathElement = root.children.single()
-    with(pathElement) {
-      assertThat(namespace).isEmpty()
-      assertThat(prefix).isNull()
-      assertThat(name).isEqualTo(PATH_TAG_NAME)
-      assertThat(hasDeclaredAaptAttrs).isEqualTo(false)
-      assertThat(next).isNull()
-    }
-
-    val pathAttributes = pathElement.attributes
-    assertThat(pathAttributes).hasSize(2)
-    assertThat(pathAttributes[0]).isEqualTo(
-      AttributeSnapshot(ANDROID_NAMESPACE, ANDROID_PREFIX, FILL_COLOR_ATTR_NAME, "#999999")
-    )
-
-    with(pathAttributes[1]) {
-      assertThat(namespace).isEqualTo(ANDROID_NAMESPACE)
-      assertThat(prefix).isEqualTo(ANDROID_PREFIX)
-      assertThat(name).isEqualTo(PATH_DATA_ATTR_NAME)
-      assertThat(value).isNotEmpty // don't care about pathData precision
-    }
-  }
-
-  @Test
-  fun parseAaptAttrTags() {
-    // Since #parseResource covers the basics, this test can be more targeted
-
-    val root = parseResourceTree("card_chip.xml")
-    assertThat(root.name).isEqualTo(VECTOR_TAG_NAME)
-    assertThat(root.hasDeclaredAaptAttrs).isEqualTo(true)
-    assertThat(root.next).isNull()
-
-    assertThat(root.children).hasSize(2)
-
-    val outerPathElement = root.children[0]
-    assertThat(outerPathElement.hasDeclaredAaptAttrs).isEqualTo(false)
-
-    val groupElement = root.children[1]
-    assertThat(groupElement.hasDeclaredAaptAttrs).isEqualTo(true)
-
-    assertThat(outerPathElement.next).isEqualTo(groupElement)
-
-    val clipPathElement = groupElement.children[0]
-    assertThat(clipPathElement.hasDeclaredAaptAttrs).isEqualTo(false)
-
-    val innerPathElement1 = groupElement.children[1]
-    assertThat(innerPathElement1.hasDeclaredAaptAttrs).isEqualTo(true)
-    with(innerPathElement1.attributes[0]) {
-      assertThat(name).isEqualTo(PATH_DATA_ATTR_NAME)
-      assertThat(this).isNotInstanceOf(AaptAttrSnapshot::class.java)
-    }
-    with(innerPathElement1.attributes[1] as AaptAttrSnapshot) {
-      assertThat(name).isEqualTo(FILL_COLOR_ATTR_NAME)
-      assertThat(id).isEqualTo("1")
-      assertThat(value).isEqualTo("@aapt:_aapt/aapt1")
-      assertThat(bundledTag.name).isEqualTo(GRADIENT_TAG_NAME) // 🎉
-    }
-
-    val innerPathElement2 = groupElement.children[2]
-    assertThat(innerPathElement2.hasDeclaredAaptAttrs).isEqualTo(true)
-    with(innerPathElement2.attributes[0]) {
-      assertThat(name).isEqualTo(PATH_DATA_ATTR_NAME)
-      assertThat(this).isNotInstanceOf(AaptAttrSnapshot::class.java)
-    }
-    with(innerPathElement2.attributes[1] as AaptAttrSnapshot) {
-      assertThat(name).isEqualTo(FILL_COLOR_ATTR_NAME)
-      assertThat(id).isEqualTo("2")
-      assertThat(value).isEqualTo("@aapt:_aapt/aapt2")
-      assertThat(bundledTag.name).isEqualTo(GRADIENT_TAG_NAME) // 🎉
-    }
-
-    val innerPathElement3 = groupElement.children[3]
-    assertThat(innerPathElement3.hasDeclaredAaptAttrs).isEqualTo(true)
-    with(innerPathElement3.attributes[0]) {
-      assertThat(name).isEqualTo(PATH_DATA_ATTR_NAME)
-      assertThat(this).isNotInstanceOf(AaptAttrSnapshot::class.java)
-    }
-    with(innerPathElement3.attributes[1]) {
-      assertThat(name).isEqualTo(FILL_TYPE_ATTR_NAME)
-      assertThat(this).isNotInstanceOf(AaptAttrSnapshot::class.java)
-    }
-    with(innerPathElement3.attributes[2] as AaptAttrSnapshot) {
-      assertThat(name).isEqualTo(FILL_COLOR_ATTR_NAME)
-      assertThat(id).isEqualTo("3")
-      assertThat(value).isEqualTo("@aapt:_aapt/aapt3")
-      assertThat(bundledTag.name).isEqualTo(GRADIENT_TAG_NAME) // 🎉
-    }
-  }
-
-  private fun parseResourceTree(resourceId: String): TagSnapshot {
-    val resourceInputStream = javaClass.classLoader.getResourceAsStream(resourceId)!!
-    return ResourceParser(resourceInputStream).createTagSnapshot()
-  }
-
-  companion object {
-    const val ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android"
-    const val ANDROID_PREFIX = "android"
-
-    const val VECTOR_TAG_NAME = "vector"
-    const val PATH_TAG_NAME = "path"
-    const val PATH_DATA_ATTR_NAME = "pathData"
-    const val FILL_COLOR_ATTR_NAME = "fillColor"
-    const val FILL_TYPE_ATTR_NAME = "fillType"
-    const val GRADIENT_TAG_NAME = "gradient"
-  }
-}
diff --git a/external/paparazzi/paparazzi/src/test/resources/accessibility-new-view.png b/external/paparazzi/paparazzi/src/test/resources/accessibility-new-view.png
deleted file mode 100644
index 57f25b5a..0000000
--- a/external/paparazzi/paparazzi/src/test/resources/accessibility-new-view.png
+++ /dev/null
Binary files differ
diff --git a/external/paparazzi/paparazzi/src/test/resources/accessibility.png b/external/paparazzi/paparazzi/src/test/resources/accessibility.png
deleted file mode 100644
index d7f3a16..0000000
--- a/external/paparazzi/paparazzi/src/test/resources/accessibility.png
+++ /dev/null
Binary files differ
diff --git a/external/paparazzi/paparazzi/src/test/resources/card_chip.xml b/external/paparazzi/paparazzi/src/test/resources/card_chip.xml
deleted file mode 100644
index a9cb398..0000000
--- a/external/paparazzi/paparazzi/src/test/resources/card_chip.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<!--Copyright Square, Inc.-->
-<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt" android:width="42dp" android:height="34dp" android:viewportWidth="42" android:viewportHeight="34">
-    <path android:pathData="M36.795 0H5.205C2.333 0 0 2.384 0 5.318v22.374c0 2.934 2.333 5.318 5.205 5.318h31.59c2.872 0 5.205-2.384 5.205-5.318V5.318C41.955 2.384 39.622 0 36.795 0z" android:fillColor="#666666"/>
-    <group>
-        <clip-path android:pathData="M0.314 21.549h11.981c0.404 0 0.808 0.183 1.122 0.504 1.48 1.559 3.5 2.338 6.058 2.338h0.224c2.378 0 3.814-0.825 3.814-2.109 0-1.192-1.211-1.742-4.711-3.072-3.097-1.146-7.18-3.163-7.45-7.748H0.27v0.459h0.404v9.17H0.27v0.458h0.045zm20.866 7.977c5.519-0.504 8.93-3.53 8.93-7.977 0-4.31-3.994-6.281-7.898-7.611-2.02-0.78-3.5-1.421-4.128-2.476h-6.058c0.27 4.172 4.083 6.052 7 7.107 3.32 1.237 5.115 1.97 5.115 3.713 0 1.742-1.705 2.797-4.487 2.797H19.43c-2.737 0-4.936-0.871-6.507-2.568-0.18-0.183-0.403-0.275-0.628-0.275H0.27v0.459h0.403v4.997c0 1.238 0.494 2.384 1.257 3.21L1.705 31.13l0.314 0.32 0.27-0.274c0.807 0.687 1.795 1.1 2.916 1.1h9.02l0.493-2.568c0.045-0.137-0.045-0.229-0.18-0.275-1.704-0.504-3.275-1.33-4.666-2.475-0.134-0.138-0.18-0.321-0.045-0.459 0.135-0.137 0.314-0.183 0.449-0.046 1.346 1.055 2.827 1.88 4.442 2.338 0.449 0.138 0.718 0.596 0.629 1.055l-0.45 2.43h5.026l0.45-2.063c0.089-0.367 0.403-0.642 0.807-0.688zM0.314 10.774h10.994c0.135-5.364 4.801-7.61 9.154-7.931 0.09-0.046 0.18-0.092 0.18-0.23L21 0.644H5.205c-1.121 0-2.109 0.412-2.916 1.1l-0.27-0.23L1.705 1.88 1.93 2.11C1.167 2.934 0.673 4.08 0.673 5.318v4.997H0.27v0.458h0.045zm41.327 11.417H30.738c-0.315 4.447-3.904 7.518-9.513 7.977-0.09 0-0.18 0.092-0.225 0.183l-0.404 1.926H36.75c1.122 0 2.11-0.413 2.917-1.1l0.27 0.275 0.313-0.321-0.224-0.23c0.808-0.825 1.301-1.97 1.301-3.209v-4.997h0.36L41.64 22.19zm-0.314-11.875V5.319c0-1.238-0.493-2.385-1.301-3.21L40.25 1.88l-0.314-0.367-0.224 0.23c-0.808-0.688-1.795-1.1-2.917-1.1h-9.333l-0.539 2.75c-0.044 0.092 0.045 0.23 0.135 0.275 1.212 0.458 2.378 1.1 3.455 1.834 0.135 0.092 0.18 0.32 0.09 0.458-0.045 0.092-0.18 0.138-0.27 0.138-0.044 0-0.134 0-0.179-0.046-1.032-0.688-2.109-1.284-3.276-1.696-0.403-0.138-0.673-0.596-0.583-1.009l0.539-2.613h-5.16l-0.36 2.017c-0.09 0.413-0.403 0.688-0.807 0.734-4.039 0.32-8.391 2.384-8.481 7.29h5.878c-0.045-0.138-0.045-0.276-0.045-0.413 0-1.467 1.436-2.384 3.904-2.384 1.795 0 4.577 0.642 6.641 2.476 0.224 0.183 0.494 0.32 0.763 0.32h12.564v-0.458h-0.404zm0 1.146H29.122c-0.404 0-0.852-0.183-1.211-0.458-1.93-1.697-4.533-2.339-6.193-2.339-0.538 0-3.23 0.092-3.23 1.697 0 1.33 1.57 2.017 3.948 2.934 4.128 1.421 8.302 3.484 8.302 8.253h10.948V21.09h-0.359v-9.17h0.36v-0.458h-0.36z"/>
-        <path android:pathData="M0.314 21.549h11.981c0.404 0 0.808 0.183 1.122 0.504 1.48 1.559 3.5 2.338 6.058 2.338h0.224c2.378 0 3.814-0.825 3.814-2.109 0-1.192-1.211-1.742-4.711-3.072-3.097-1.146-7.18-3.163-7.45-7.748H0.27v0.459h0.404v9.17H0.27v0.458h0.045zm20.866 7.977c5.519-0.504 8.93-3.53 8.93-7.977 0-4.31-3.994-6.281-7.898-7.611-2.02-0.78-3.5-1.421-4.128-2.476h-6.058c0.27 4.172 4.083 6.052 7 7.107 3.32 1.237 5.115 1.97 5.115 3.713 0 1.742-1.705 2.797-4.487 2.797H19.43c-2.737 0-4.936-0.871-6.507-2.568-0.18-0.183-0.403-0.275-0.628-0.275H0.27v0.459h0.403v4.997c0 1.238 0.494 2.384 1.257 3.21L1.705 31.13l0.314 0.32 0.27-0.274c0.807 0.687 1.795 1.1 2.916 1.1h9.02l0.493-2.568c0.045-0.137-0.045-0.229-0.18-0.275-1.704-0.504-3.275-1.33-4.666-2.475-0.134-0.138-0.18-0.321-0.045-0.459 0.135-0.137 0.314-0.183 0.449-0.046 1.346 1.055 2.827 1.88 4.442 2.338 0.449 0.138 0.718 0.596 0.629 1.055l-0.45 2.43h5.026l0.45-2.063c0.089-0.367 0.403-0.642 0.807-0.688zM0.314 10.774h10.994c0.135-5.364 4.801-7.61 9.154-7.931 0.09-0.046 0.18-0.092 0.18-0.23L21 0.644H5.205c-1.121 0-2.109 0.412-2.916 1.1l-0.27-0.23L1.705 1.88 1.93 2.11C1.167 2.934 0.673 4.08 0.673 5.318v4.997H0.27v0.458h0.045zm41.327 11.417H30.738c-0.315 4.447-3.904 7.518-9.513 7.977-0.09 0-0.18 0.092-0.225 0.183l-0.404 1.926H36.75c1.122 0 2.11-0.413 2.917-1.1l0.27 0.275 0.313-0.321-0.224-0.23c0.808-0.825 1.301-1.97 1.301-3.209v-4.997h0.36L41.64 22.19zm-0.314-11.875V5.319c0-1.238-0.493-2.385-1.301-3.21L40.25 1.88l-0.314-0.367-0.224 0.23c-0.808-0.688-1.795-1.1-2.917-1.1h-9.333l-0.539 2.75c-0.044 0.092 0.045 0.23 0.135 0.275 1.212 0.458 2.378 1.1 3.455 1.834 0.135 0.092 0.18 0.32 0.09 0.458-0.045 0.092-0.18 0.138-0.27 0.138-0.044 0-0.134 0-0.179-0.046-1.032-0.688-2.109-1.284-3.276-1.696-0.403-0.138-0.673-0.596-0.583-1.009l0.539-2.613h-5.16l-0.36 2.017c-0.09 0.413-0.403 0.688-0.807 0.734-4.039 0.32-8.391 2.384-8.481 7.29h5.878c-0.045-0.138-0.045-0.276-0.045-0.413 0-1.467 1.436-2.384 3.904-2.384 1.795 0 4.577 0.642 6.641 2.476 0.224 0.183 0.494 0.32 0.763 0.32h12.564v-0.458h-0.404zm0 1.146H29.122c-0.404 0-0.852-0.183-1.211-0.458-1.93-1.697-4.533-2.339-6.193-2.339-0.538 0-3.23 0.092-3.23 1.697 0 1.33 1.57 2.017 3.948 2.934 4.128 1.421 8.302 3.484 8.302 8.253h10.948V21.09h-0.359v-9.17h0.36v-0.458h-0.36z">
-            <aapt:attr name="android:fillColor">
-                <gradient android:startY="3.4928" android:startX="1.38832" android:endY="46.3417" android:endX="68.7929" android:type="linear">
-                    <item android:offset="0" android:color="#FFFFFFFF"/>
-                    <item android:offset="0.4081" android:color="#FFC7B299"/>
-                    <item android:offset="1" android:color="#FF998675"/>
-                </gradient>
-            </aapt:attr>
-        </path>
-        <path android:pathData="M0.314 21.549h11.981c0.404 0 0.808 0.183 1.122 0.504 1.48 1.559 3.5 2.338 6.058 2.338h0.224c2.378 0 3.814-0.825 3.814-2.109 0-1.192-1.211-1.742-4.711-3.072-3.097-1.146-7.18-3.163-7.45-7.748H0.27v0.459h0.404v9.17H0.27v0.458h0.045zm20.866 7.977c5.519-0.504 8.93-3.53 8.93-7.977 0-4.31-3.994-6.281-7.898-7.611-2.02-0.78-3.5-1.421-4.128-2.476h-6.058c0.27 4.172 4.083 6.052 7 7.107 3.32 1.237 5.115 1.97 5.115 3.713 0 1.742-1.705 2.797-4.487 2.797H19.43c-2.737 0-4.936-0.871-6.507-2.568-0.18-0.183-0.403-0.275-0.628-0.275H0.27v0.459h0.403v4.997c0 1.238 0.494 2.384 1.257 3.21L1.705 31.13l0.314 0.32 0.27-0.274c0.807 0.687 1.795 1.1 2.916 1.1h9.02l0.493-2.568c0.045-0.137-0.045-0.229-0.18-0.275-1.704-0.504-3.275-1.33-4.666-2.475-0.134-0.138-0.18-0.321-0.045-0.459 0.135-0.137 0.314-0.183 0.449-0.046 1.346 1.055 2.827 1.88 4.442 2.338 0.449 0.138 0.718 0.596 0.629 1.055l-0.45 2.43h5.026l0.45-2.063c0.089-0.367 0.403-0.642 0.807-0.688zM0.314 10.774h10.994c0.135-5.364 4.801-7.61 9.154-7.931 0.09-0.046 0.18-0.092 0.18-0.23L21 0.644H5.205c-1.121 0-2.109 0.412-2.916 1.1l-0.27-0.23L1.705 1.88 1.93 2.11C1.167 2.934 0.673 4.08 0.673 5.318v4.997H0.27v0.458h0.045zm41.327 11.417H30.738c-0.315 4.447-3.904 7.518-9.513 7.977-0.09 0-0.18 0.092-0.225 0.183l-0.404 1.926H36.75c1.122 0 2.11-0.413 2.917-1.1l0.27 0.275 0.313-0.321-0.224-0.23c0.808-0.825 1.301-1.97 1.301-3.209v-4.997h0.36L41.64 22.19zm-0.314-11.875V5.319c0-1.238-0.493-2.385-1.301-3.21L40.25 1.88l-0.314-0.367-0.224 0.23c-0.808-0.688-1.795-1.1-2.917-1.1h-9.333l-0.539 2.75c-0.044 0.092 0.045 0.23 0.135 0.275 1.212 0.458 2.378 1.1 3.455 1.834 0.135 0.092 0.18 0.32 0.09 0.458-0.045 0.092-0.18 0.138-0.27 0.138-0.044 0-0.134 0-0.179-0.046-1.032-0.688-2.109-1.284-3.276-1.696-0.403-0.138-0.673-0.596-0.583-1.009l0.539-2.613h-5.16l-0.36 2.017c-0.09 0.413-0.403 0.688-0.807 0.734-4.039 0.32-8.391 2.384-8.481 7.29h5.878c-0.045-0.138-0.045-0.276-0.045-0.413 0-1.467 1.436-2.384 3.904-2.384 1.795 0 4.577 0.642 6.641 2.476 0.224 0.183 0.494 0.32 0.763 0.32h12.564v-0.458h-0.404zm0 1.146H29.122c-0.404 0-0.852-0.183-1.211-0.458-1.93-1.697-4.533-2.339-6.193-2.339-0.538 0-3.23 0.092-3.23 1.697 0 1.33 1.57 2.017 3.948 2.934 4.128 1.421 8.302 3.484 8.302 8.253h10.948V21.09h-0.359v-9.17h0.36v-0.458h-0.36z">
-            <aapt:attr name="android:fillColor">
-                <gradient android:startY="31.3798" android:startX="42.1542" android:endY="-9.12049" android:endX="13.8976" android:type="linear">
-                    <item android:offset="0" android:color="#FFF1EAE2"/>
-                    <item android:offset="0.149949" android:color="#FFF3ECE3"/>
-                    <item android:offset="0.319891" android:color="#FFF4EDE4"/>
-                    <item android:offset="0.509302" android:color="#FFEFE6DB"/>
-                    <item android:offset="0.707905" android:color="#FFECE4DB"/>
-                    <item android:offset="1" android:color="#FFF1F1F1"/>
-                </gradient>
-            </aapt:attr>
-        </path>
-        <path android:pathData="M1.25 0.5C1.08 0.775 1.166 1 1.441 1S2.08 0.775 2.25 0.5C2.42 0.225 2.334 0 2.059 0S1.42 0.225 1.25 0.5zM24 1.03c0 0.565 0.225 0.89 0.5 0.72 0.275-0.17 0.5-0.633 0.5-1.03C25 0.324 24.775 0 24.5 0S24 0.464 24 1.03zm4-0.78c0 0.138 0.113 0.25 0.25 0.25s0.25-0.112 0.25-0.25S28.387 0 28.25 0 28 0.113 28 0.25zm-8.181 2C19.661 2.663 19.749 3 20.016 3 20.282 3 20.5 2.663 20.5 2.25S20.412 1.5 20.303 1.5c-0.108 0-0.326 0.337-0.484 0.75zM24 2.75C24 2.888 24.113 3 24.25 3s0.25-0.112 0.25-0.25-0.113-0.25-0.25-0.25S24 2.612 24 2.75zm-4.76 1.78c-0.45 1.42 0.05 1.796 0.721 0.543 0.326-0.609 0.357-1.127 0.077-1.3-0.256-0.158-0.615 0.182-0.797 0.757zM22.83 4c-0.977 3.02-0.495 6.254 0.669 4.5 0.274-0.412 0.448-1.088 0.387-1.5-0.06-0.412 0.046-0.998 0.236-1.301 0.191-0.303 0.033-0.978-0.351-1.5C23.19 3.412 23.03 3.378 22.829 4zm2.895 1.875C24.304 9.252 23.56 14.5 24.5 14.5c0.275 0 0.5-0.575 0.5-1.278C25 11.64 26.04 7.34 26.504 7c0.188-0.138 0.493-0.869 0.678-1.625 0.501-2.046-0.536-1.69-1.457 0.5zM32 4.75C32 4.888 32.112 5 32.25 5s0.25-0.112 0.25-0.25-0.112-0.25-0.25-0.25S32 4.612 32 4.75zM0.508 5.875c0.004 0.206 0.217 0.706 0.473 1.11 0.576 0.911 1.251 0.341 0.846-0.714-0.298-0.779-1.333-1.09-1.32-0.396zM13 6.029c0 0.292 0.225 0.391 0.5 0.221S14 5.842 14 5.72c0-0.12-0.225-0.22-0.5-0.22S13 5.739 13 6.03zm20.54 0.173c-0.415 0.5-0.424 0.753-0.031 0.885C34.584 7.444 29.094 22 27.884 22c-0.223 0-1.383-0.9-2.576-2-3.16-2.913-3.467-2.449-0.421 0.636l2.603 2.635-1.295 1.398c-1.703 1.835-1.092 2.398 0.719 0.663 1.881-1.802 5.678-9.57 7.284-14.905C34.914 8.05 35.5 5.97 35.5 5.804c0-0.58-1.382-0.298-1.96 0.399zM2.876 6.33c0.344 0.139 0.906 0.139 1.25 0S4.188 6.079 3.5 6.079 2.531 6.193 2.875 6.331zM5 6.5C5 6.775 5.225 7 5.5 7S6 6.775 6 6.5 5.775 6 5.5 6 5 6.225 5 6.5zm10.5 0.25C15.5 6.888 15.613 7 15.75 7S16 6.888 16 6.75 15.887 6.5 15.75 6.5 15.5 6.612 15.5 6.75zM13 7.25c0 0.138 0.113 0.25 0.25 0.25s0.25-0.112 0.25-0.25S13.387 7 13.25 7 13 7.112 13 7.25zM8.5 8.146C6.987 8.373 5.02 8.447 4.128 8.311 3.098 8.155 2.245 8.327 1.79 8.783 1.395 9.177 0.83 9.5 0.535 9.5 0.241 9.5 0 10.063 0 10.75 0 11.943 0.136 12 2.966 12c2.761 0 3.044 0.11 4.096 1.587 0.656 0.922 1.216 1.329 1.336 0.971 0.112-0.338-0.191-1.053-0.674-1.587-0.484-0.534-0.788-0.983-0.676-0.998 0.111-0.015 1.954-0.21 4.096-0.436 2.142-0.224 3.995-0.51 4.12-0.634 0.124-0.124-0.05-0.81-0.387-1.524-0.723-1.532-2.324-1.841-6.377-1.233zM16 7.75C16 7.888 16.113 8 16.25 8s0.25-0.112 0.25-0.25-0.113-0.25-0.25-0.25S16 7.612 16 7.75zm12.278 2.778c-1.78 3.966-1.386 4.36 0.472 0.472 0.785-1.643 1.308-3.108 1.162-3.255-0.146-0.146-0.882 1.106-1.634 2.783zM13.334 8.834c-0.184 0.183-0.484 0.183-0.668 0C12.483 8.65 12.633 8.5 13 8.5s0.517 0.15 0.334 0.334zm4.968 0.541c-1.22 4.022-1.857 8.726-1.305 9.62 0.555 0.898 1.384-2.032 1.761-6.225 0.172-1.915 0.423-3.658 0.557-3.875 0.134-0.217 0.021-0.395-0.252-0.395-0.272 0-0.615 0.394-0.761 0.875zM4.5 9.25c0 0.137-0.112 0.25-0.25 0.25S4 9.387 4 9.25 4.112 9 4.25 9 4.5 9.113 4.5 9.25zm2 0c0 0.137-0.112 0.25-0.25 0.25S6 9.387 6 9.25 6.112 9 6.25 9 6.5 9.113 6.5 9.25zm4.375 0.108c-0.756 0.114-1.993 0.114-2.75 0C7.369 9.243 7.987 9.15 9.5 9.15c1.512 0 2.132 0.093 1.375 0.208zM22.08 11.93c-0.698 2.33-0.737 3.226-0.123 2.847 0.494-0.305 1.282-4.204 0.923-4.564-0.121-0.12-0.481 0.652-0.8 1.717zM3.5 13.5c0 0.367 0.15 0.517 0.333 0.334 0.183-0.184 0.183-0.484 0-0.668C3.65 12.983 3.5 13.133 3.5 13.5zm1-0.25c0 0.137 0.112 0.25 0.25 0.25S5 13.387 5 13.25 4.888 13 4.75 13 4.5 13.113 4.5 13.25zm28.334 2.584c-0.184 0.183-0.334 0.565-0.334 0.85 0 0.313 0.233 0.283 0.592-0.076 0.325-0.325 0.475-0.708 0.333-0.85-0.142-0.142-0.408-0.108-0.591 0.076zM15.5 16.25c0 0.137 0.113 0.25 0.25 0.25S16 16.387 16 16.25 15.887 16 15.75 16s-0.25 0.113-0.25 0.25zm3.959 2.375c-0.023 0.344-0.137 1.2-0.254 1.902-0.156 0.938 0.188 1.662 1.291 2.719 1.452 1.391 2.13 3.2 0.919 2.452-0.399-0.247-0.479-0.085-0.25 0.511 0.184 0.48 0.335 1.305 0.335 1.832 0 0.527 0.242 0.959 0.538 0.959 0.296 0 0.497-0.619 0.447-1.375-0.139-2.099-0.066-2.203 1.091-1.584 0.928 0.497 1.031 0.46 0.75-0.274C24.146 25.301 24 24.824 24 24.71c0-0.115-0.281-0.212-0.625-0.215-0.343-0.003-1.336-0.736-2.204-1.631-1.391-1.431-1.5-1.736-0.91-2.543 0.683-0.934 0.495-2.32-0.314-2.32-0.246 0-0.465 0.282-0.488 0.625zM6.75 21c-0.17 0.275-0.07 0.5 0.22 0.5 0.292 0 0.53-0.225 0.53-0.5s-0.099-0.5-0.22-0.5c-0.122 0-0.36 0.225-0.53 0.5zm9 0.09c-0.825 0.245-2.328 0.325-3.339 0.177-1.258-0.183-2.075-0.032-2.586 0.48-0.412 0.411-1.159 0.823-1.661 0.916C5.802 23.1 2.816 24.16 3.378 24.36c0.345 0.124 0.501 0.431 0.345 0.683C3.569 25.294 4.13 25.5 4.971 25.5 5.81 25.5 6.5 25.725 6.5 26s-0.956 0.503-2.125 0.508C2.819 26.514 2.45 26.645 3 27c0.413 0.267 1.699 0.488 2.86 0.492 1.7 0.006 2.05 0.158 1.81 0.788-0.165 0.428-0.6 0.663-0.968 0.521-0.369-0.14-0.803-0.041-0.965 0.222C5.574 29.285 5.932 29.5 6.532 29.5c0.856 0 0.97 0.145 0.534 0.671-0.715 0.861-0.279 1.291 0.977 0.963 0.696-0.183 0.898-0.534 0.688-1.196C8.528 29.304 8.676 29 9.186 29c0.415 0 0.892-0.223 1.06-0.494 0.175-0.284-0.026-0.367-0.471-0.197-1.216 0.467-0.908-0.593 0.349-1.199l1.125-0.543-1.125-0.033C8.85 26.496 8.62 25.753 9.75 25.319c0.412-0.158 0.75-0.621 0.75-1.03 0-0.658 2.703-1.778 4.31-1.786 0.585-0.003 1.464 4.422 1.266 6.372C16.014 29.494 16.197 30 16.482 30 16.791 30 17 28.576 17 26.47c0-2.225-0.184-3.415-0.5-3.22-0.786 0.485-0.585-0.328 0.33-1.338 1.061-1.173 0.792-1.377-1.08-0.822zm25.285 0.994c-0.019 0.459-0.171 1.19-0.338 1.625-0.2 0.519-0.028 0.791 0.5 0.791 0.875 0 0.97-0.698 0.303-2.25-0.343-0.799-0.437-0.832-0.465-0.166zM10.5 22.25c0 0.137-0.113 0.25-0.25 0.25S10 22.387 10 22.25 10.113 22 10.25 22s0.25 0.113 0.25 0.25zM39 23.5c0 0.366 0.15 0.517 0.334 0.334 0.182-0.184 0.182-0.484 0-0.668C39.15 22.983 39 23.134 39 23.5zM8.634 24.328c-0.338 0.137-1.013 0.146-1.5 0.018-0.486-0.127-0.209-0.238 0.616-0.248 0.825-0.01 1.223 0.093 0.884 0.23zM5 24.75C5 24.887 4.888 25 4.75 25S4.5 24.887 4.5 24.75s0.112-0.25 0.25-0.25S5 24.613 5 24.75zm26.5 0.75c0 0.275 0.238 0.5 0.53 0.5 0.29 0 0.39-0.225 0.22-0.5S31.842 25 31.72 25c-0.121 0-0.22 0.225-0.22 0.5zm6.822 0.54c-0.857 0.826-0.87 1.012-0.164 2.427C38.58 29.311 38.74 30 38.517 30c-0.223 0-0.375 0.394-0.337 0.875 0.048 0.605-0.355 0.924-1.305 1.033-0.86 0.099-1.375-0.079-1.375-0.475 0-0.465-0.148-0.485-0.556-0.076C33.995 32.303 34.96 33 37.225 33c1.465 0 2.26-0.243 2.455-0.75 0.158-0.413 0.547-0.75 0.864-0.75 0.416 0 0.404 0.21-0.045 0.75-0.52 0.627-0.448 0.75 0.439 0.75C41.717 33 42 32.689 42 31.834c0-1.512-0.486-1.968-1.341-1.258-0.852 0.706-1.284 0.331-0.867-0.755C39.965 29.37 40.532 29 41.053 29c1.19 0 1.244-0.85 0.072-1.155-0.834-0.218-0.834-0.232 0-0.287C42.063 27.496 42.429 25 41.5 25c-0.275 0-0.5 0.225-0.5 0.5 0 0.609-1.35 0.67-1.584 0.073-0.091-0.236-0.583-0.026-1.094 0.466zM8 25.72c0 0.122-0.225 0.36-0.5 0.53C7.225 26.42 7 26.32 7 26.03c0-0.292 0.225-0.53 0.5-0.53S8 25.599 8 25.72zm15 1.03c0 0.137 0.113 0.25 0.25 0.25s0.25-0.113 0.25-0.25-0.113-0.25-0.25-0.25S23 26.613 23 26.75zM1.5 27.5c0 0.366 0.15 0.517 0.333 0.334 0.184-0.184 0.184-0.484 0-0.668C1.65 26.983 1.5 27.134 1.5 27.5zm23.532 0.29c0.325 0.39 0.913 0.71 1.308 0.71 1.006 0 0.39-0.823-0.861-1.15-0.85-0.223-0.93-0.144-0.447 0.44zm-10.28 1.335c-0.18 0.894-0.429 1.992-0.554 2.441-0.126 0.448 0.06 0.926 0.412 1.06 0.465 0.178 0.667-0.492 0.736-2.44 0.11-3.047-0.114-3.446-0.594-1.061zm8.341 0.282c-0.078 1.37 0.023 1.65 0.393 1.093 0.603-0.907 0.664-2.349 0.114-2.688-0.22-0.136-0.448 0.582-0.507 1.595zM24.5 29.25c0 0.137 0.113 0.25 0.25 0.25S25 29.387 25 29.25 24.887 29 24.75 29s-0.25 0.113-0.25 0.25zm1.166 0.084c0.184 0.183 0.484 0.183 0.668 0C26.517 29.15 26.366 29 26 29s-0.517 0.15-0.334 0.334zM28 29.75c0 0.137 0.113 0.25 0.25 0.25s0.25-0.113 0.25-0.25-0.113-0.25-0.25-0.25S28 29.613 28 29.75zM1 30.5c0 0.366 0.15 0.517 0.333 0.334 0.183-0.184 0.183-0.484 0-0.668C1.15 29.983 1 30.134 1 30.5zm28-0.25c0 0.137 0.113 0.25 0.25 0.25s0.25-0.113 0.25-0.25S29.387 30 29.25 30 29 30.113 29 30.25zm-7.5 1.5c0 0.137 0.113 0.25 0.25 0.25S22 31.887 22 31.75s-0.113-0.25-0.25-0.25-0.25 0.113-0.25 0.25zm-14 0.75c0.982 0.635 2.5 0.635 2.5 0 0-0.275-0.731-0.496-1.625-0.492C7.142 32.013 6.931 32.132 7.5 32.5zm17.5 0c0.97 0.627 1.5 0.627 1.5 0 0-0.275-0.506-0.496-1.125-0.492-0.91 0.006-0.982 0.1-0.375 0.492z" android:fillType="evenOdd">
-            <aapt:attr name="android:fillColor">
-                <gradient android:startY="1.5" android:startX="32.5" android:endY="37.0292" android:endX="-0.969948" android:type="linear">
-                    <item android:offset="0" android:color="#FFECE3DA"/>
-                    <item android:offset="0.208782" android:color="#FFEBE2D6"/>
-                    <item android:offset="1" android:color="#FFEBE2D9"/>
-                </gradient>
-            </aapt:attr>
-        </path>
-    </group>
-</vector>
diff --git a/external/paparazzi/paparazzi/src/test/resources/plus_sign.xml b/external/paparazzi/paparazzi/src/test/resources/plus_sign.xml
deleted file mode 100644
index 1556760..0000000
--- a/external/paparazzi/paparazzi/src/test/resources/plus_sign.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:viewportHeight="40" android:viewportWidth="40" android:width="24dp">
-    <path android:fillColor="#999999" android:pathData="M21.5 14c0-0.828-0.672-1.5-1.5-1.5s-1.5 0.672-1.5 1.5v4.5H14c-0.828 0-1.5 0.672-1.5 1.5s0.672 1.5 1.5 1.5h4.5V26c0 0.828 0.672 1.5 1.5 1.5s1.5-0.672 1.5-1.5v-4.5H26c0.828 0 1.5-0.672 1.5-1.5s-0.672-1.5-1.5-1.5h-4.5V14z"/>
-</vector>
diff --git a/external/paparazzi/paparazzi/src/test/resources/rendering-mode-normal.png b/external/paparazzi/paparazzi/src/test/resources/rendering-mode-normal.png
deleted file mode 100644
index e69de29..0000000
--- a/external/paparazzi/paparazzi/src/test/resources/rendering-mode-normal.png
+++ /dev/null
diff --git a/external/paparazzi/paparazzi/src/test/resources/rendering-mode-shrink.png b/external/paparazzi/paparazzi/src/test/resources/rendering-mode-shrink.png
deleted file mode 100644
index e69de29..0000000
--- a/external/paparazzi/paparazzi/src/test/resources/rendering-mode-shrink.png
+++ /dev/null
diff --git a/external/paparazzi/paparazzi/src/test/resources/without-layout-params.png b/external/paparazzi/paparazzi/src/test/resources/without-layout-params.png
deleted file mode 100644
index e3da5cb..0000000
--- a/external/paparazzi/paparazzi/src/test/resources/without-layout-params.png
+++ /dev/null
Binary files differ
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index b276acf..e35bc05 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -56,8 +56,6 @@
 mockito = "2.25.0"
 moshi = "1.13.0"
 protobuf = "3.22.3"
-paparazzi = "1.0.0"
-paparazziNative = "2022.1.1-canary-f5f9f71"
 skiko = "0.7.7"
 spdxGradlePlugin = "0.3.0"
 sqldelight = "1.3.0"
@@ -245,11 +243,6 @@
 playServicesDevicePerformance = { module = "com.google.android.gms:play-services-deviceperformance", version = "16.0.0" }
 playServicesFido = {module = "com.google.android.gms:play-services-fido", version = "20.1.0"}
 playServicesWearable = { module = "com.google.android.gms:play-services-wearable", version = "17.1.0" }
-paparazzi = { module = "app.cash.paparazzi:paparazzi", version.ref = "paparazzi" }
-paparazziNativeJvm = { module = "app.cash.paparazzi:layoutlib-native-jdk11", version.ref = "paparazziNative" }
-paparazziNativeLinuxX64 = { module = "app.cash.paparazzi:layoutlib-native-linux", version.ref = "paparazziNative" }
-paparazziNativeMacOsArm64 = { module = "app.cash.paparazzi:layoutlib-native-macarm", version.ref = "paparazziNative" }
-paparazziNativeMacOsX64 = { module = "app.cash.paparazzi:layoutlib-native-macosx", version.ref = "paparazziNative" }
 protobuf = { module = "com.google.protobuf:protobuf-java", version.ref = "protobuf" }
 protobufCompiler = { module = "com.google.protobuf:protoc", version.ref = "protobuf" }
 protobufGradlePlugin = { module = "com.google.protobuf:protobuf-gradle-plugin", version = "0.9.4" }
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 4061606..82e12f6 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -238,7 +238,6 @@
             <trusting group="com.google.auto.value"/>
             <trusting group="com.google.auto.value" name="auto-value"/>
          </trusted-key>
-         <trusted-key id="70731C2FFB496DC4E8105AA3604F437C1682DDE5" group="app.cash.paparazzi"/>
          <trusted-key id="70CD19BFD9F6C330027D6F260315BFB7970A144F">
             <trusting group="com.sun.istack"/>
             <trusting group="com.sun.xml.bind"/>
diff --git a/gradlew b/gradlew
index 64c7da7..4019b0b 100755
--- a/gradlew
+++ b/gradlew
@@ -264,8 +264,7 @@
   fi
   if [ "$compact" == "--strict" ]; then
     expanded="-Pandroidx.validateNoUnrecognizedMessages\
-     -Pandroidx.verifyUpToDate\
-     --no-watch-fs"
+     -Pandroidx.verifyUpToDate"
     if [ "$USE_ANDROIDX_REMOTE_BUILD_CACHE" == "" ]; then
       expanded="$expanded --offline"
     fi
diff --git a/libraryversions.toml b/libraryversions.toml
index 5d08392..702a656 100644
--- a/libraryversions.toml
+++ b/libraryversions.toml
@@ -97,7 +97,7 @@
 LINT = "1.0.0-alpha01"
 LOADER = "1.2.0-alpha01"
 MEDIA = "1.7.0-rc01"
-MEDIAROUTER = "1.7.0-alpha02"
+MEDIAROUTER = "1.7.0-beta01"
 METRICS = "1.0.0-beta02"
 NAVIGATION = "2.8.0-alpha03"
 PAGING = "3.3.0-alpha03"
@@ -202,6 +202,7 @@
 COMPOSE_FOUNDATION = { group = "androidx.compose.foundation", atomicGroupVersion = "versions.COMPOSE" }
 COMPOSE_MATERIAL = { group = "androidx.compose.material", atomicGroupVersion = "versions.COMPOSE" }
 COMPOSE_MATERIAL3 = { group = "androidx.compose.material3", atomicGroupVersion = "versions.COMPOSE_MATERIAL3" }
+COMPOSE_MATERIAL3_ADAPTIVE = { group = "androidx.compose.material3.adaptive", atomicGroupVersion = "versions.COMPOSE_MATERIAL3_ADAPTIVE" }
 COMPOSE_RUNTIME = { group = "androidx.compose.runtime", atomicGroupVersion = "versions.COMPOSE" }
 COMPOSE_RUNTIME_TRACING = { group = "androidx.compose.runtime", atomicGroupVersion = "versions.COMPOSE_RUNTIME_TRACING", overrideInclude = [ ":compose:runtime:runtime-tracing" ] }
 COMPOSE_UI = { group = "androidx.compose.ui", atomicGroupVersion = "versions.COMPOSE" }
diff --git a/lint/lint-gradle/src/main/java/androidx/lint/gradle/GradleIssueRegistry.kt b/lint/lint-gradle/src/main/java/androidx/lint/gradle/GradleIssueRegistry.kt
index 7d3cfd3..bdc7136 100644
--- a/lint/lint-gradle/src/main/java/androidx/lint/gradle/GradleIssueRegistry.kt
+++ b/lint/lint-gradle/src/main/java/androidx/lint/gradle/GradleIssueRegistry.kt
@@ -33,7 +33,7 @@
     override val vendor = Vendor(
         // TODO: Update component (or the issue template)
         feedbackUrl = "https://issuetracker.google.com/issues/new?component=1147525",
-        identifier = "androidx.gradle-lint:gradle-lint-checks",
+        identifier = "androidx.lint:lint-gradle",
         vendorName = "Android Open Source Project",
     )
 }
diff --git a/mediarouter/mediarouter-testing/api/1.7.0-beta01.txt b/mediarouter/mediarouter-testing/api/1.7.0-beta01.txt
new file mode 100644
index 0000000..14e1df6
--- /dev/null
+++ b/mediarouter/mediarouter-testing/api/1.7.0-beta01.txt
@@ -0,0 +1,9 @@
+// Signature format: 4.0
+package androidx.mediarouter.testing {
+
+  public class MediaRouterTestHelper {
+    method @MainThread public static void resetMediaRouter();
+  }
+
+}
+
diff --git a/compose/material3/material3-adaptive/api/res-current.txt b/mediarouter/mediarouter-testing/api/res-1.7.0-beta01.txt
similarity index 100%
copy from compose/material3/material3-adaptive/api/res-current.txt
copy to mediarouter/mediarouter-testing/api/res-1.7.0-beta01.txt
diff --git a/mediarouter/mediarouter-testing/api/restricted_1.7.0-beta01.txt b/mediarouter/mediarouter-testing/api/restricted_1.7.0-beta01.txt
new file mode 100644
index 0000000..14e1df6
--- /dev/null
+++ b/mediarouter/mediarouter-testing/api/restricted_1.7.0-beta01.txt
@@ -0,0 +1,9 @@
+// Signature format: 4.0
+package androidx.mediarouter.testing {
+
+  public class MediaRouterTestHelper {
+    method @MainThread public static void resetMediaRouter();
+  }
+
+}
+
diff --git a/mediarouter/mediarouter/api/1.7.0-beta01.txt b/mediarouter/mediarouter/api/1.7.0-beta01.txt
new file mode 100644
index 0000000..e67bdb6
--- /dev/null
+++ b/mediarouter/mediarouter/api/1.7.0-beta01.txt
@@ -0,0 +1,638 @@
+// Signature format: 4.0
+package androidx.mediarouter.app {
+
+  public class MediaRouteActionProvider extends androidx.core.view.ActionProvider {
+    ctor public MediaRouteActionProvider(android.content.Context);
+    method @Deprecated public void enableDynamicGroup();
+    method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
+    method public androidx.mediarouter.app.MediaRouteButton? getMediaRouteButton();
+    method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
+    method public android.view.View onCreateActionView();
+    method public androidx.mediarouter.app.MediaRouteButton onCreateMediaRouteButton();
+    method @Deprecated public void setAlwaysVisible(boolean);
+    method public void setDialogFactory(androidx.mediarouter.app.MediaRouteDialogFactory);
+    method public void setRouteSelector(androidx.mediarouter.media.MediaRouteSelector);
+  }
+
+  public class MediaRouteButton extends android.view.View {
+    ctor public MediaRouteButton(android.content.Context);
+    ctor public MediaRouteButton(android.content.Context, android.util.AttributeSet?);
+    ctor public MediaRouteButton(android.content.Context, android.util.AttributeSet?, int);
+    method @Deprecated public void enableDynamicGroup();
+    method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
+    method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
+    method public void onAttachedToWindow();
+    method public void onDetachedFromWindow();
+    method @Deprecated public void setAlwaysVisible(boolean);
+    method public void setDialogFactory(androidx.mediarouter.app.MediaRouteDialogFactory);
+    method public void setRemoteIndicatorDrawable(android.graphics.drawable.Drawable?);
+    method public void setRouteSelector(androidx.mediarouter.media.MediaRouteSelector);
+    method public boolean showDialog();
+  }
+
+  public class MediaRouteChooserDialog extends androidx.appcompat.app.AppCompatDialog {
+    ctor public MediaRouteChooserDialog(android.content.Context);
+    ctor public MediaRouteChooserDialog(android.content.Context, int);
+    method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
+    method public boolean onFilterRoute(androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void onFilterRoutes(java.util.List<androidx.mediarouter.media.MediaRouter.RouteInfo!>);
+    method public void refreshRoutes();
+    method public void setRouteSelector(androidx.mediarouter.media.MediaRouteSelector);
+  }
+
+  public class MediaRouteChooserDialogFragment extends androidx.fragment.app.DialogFragment {
+    ctor public MediaRouteChooserDialogFragment();
+    method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
+    method public androidx.mediarouter.app.MediaRouteChooserDialog onCreateChooserDialog(android.content.Context, android.os.Bundle?);
+    method public void setRouteSelector(androidx.mediarouter.media.MediaRouteSelector);
+  }
+
+  public class MediaRouteControllerDialog extends androidx.appcompat.app.AlertDialog {
+    ctor public MediaRouteControllerDialog(android.content.Context);
+    ctor public MediaRouteControllerDialog(android.content.Context, int);
+    method public android.view.View? getMediaControlView();
+    method public android.support.v4.media.session.MediaSessionCompat.Token? getMediaSession();
+    method public androidx.mediarouter.media.MediaRouter.RouteInfo getRoute();
+    method public boolean isVolumeControlEnabled();
+    method public android.view.View? onCreateMediaControlView(android.os.Bundle?);
+    method public void setVolumeControlEnabled(boolean);
+  }
+
+  public class MediaRouteControllerDialogFragment extends androidx.fragment.app.DialogFragment {
+    ctor public MediaRouteControllerDialogFragment();
+    method public androidx.mediarouter.app.MediaRouteControllerDialog onCreateControllerDialog(android.content.Context, android.os.Bundle?);
+  }
+
+  public class MediaRouteDialogFactory {
+    ctor public MediaRouteDialogFactory();
+    method public static androidx.mediarouter.app.MediaRouteDialogFactory getDefault();
+    method public androidx.mediarouter.app.MediaRouteChooserDialogFragment onCreateChooserDialogFragment();
+    method public androidx.mediarouter.app.MediaRouteControllerDialogFragment onCreateControllerDialogFragment();
+  }
+
+  public class MediaRouteDiscoveryFragment extends androidx.fragment.app.Fragment {
+    ctor public MediaRouteDiscoveryFragment();
+    method public androidx.mediarouter.media.MediaRouter getMediaRouter();
+    method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
+    method public androidx.mediarouter.media.MediaRouter.Callback? onCreateCallback();
+    method public int onPrepareCallbackFlags();
+    method public void setRouteSelector(androidx.mediarouter.media.MediaRouteSelector);
+  }
+
+  public final class SystemOutputSwitcherDialogController {
+    method public static boolean showDialog(android.content.Context);
+  }
+
+}
+
+package androidx.mediarouter.media {
+
+  public final class MediaControlIntent {
+    field public static final String ACTION_END_SESSION = "android.media.intent.action.END_SESSION";
+    field public static final String ACTION_ENQUEUE = "android.media.intent.action.ENQUEUE";
+    field public static final String ACTION_GET_SESSION_STATUS = "android.media.intent.action.GET_SESSION_STATUS";
+    field public static final String ACTION_GET_STATUS = "android.media.intent.action.GET_STATUS";
+    field public static final String ACTION_PAUSE = "android.media.intent.action.PAUSE";
+    field public static final String ACTION_PLAY = "android.media.intent.action.PLAY";
+    field public static final String ACTION_REMOVE = "android.media.intent.action.REMOVE";
+    field public static final String ACTION_RESUME = "android.media.intent.action.RESUME";
+    field public static final String ACTION_SEEK = "android.media.intent.action.SEEK";
+    field public static final String ACTION_SEND_MESSAGE = "android.media.intent.action.SEND_MESSAGE";
+    field public static final String ACTION_START_SESSION = "android.media.intent.action.START_SESSION";
+    field public static final String ACTION_STOP = "android.media.intent.action.STOP";
+    field public static final String CATEGORY_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
+    field public static final String CATEGORY_LIVE_VIDEO = "android.media.intent.category.LIVE_VIDEO";
+    field public static final String CATEGORY_REMOTE_PLAYBACK = "android.media.intent.category.REMOTE_PLAYBACK";
+    field public static final int ERROR_INVALID_ITEM_ID = 3; // 0x3
+    field public static final int ERROR_INVALID_SESSION_ID = 2; // 0x2
+    field public static final int ERROR_UNKNOWN = 0; // 0x0
+    field public static final int ERROR_UNSUPPORTED_OPERATION = 1; // 0x1
+    field public static final String EXTRA_ERROR_CODE = "android.media.intent.extra.ERROR_CODE";
+    field public static final String EXTRA_ITEM_CONTENT_POSITION = "android.media.intent.extra.ITEM_POSITION";
+    field public static final String EXTRA_ITEM_HTTP_HEADERS = "android.media.intent.extra.HTTP_HEADERS";
+    field public static final String EXTRA_ITEM_ID = "android.media.intent.extra.ITEM_ID";
+    field public static final String EXTRA_ITEM_METADATA = "android.media.intent.extra.ITEM_METADATA";
+    field public static final String EXTRA_ITEM_STATUS = "android.media.intent.extra.ITEM_STATUS";
+    field public static final String EXTRA_ITEM_STATUS_UPDATE_RECEIVER = "android.media.intent.extra.ITEM_STATUS_UPDATE_RECEIVER";
+    field public static final String EXTRA_MESSAGE = "android.media.intent.extra.MESSAGE";
+    field public static final String EXTRA_MESSAGE_RECEIVER = "android.media.intent.extra.MESSAGE_RECEIVER";
+    field public static final String EXTRA_SESSION_ID = "android.media.intent.extra.SESSION_ID";
+    field public static final String EXTRA_SESSION_STATUS = "android.media.intent.extra.SESSION_STATUS";
+    field public static final String EXTRA_SESSION_STATUS_UPDATE_RECEIVER = "android.media.intent.extra.SESSION_STATUS_UPDATE_RECEIVER";
+  }
+
+  public final class MediaItemMetadata {
+    field public static final String KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
+    field public static final String KEY_ALBUM_TITLE = "android.media.metadata.ALBUM_TITLE";
+    field public static final String KEY_ARTIST = "android.media.metadata.ARTIST";
+    field public static final String KEY_ARTWORK_URI = "android.media.metadata.ARTWORK_URI";
+    field public static final String KEY_AUTHOR = "android.media.metadata.AUTHOR";
+    field public static final String KEY_COMPOSER = "android.media.metadata.COMPOSER";
+    field public static final String KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
+    field public static final String KEY_DURATION = "android.media.metadata.DURATION";
+    field public static final String KEY_TITLE = "android.media.metadata.TITLE";
+    field public static final String KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER";
+    field public static final String KEY_YEAR = "android.media.metadata.YEAR";
+  }
+
+  public final class MediaItemStatus {
+    method public android.os.Bundle asBundle();
+    method public static androidx.mediarouter.media.MediaItemStatus? fromBundle(android.os.Bundle?);
+    method public long getContentDuration();
+    method public long getContentPosition();
+    method public android.os.Bundle? getExtras();
+    method public int getPlaybackState();
+    method public long getTimestamp();
+    field public static final String EXTRA_HTTP_RESPONSE_HEADERS = "android.media.status.extra.HTTP_RESPONSE_HEADERS";
+    field public static final String EXTRA_HTTP_STATUS_CODE = "android.media.status.extra.HTTP_STATUS_CODE";
+    field public static final int PLAYBACK_STATE_BUFFERING = 3; // 0x3
+    field public static final int PLAYBACK_STATE_CANCELED = 5; // 0x5
+    field public static final int PLAYBACK_STATE_ERROR = 7; // 0x7
+    field public static final int PLAYBACK_STATE_FINISHED = 4; // 0x4
+    field public static final int PLAYBACK_STATE_INVALIDATED = 6; // 0x6
+    field public static final int PLAYBACK_STATE_PAUSED = 2; // 0x2
+    field public static final int PLAYBACK_STATE_PENDING = 0; // 0x0
+    field public static final int PLAYBACK_STATE_PLAYING = 1; // 0x1
+  }
+
+  public static final class MediaItemStatus.Builder {
+    ctor public MediaItemStatus.Builder(androidx.mediarouter.media.MediaItemStatus);
+    ctor public MediaItemStatus.Builder(int);
+    method public androidx.mediarouter.media.MediaItemStatus build();
+    method public androidx.mediarouter.media.MediaItemStatus.Builder setContentDuration(long);
+    method public androidx.mediarouter.media.MediaItemStatus.Builder setContentPosition(long);
+    method public androidx.mediarouter.media.MediaItemStatus.Builder setExtras(android.os.Bundle?);
+    method public androidx.mediarouter.media.MediaItemStatus.Builder setPlaybackState(int);
+    method public androidx.mediarouter.media.MediaItemStatus.Builder setTimestamp(long);
+  }
+
+  public final class MediaRouteDescriptor {
+    method public android.os.Bundle asBundle();
+    method public boolean canDisconnectAndKeepPlaying();
+    method public static androidx.mediarouter.media.MediaRouteDescriptor? fromBundle(android.os.Bundle?);
+    method public java.util.Set<java.lang.String!> getAllowedPackages();
+    method public int getConnectionState();
+    method public java.util.List<android.content.IntentFilter!> getControlFilters();
+    method public java.util.Set<java.lang.String!> getDeduplicationIds();
+    method public String? getDescription();
+    method public int getDeviceType();
+    method public android.os.Bundle? getExtras();
+    method public android.net.Uri? getIconUri();
+    method public String getId();
+    method public String getName();
+    method public int getPlaybackStream();
+    method public int getPlaybackType();
+    method public int getPresentationDisplayId();
+    method public android.content.IntentSender? getSettingsActivity();
+    method public int getVolume();
+    method public int getVolumeHandling();
+    method public int getVolumeMax();
+    method @Deprecated public boolean isConnecting();
+    method public boolean isDynamicGroupRoute();
+    method public boolean isEnabled();
+    method public boolean isSystemRoute();
+    method public boolean isValid();
+    method public boolean isVisibilityPublic();
+  }
+
+  public static final class MediaRouteDescriptor.Builder {
+    ctor public MediaRouteDescriptor.Builder(androidx.mediarouter.media.MediaRouteDescriptor);
+    ctor public MediaRouteDescriptor.Builder(String, String);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder addControlFilter(android.content.IntentFilter);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder addControlFilters(java.util.Collection<android.content.IntentFilter!>);
+    method public androidx.mediarouter.media.MediaRouteDescriptor build();
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder clearControlFilters();
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setCanDisconnect(boolean);
+    method @Deprecated public androidx.mediarouter.media.MediaRouteDescriptor.Builder setConnecting(boolean);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setConnectionState(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setDeduplicationIds(java.util.Set<java.lang.String!>);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setDescription(String?);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setDeviceType(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setEnabled(boolean);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setExtras(android.os.Bundle?);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setIconUri(android.net.Uri);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setId(String);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setIsDynamicGroupRoute(boolean);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setName(String);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setPlaybackStream(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setPlaybackType(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setPresentationDisplayId(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setSettingsActivity(android.content.IntentSender?);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setVisibilityPublic();
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setVisibilityRestricted(java.util.Set<java.lang.String!>);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setVolume(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setVolumeHandling(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setVolumeMax(int);
+  }
+
+  public final class MediaRouteDiscoveryRequest {
+    ctor public MediaRouteDiscoveryRequest(androidx.mediarouter.media.MediaRouteSelector, boolean);
+    method public android.os.Bundle asBundle();
+    method public static androidx.mediarouter.media.MediaRouteDiscoveryRequest? fromBundle(android.os.Bundle?);
+    method public androidx.mediarouter.media.MediaRouteSelector getSelector();
+    method public boolean isActiveScan();
+    method public boolean isValid();
+  }
+
+  public abstract class MediaRouteProvider {
+    ctor public MediaRouteProvider(android.content.Context);
+    method public final android.content.Context getContext();
+    method public final androidx.mediarouter.media.MediaRouteProviderDescriptor? getDescriptor();
+    method public final androidx.mediarouter.media.MediaRouteDiscoveryRequest? getDiscoveryRequest();
+    method public final android.os.Handler getHandler();
+    method public final androidx.mediarouter.media.MediaRouteProvider.ProviderMetadata getMetadata();
+    method public androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController? onCreateDynamicGroupRouteController(String);
+    method public androidx.mediarouter.media.MediaRouteProvider.RouteController? onCreateRouteController(String);
+    method public void onDiscoveryRequestChanged(androidx.mediarouter.media.MediaRouteDiscoveryRequest?);
+    method public final void setCallback(androidx.mediarouter.media.MediaRouteProvider.Callback?);
+    method public final void setDescriptor(androidx.mediarouter.media.MediaRouteProviderDescriptor?);
+    method public final void setDiscoveryRequest(androidx.mediarouter.media.MediaRouteDiscoveryRequest?);
+  }
+
+  public abstract static class MediaRouteProvider.Callback {
+    ctor public MediaRouteProvider.Callback();
+    method public void onDescriptorChanged(androidx.mediarouter.media.MediaRouteProvider, androidx.mediarouter.media.MediaRouteProviderDescriptor?);
+  }
+
+  public abstract static class MediaRouteProvider.DynamicGroupRouteController extends androidx.mediarouter.media.MediaRouteProvider.RouteController {
+    ctor public MediaRouteProvider.DynamicGroupRouteController();
+    method public String? getGroupableSelectionTitle();
+    method public String? getTransferableSectionTitle();
+    method public final void notifyDynamicRoutesChanged(androidx.mediarouter.media.MediaRouteDescriptor, java.util.Collection<androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor!>);
+    method @Deprecated public final void notifyDynamicRoutesChanged(java.util.Collection<androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor!>);
+    method public abstract void onAddMemberRoute(String);
+    method public abstract void onRemoveMemberRoute(String);
+    method public abstract void onUpdateMemberRoutes(java.util.List<java.lang.String!>?);
+  }
+
+  public static final class MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor {
+    method public androidx.mediarouter.media.MediaRouteDescriptor getRouteDescriptor();
+    method public int getSelectionState();
+    method public boolean isGroupable();
+    method public boolean isTransferable();
+    method public boolean isUnselectable();
+    field public static final int SELECTED = 3; // 0x3
+    field public static final int SELECTING = 2; // 0x2
+    field public static final int UNSELECTED = 1; // 0x1
+    field public static final int UNSELECTING = 0; // 0x0
+  }
+
+  public static final class MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder {
+    ctor public MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder(androidx.mediarouter.media.MediaRouteDescriptor);
+    ctor public MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder(androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor);
+    method public androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor build();
+    method public androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder setIsGroupable(boolean);
+    method public androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder setIsTransferable(boolean);
+    method public androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder setIsUnselectable(boolean);
+    method public androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder setSelectionState(int);
+  }
+
+  public static final class MediaRouteProvider.ProviderMetadata {
+    method public android.content.ComponentName getComponentName();
+    method public String getPackageName();
+  }
+
+  public abstract static class MediaRouteProvider.RouteController {
+    ctor public MediaRouteProvider.RouteController();
+    method public boolean onControlRequest(android.content.Intent, androidx.mediarouter.media.MediaRouter.ControlRequestCallback?);
+    method public void onRelease();
+    method public void onSelect();
+    method public void onSetVolume(int);
+    method @Deprecated public void onUnselect();
+    method public void onUnselect(int);
+    method public void onUpdateVolume(int);
+  }
+
+  public final class MediaRouteProviderDescriptor {
+    method public android.os.Bundle asBundle();
+    method public static androidx.mediarouter.media.MediaRouteProviderDescriptor? fromBundle(android.os.Bundle?);
+    method public java.util.List<androidx.mediarouter.media.MediaRouteDescriptor!> getRoutes();
+    method public boolean isValid();
+    method public boolean supportsDynamicGroupRoute();
+  }
+
+  public static final class MediaRouteProviderDescriptor.Builder {
+    ctor public MediaRouteProviderDescriptor.Builder();
+    ctor public MediaRouteProviderDescriptor.Builder(androidx.mediarouter.media.MediaRouteProviderDescriptor);
+    method public androidx.mediarouter.media.MediaRouteProviderDescriptor.Builder addRoute(androidx.mediarouter.media.MediaRouteDescriptor);
+    method public androidx.mediarouter.media.MediaRouteProviderDescriptor.Builder addRoutes(java.util.Collection<androidx.mediarouter.media.MediaRouteDescriptor!>);
+    method public androidx.mediarouter.media.MediaRouteProviderDescriptor build();
+    method public androidx.mediarouter.media.MediaRouteProviderDescriptor.Builder setSupportsDynamicGroupRoute(boolean);
+  }
+
+  public abstract class MediaRouteProviderService extends android.app.Service {
+    ctor public MediaRouteProviderService();
+    method public androidx.mediarouter.media.MediaRouteProvider? getMediaRouteProvider();
+    method public android.os.IBinder? onBind(android.content.Intent);
+    method public abstract androidx.mediarouter.media.MediaRouteProvider? onCreateMediaRouteProvider();
+    field public static final String SERVICE_INTERFACE = "android.media.MediaRouteProviderService";
+  }
+
+  public final class MediaRouteSelector {
+    method public android.os.Bundle asBundle();
+    method public boolean contains(androidx.mediarouter.media.MediaRouteSelector);
+    method public static androidx.mediarouter.media.MediaRouteSelector? fromBundle(android.os.Bundle?);
+    method public java.util.List<java.lang.String!> getControlCategories();
+    method public boolean hasControlCategory(String?);
+    method public boolean isEmpty();
+    method public boolean isValid();
+    method public boolean matchesControlFilters(java.util.List<android.content.IntentFilter!>?);
+    field public static final androidx.mediarouter.media.MediaRouteSelector! EMPTY;
+  }
+
+  public static final class MediaRouteSelector.Builder {
+    ctor public MediaRouteSelector.Builder();
+    ctor public MediaRouteSelector.Builder(androidx.mediarouter.media.MediaRouteSelector);
+    method public androidx.mediarouter.media.MediaRouteSelector.Builder addControlCategories(java.util.Collection<java.lang.String!>);
+    method public androidx.mediarouter.media.MediaRouteSelector.Builder addControlCategory(String);
+    method public androidx.mediarouter.media.MediaRouteSelector.Builder addSelector(androidx.mediarouter.media.MediaRouteSelector);
+    method public androidx.mediarouter.media.MediaRouteSelector build();
+  }
+
+  public final class MediaRouter {
+    method @MainThread public void addCallback(androidx.mediarouter.media.MediaRouteSelector, androidx.mediarouter.media.MediaRouter.Callback);
+    method @MainThread public void addCallback(androidx.mediarouter.media.MediaRouteSelector, androidx.mediarouter.media.MediaRouter.Callback, int);
+    method @MainThread public void addProvider(androidx.mediarouter.media.MediaRouteProvider);
+    method @Deprecated @MainThread public void addRemoteControlClient(Object);
+    method @MainThread public androidx.mediarouter.media.MediaRouter.RouteInfo? getBluetoothRoute();
+    method @MainThread public androidx.mediarouter.media.MediaRouter.RouteInfo getDefaultRoute();
+    method @MainThread public static androidx.mediarouter.media.MediaRouter getInstance(android.content.Context);
+    method public android.support.v4.media.session.MediaSessionCompat.Token? getMediaSessionToken();
+    method @MainThread public java.util.List<androidx.mediarouter.media.MediaRouter.ProviderInfo!> getProviders();
+    method @MainThread public androidx.mediarouter.media.MediaRouterParams? getRouterParams();
+    method @MainThread public java.util.List<androidx.mediarouter.media.MediaRouter.RouteInfo!> getRoutes();
+    method @MainThread public androidx.mediarouter.media.MediaRouter.RouteInfo getSelectedRoute();
+    method @MainThread public boolean isRouteAvailable(androidx.mediarouter.media.MediaRouteSelector, int);
+    method @MainThread public void removeCallback(androidx.mediarouter.media.MediaRouter.Callback);
+    method @MainThread public void removeProvider(androidx.mediarouter.media.MediaRouteProvider);
+    method @Deprecated @MainThread public void removeRemoteControlClient(Object);
+    method @MainThread public void selectRoute(androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method @MainThread public void setMediaSession(Object?);
+    method @MainThread public void setMediaSessionCompat(android.support.v4.media.session.MediaSessionCompat?);
+    method @MainThread public void setOnPrepareTransferListener(androidx.mediarouter.media.MediaRouter.OnPrepareTransferListener?);
+    method @MainThread public void setRouteListingPreference(androidx.mediarouter.media.RouteListingPreference?);
+    method @MainThread public void setRouterParams(androidx.mediarouter.media.MediaRouterParams?);
+    method @MainThread public void unselect(int);
+    method @MainThread public androidx.mediarouter.media.MediaRouter.RouteInfo updateSelectedRoute(androidx.mediarouter.media.MediaRouteSelector);
+    field public static final int AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE = 1; // 0x1
+    field public static final int AVAILABILITY_FLAG_REQUIRE_MATCH = 2; // 0x2
+    field public static final int CALLBACK_FLAG_FORCE_DISCOVERY = 8; // 0x8
+    field public static final int CALLBACK_FLAG_PERFORM_ACTIVE_SCAN = 1; // 0x1
+    field public static final int CALLBACK_FLAG_REQUEST_DISCOVERY = 4; // 0x4
+    field public static final int CALLBACK_FLAG_UNFILTERED_EVENTS = 2; // 0x2
+    field public static final int UNSELECT_REASON_DISCONNECTED = 1; // 0x1
+    field public static final int UNSELECT_REASON_ROUTE_CHANGED = 3; // 0x3
+    field public static final int UNSELECT_REASON_STOPPED = 2; // 0x2
+    field public static final int UNSELECT_REASON_UNKNOWN = 0; // 0x0
+  }
+
+  public abstract static class MediaRouter.Callback {
+    ctor public MediaRouter.Callback();
+    method public void onProviderAdded(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.ProviderInfo);
+    method public void onProviderChanged(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.ProviderInfo);
+    method public void onProviderRemoved(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.ProviderInfo);
+    method public void onRouteAdded(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void onRouteChanged(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void onRoutePresentationDisplayChanged(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void onRouteRemoved(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method @Deprecated public void onRouteSelected(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void onRouteSelected(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo, int);
+    method public void onRouteSelected(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo, int, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method @Deprecated public void onRouteUnselected(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void onRouteUnselected(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo, int);
+    method public void onRouteVolumeChanged(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+  }
+
+  public abstract static class MediaRouter.ControlRequestCallback {
+    ctor public MediaRouter.ControlRequestCallback();
+    method public void onError(String?, android.os.Bundle?);
+    method public void onResult(android.os.Bundle?);
+  }
+
+  public static interface MediaRouter.OnPrepareTransferListener {
+    method @MainThread public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!>? onPrepareTransfer(androidx.mediarouter.media.MediaRouter.RouteInfo, androidx.mediarouter.media.MediaRouter.RouteInfo);
+  }
+
+  public static final class MediaRouter.ProviderInfo {
+    method public android.content.ComponentName getComponentName();
+    method public String getPackageName();
+    method @MainThread public androidx.mediarouter.media.MediaRouteProvider getProviderInstance();
+    method @MainThread public java.util.List<androidx.mediarouter.media.MediaRouter.RouteInfo!> getRoutes();
+  }
+
+  public static class MediaRouter.RouteInfo {
+    method public boolean canDisconnect();
+    method public int getConnectionState();
+    method public java.util.List<android.content.IntentFilter!> getControlFilters();
+    method public String? getDescription();
+    method public int getDeviceType();
+    method public android.os.Bundle? getExtras();
+    method public android.net.Uri? getIconUri();
+    method public String getId();
+    method public String getName();
+    method public int getPlaybackStream();
+    method public int getPlaybackType();
+    method @MainThread public android.view.Display? getPresentationDisplay();
+    method public androidx.mediarouter.media.MediaRouter.ProviderInfo getProvider();
+    method public android.content.IntentSender? getSettingsIntent();
+    method public int getVolume();
+    method public int getVolumeHandling();
+    method public int getVolumeMax();
+    method @MainThread public boolean isBluetooth();
+    method @Deprecated public boolean isConnecting();
+    method @MainThread public boolean isDefault();
+    method public boolean isDeviceSpeaker();
+    method public boolean isEnabled();
+    method @MainThread public boolean isSelected();
+    method public boolean isSystemRoute();
+    method @MainThread public boolean matchesSelector(androidx.mediarouter.media.MediaRouteSelector);
+    method @MainThread public void requestSetVolume(int);
+    method @MainThread public void requestUpdateVolume(int);
+    method @MainThread public void select();
+    method @MainThread public void sendControlRequest(android.content.Intent, androidx.mediarouter.media.MediaRouter.ControlRequestCallback?);
+    method @MainThread public boolean supportsControlAction(String, String);
+    method @MainThread public boolean supportsControlCategory(String);
+    method @MainThread public boolean supportsControlRequest(android.content.Intent);
+    field public static final int CONNECTION_STATE_CONNECTED = 2; // 0x2
+    field public static final int CONNECTION_STATE_CONNECTING = 1; // 0x1
+    field public static final int CONNECTION_STATE_DISCONNECTED = 0; // 0x0
+    field public static final int DEVICE_TYPE_AUDIO_VIDEO_RECEIVER = 4; // 0x4
+    field public static final int DEVICE_TYPE_BLE_HEADSET = 22; // 0x16
+    field public static final int DEVICE_TYPE_BLUETOOTH_A2DP = 3; // 0x3
+    field public static final int DEVICE_TYPE_BUILTIN_SPEAKER = 12; // 0xc
+    field public static final int DEVICE_TYPE_CAR = 9; // 0x9
+    field public static final int DEVICE_TYPE_COMPUTER = 7; // 0x7
+    field public static final int DEVICE_TYPE_DOCK = 19; // 0x13
+    field public static final int DEVICE_TYPE_GAME_CONSOLE = 8; // 0x8
+    field public static final int DEVICE_TYPE_GROUP = 1000; // 0x3e8
+    field public static final int DEVICE_TYPE_HDMI = 16; // 0x10
+    field public static final int DEVICE_TYPE_HDMI_ARC = 23; // 0x17
+    field public static final int DEVICE_TYPE_HDMI_EARC = 24; // 0x18
+    field public static final int DEVICE_TYPE_HEARING_AID = 21; // 0x15
+    field public static final int DEVICE_TYPE_REMOTE_SPEAKER = 2; // 0x2
+    field public static final int DEVICE_TYPE_SMARTPHONE = 11; // 0xb
+    field public static final int DEVICE_TYPE_SMARTWATCH = 10; // 0xa
+    field @Deprecated public static final int DEVICE_TYPE_SPEAKER = 2; // 0x2
+    field public static final int DEVICE_TYPE_TABLET = 5; // 0x5
+    field public static final int DEVICE_TYPE_TABLET_DOCKED = 6; // 0x6
+    field public static final int DEVICE_TYPE_TV = 1; // 0x1
+    field public static final int DEVICE_TYPE_USB_ACCESSORY = 18; // 0x12
+    field public static final int DEVICE_TYPE_USB_DEVICE = 17; // 0x11
+    field public static final int DEVICE_TYPE_USB_HEADSET = 20; // 0x14
+    field public static final int DEVICE_TYPE_WIRED_HEADPHONES = 14; // 0xe
+    field public static final int DEVICE_TYPE_WIRED_HEADSET = 13; // 0xd
+    field public static final int PLAYBACK_TYPE_LOCAL = 0; // 0x0
+    field public static final int PLAYBACK_TYPE_REMOTE = 1; // 0x1
+    field public static final int PLAYBACK_VOLUME_FIXED = 0; // 0x0
+    field public static final int PLAYBACK_VOLUME_VARIABLE = 1; // 0x1
+  }
+
+  public class MediaRouterParams {
+    method public int getDialogType();
+    method public boolean isMediaTransferReceiverEnabled();
+    method public boolean isOutputSwitcherEnabled();
+    method public boolean isTransferToLocalEnabled();
+    field public static final int DIALOG_TYPE_DEFAULT = 1; // 0x1
+    field public static final int DIALOG_TYPE_DYNAMIC_GROUP = 2; // 0x2
+    field public static final String ENABLE_GROUP_VOLUME_UX = "androidx.mediarouter.media.MediaRouterParams.ENABLE_GROUP_VOLUME_UX";
+  }
+
+  public static final class MediaRouterParams.Builder {
+    ctor public MediaRouterParams.Builder();
+    ctor public MediaRouterParams.Builder(androidx.mediarouter.media.MediaRouterParams);
+    method public androidx.mediarouter.media.MediaRouterParams build();
+    method public androidx.mediarouter.media.MediaRouterParams.Builder setDialogType(int);
+    method public androidx.mediarouter.media.MediaRouterParams.Builder setMediaTransferReceiverEnabled(boolean);
+    method public androidx.mediarouter.media.MediaRouterParams.Builder setOutputSwitcherEnabled(boolean);
+    method public androidx.mediarouter.media.MediaRouterParams.Builder setTransferToLocalEnabled(boolean);
+  }
+
+  public final class MediaSessionStatus {
+    method public android.os.Bundle asBundle();
+    method public static androidx.mediarouter.media.MediaSessionStatus? fromBundle(android.os.Bundle?);
+    method public android.os.Bundle? getExtras();
+    method public int getSessionState();
+    method public long getTimestamp();
+    method public boolean isQueuePaused();
+    field public static final int SESSION_STATE_ACTIVE = 0; // 0x0
+    field public static final int SESSION_STATE_ENDED = 1; // 0x1
+    field public static final int SESSION_STATE_INVALIDATED = 2; // 0x2
+  }
+
+  public static final class MediaSessionStatus.Builder {
+    ctor public MediaSessionStatus.Builder(androidx.mediarouter.media.MediaSessionStatus);
+    ctor public MediaSessionStatus.Builder(int);
+    method public androidx.mediarouter.media.MediaSessionStatus build();
+    method public androidx.mediarouter.media.MediaSessionStatus.Builder setExtras(android.os.Bundle?);
+    method public androidx.mediarouter.media.MediaSessionStatus.Builder setQueuePaused(boolean);
+    method public androidx.mediarouter.media.MediaSessionStatus.Builder setSessionState(int);
+    method public androidx.mediarouter.media.MediaSessionStatus.Builder setTimestamp(long);
+  }
+
+  public final class MediaTransferReceiver extends android.content.BroadcastReceiver {
+    ctor public MediaTransferReceiver();
+    method public void onReceive(android.content.Context, android.content.Intent);
+  }
+
+  public class RemotePlaybackClient {
+    ctor public RemotePlaybackClient(android.content.Context, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void endSession(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+    method public void enqueue(android.net.Uri, String?, android.os.Bundle?, long, android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.ItemActionCallback?);
+    method public String? getSessionId();
+    method public void getSessionStatus(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+    method public void getStatus(String, android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.ItemActionCallback?);
+    method public boolean hasSession();
+    method public boolean isMessagingSupported();
+    method public boolean isQueuingSupported();
+    method public boolean isRemotePlaybackSupported();
+    method public boolean isSessionManagementSupported();
+    method public void pause(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+    method public void play(android.net.Uri, String?, android.os.Bundle?, long, android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.ItemActionCallback?);
+    method public void release();
+    method public void remove(String, android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.ItemActionCallback?);
+    method public void resume(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+    method public void seek(String, long, android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.ItemActionCallback?);
+    method public void sendMessage(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+    method public void setOnMessageReceivedListener(androidx.mediarouter.media.RemotePlaybackClient.OnMessageReceivedListener?);
+    method public void setSessionId(String?);
+    method public void setStatusCallback(androidx.mediarouter.media.RemotePlaybackClient.StatusCallback?);
+    method public void startSession(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+    method public void stop(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+  }
+
+  public abstract static class RemotePlaybackClient.ActionCallback {
+    ctor public RemotePlaybackClient.ActionCallback();
+    method public void onError(String?, int, android.os.Bundle?);
+  }
+
+  public abstract static class RemotePlaybackClient.ItemActionCallback extends androidx.mediarouter.media.RemotePlaybackClient.ActionCallback {
+    ctor public RemotePlaybackClient.ItemActionCallback();
+    method public void onResult(android.os.Bundle, String, androidx.mediarouter.media.MediaSessionStatus?, String, androidx.mediarouter.media.MediaItemStatus);
+  }
+
+  public static interface RemotePlaybackClient.OnMessageReceivedListener {
+    method public void onMessageReceived(String, android.os.Bundle?);
+  }
+
+  public abstract static class RemotePlaybackClient.SessionActionCallback extends androidx.mediarouter.media.RemotePlaybackClient.ActionCallback {
+    ctor public RemotePlaybackClient.SessionActionCallback();
+    method public void onResult(android.os.Bundle, String, androidx.mediarouter.media.MediaSessionStatus?);
+  }
+
+  public abstract static class RemotePlaybackClient.StatusCallback {
+    ctor public RemotePlaybackClient.StatusCallback();
+    method public void onItemStatusChanged(android.os.Bundle?, String, androidx.mediarouter.media.MediaSessionStatus?, String, androidx.mediarouter.media.MediaItemStatus);
+    method public void onSessionChanged(String?);
+    method public void onSessionStatusChanged(android.os.Bundle?, String, androidx.mediarouter.media.MediaSessionStatus?);
+  }
+
+  public final class RouteListingPreference {
+    method public java.util.List<androidx.mediarouter.media.RouteListingPreference.Item!> getItems();
+    method public android.content.ComponentName? getLinkedItemComponentName();
+    method public boolean isSystemOrderingEnabled();
+    field public static final String ACTION_TRANSFER_MEDIA = "android.media.action.TRANSFER_MEDIA";
+    field public static final String EXTRA_ROUTE_ID = "android.media.extra.ROUTE_ID";
+  }
+
+  public static final class RouteListingPreference.Builder {
+    ctor public RouteListingPreference.Builder();
+    method public androidx.mediarouter.media.RouteListingPreference build();
+    method public androidx.mediarouter.media.RouteListingPreference.Builder setItems(java.util.List<androidx.mediarouter.media.RouteListingPreference.Item!>);
+    method public androidx.mediarouter.media.RouteListingPreference.Builder setLinkedItemComponentName(android.content.ComponentName?);
+    method public androidx.mediarouter.media.RouteListingPreference.Builder setSystemOrderingEnabled(boolean);
+  }
+
+  public static final class RouteListingPreference.Item {
+    method public CharSequence? getCustomSubtextMessage();
+    method public int getFlags();
+    method public String getRouteId();
+    method public int getSelectionBehavior();
+    method public int getSubText();
+    field public static final int FLAG_ONGOING_SESSION = 1; // 0x1
+    field public static final int FLAG_ONGOING_SESSION_MANAGED = 2; // 0x2
+    field public static final int FLAG_SUGGESTED = 4; // 0x4
+    field public static final int SELECTION_BEHAVIOR_GO_TO_APP = 2; // 0x2
+    field public static final int SELECTION_BEHAVIOR_NONE = 0; // 0x0
+    field public static final int SELECTION_BEHAVIOR_TRANSFER = 1; // 0x1
+    field public static final int SUBTEXT_AD_ROUTING_DISALLOWED = 4; // 0x4
+    field public static final int SUBTEXT_CUSTOM = 10000; // 0x2710
+    field public static final int SUBTEXT_DEVICE_LOW_POWER = 5; // 0x5
+    field public static final int SUBTEXT_DOWNLOADED_CONTENT_ROUTING_DISALLOWED = 3; // 0x3
+    field public static final int SUBTEXT_ERROR_UNKNOWN = 1; // 0x1
+    field public static final int SUBTEXT_NONE = 0; // 0x0
+    field public static final int SUBTEXT_SUBSCRIPTION_REQUIRED = 2; // 0x2
+    field public static final int SUBTEXT_TRACK_UNSUPPORTED = 7; // 0x7
+    field public static final int SUBTEXT_UNAUTHORIZED = 6; // 0x6
+  }
+
+  public static final class RouteListingPreference.Item.Builder {
+    ctor public RouteListingPreference.Item.Builder(String);
+    method public androidx.mediarouter.media.RouteListingPreference.Item build();
+    method public androidx.mediarouter.media.RouteListingPreference.Item.Builder setCustomSubtextMessage(CharSequence?);
+    method public androidx.mediarouter.media.RouteListingPreference.Item.Builder setFlags(int);
+    method public androidx.mediarouter.media.RouteListingPreference.Item.Builder setSelectionBehavior(int);
+    method public androidx.mediarouter.media.RouteListingPreference.Item.Builder setSubText(int);
+  }
+
+}
+
diff --git a/mediarouter/mediarouter/api/res-1.7.0-beta01.txt b/mediarouter/mediarouter/api/res-1.7.0-beta01.txt
new file mode 100644
index 0000000..620c3fe
--- /dev/null
+++ b/mediarouter/mediarouter/api/res-1.7.0-beta01.txt
@@ -0,0 +1,4 @@
+dimen mediarouter_chooser_list_item_padding_bottom
+dimen mediarouter_chooser_list_item_padding_end
+dimen mediarouter_chooser_list_item_padding_start
+dimen mediarouter_chooser_list_item_padding_top
diff --git a/mediarouter/mediarouter/api/restricted_1.7.0-beta01.txt b/mediarouter/mediarouter/api/restricted_1.7.0-beta01.txt
new file mode 100644
index 0000000..e67bdb6
--- /dev/null
+++ b/mediarouter/mediarouter/api/restricted_1.7.0-beta01.txt
@@ -0,0 +1,638 @@
+// Signature format: 4.0
+package androidx.mediarouter.app {
+
+  public class MediaRouteActionProvider extends androidx.core.view.ActionProvider {
+    ctor public MediaRouteActionProvider(android.content.Context);
+    method @Deprecated public void enableDynamicGroup();
+    method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
+    method public androidx.mediarouter.app.MediaRouteButton? getMediaRouteButton();
+    method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
+    method public android.view.View onCreateActionView();
+    method public androidx.mediarouter.app.MediaRouteButton onCreateMediaRouteButton();
+    method @Deprecated public void setAlwaysVisible(boolean);
+    method public void setDialogFactory(androidx.mediarouter.app.MediaRouteDialogFactory);
+    method public void setRouteSelector(androidx.mediarouter.media.MediaRouteSelector);
+  }
+
+  public class MediaRouteButton extends android.view.View {
+    ctor public MediaRouteButton(android.content.Context);
+    ctor public MediaRouteButton(android.content.Context, android.util.AttributeSet?);
+    ctor public MediaRouteButton(android.content.Context, android.util.AttributeSet?, int);
+    method @Deprecated public void enableDynamicGroup();
+    method public androidx.mediarouter.app.MediaRouteDialogFactory getDialogFactory();
+    method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
+    method public void onAttachedToWindow();
+    method public void onDetachedFromWindow();
+    method @Deprecated public void setAlwaysVisible(boolean);
+    method public void setDialogFactory(androidx.mediarouter.app.MediaRouteDialogFactory);
+    method public void setRemoteIndicatorDrawable(android.graphics.drawable.Drawable?);
+    method public void setRouteSelector(androidx.mediarouter.media.MediaRouteSelector);
+    method public boolean showDialog();
+  }
+
+  public class MediaRouteChooserDialog extends androidx.appcompat.app.AppCompatDialog {
+    ctor public MediaRouteChooserDialog(android.content.Context);
+    ctor public MediaRouteChooserDialog(android.content.Context, int);
+    method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
+    method public boolean onFilterRoute(androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void onFilterRoutes(java.util.List<androidx.mediarouter.media.MediaRouter.RouteInfo!>);
+    method public void refreshRoutes();
+    method public void setRouteSelector(androidx.mediarouter.media.MediaRouteSelector);
+  }
+
+  public class MediaRouteChooserDialogFragment extends androidx.fragment.app.DialogFragment {
+    ctor public MediaRouteChooserDialogFragment();
+    method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
+    method public androidx.mediarouter.app.MediaRouteChooserDialog onCreateChooserDialog(android.content.Context, android.os.Bundle?);
+    method public void setRouteSelector(androidx.mediarouter.media.MediaRouteSelector);
+  }
+
+  public class MediaRouteControllerDialog extends androidx.appcompat.app.AlertDialog {
+    ctor public MediaRouteControllerDialog(android.content.Context);
+    ctor public MediaRouteControllerDialog(android.content.Context, int);
+    method public android.view.View? getMediaControlView();
+    method public android.support.v4.media.session.MediaSessionCompat.Token? getMediaSession();
+    method public androidx.mediarouter.media.MediaRouter.RouteInfo getRoute();
+    method public boolean isVolumeControlEnabled();
+    method public android.view.View? onCreateMediaControlView(android.os.Bundle?);
+    method public void setVolumeControlEnabled(boolean);
+  }
+
+  public class MediaRouteControllerDialogFragment extends androidx.fragment.app.DialogFragment {
+    ctor public MediaRouteControllerDialogFragment();
+    method public androidx.mediarouter.app.MediaRouteControllerDialog onCreateControllerDialog(android.content.Context, android.os.Bundle?);
+  }
+
+  public class MediaRouteDialogFactory {
+    ctor public MediaRouteDialogFactory();
+    method public static androidx.mediarouter.app.MediaRouteDialogFactory getDefault();
+    method public androidx.mediarouter.app.MediaRouteChooserDialogFragment onCreateChooserDialogFragment();
+    method public androidx.mediarouter.app.MediaRouteControllerDialogFragment onCreateControllerDialogFragment();
+  }
+
+  public class MediaRouteDiscoveryFragment extends androidx.fragment.app.Fragment {
+    ctor public MediaRouteDiscoveryFragment();
+    method public androidx.mediarouter.media.MediaRouter getMediaRouter();
+    method public androidx.mediarouter.media.MediaRouteSelector getRouteSelector();
+    method public androidx.mediarouter.media.MediaRouter.Callback? onCreateCallback();
+    method public int onPrepareCallbackFlags();
+    method public void setRouteSelector(androidx.mediarouter.media.MediaRouteSelector);
+  }
+
+  public final class SystemOutputSwitcherDialogController {
+    method public static boolean showDialog(android.content.Context);
+  }
+
+}
+
+package androidx.mediarouter.media {
+
+  public final class MediaControlIntent {
+    field public static final String ACTION_END_SESSION = "android.media.intent.action.END_SESSION";
+    field public static final String ACTION_ENQUEUE = "android.media.intent.action.ENQUEUE";
+    field public static final String ACTION_GET_SESSION_STATUS = "android.media.intent.action.GET_SESSION_STATUS";
+    field public static final String ACTION_GET_STATUS = "android.media.intent.action.GET_STATUS";
+    field public static final String ACTION_PAUSE = "android.media.intent.action.PAUSE";
+    field public static final String ACTION_PLAY = "android.media.intent.action.PLAY";
+    field public static final String ACTION_REMOVE = "android.media.intent.action.REMOVE";
+    field public static final String ACTION_RESUME = "android.media.intent.action.RESUME";
+    field public static final String ACTION_SEEK = "android.media.intent.action.SEEK";
+    field public static final String ACTION_SEND_MESSAGE = "android.media.intent.action.SEND_MESSAGE";
+    field public static final String ACTION_START_SESSION = "android.media.intent.action.START_SESSION";
+    field public static final String ACTION_STOP = "android.media.intent.action.STOP";
+    field public static final String CATEGORY_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
+    field public static final String CATEGORY_LIVE_VIDEO = "android.media.intent.category.LIVE_VIDEO";
+    field public static final String CATEGORY_REMOTE_PLAYBACK = "android.media.intent.category.REMOTE_PLAYBACK";
+    field public static final int ERROR_INVALID_ITEM_ID = 3; // 0x3
+    field public static final int ERROR_INVALID_SESSION_ID = 2; // 0x2
+    field public static final int ERROR_UNKNOWN = 0; // 0x0
+    field public static final int ERROR_UNSUPPORTED_OPERATION = 1; // 0x1
+    field public static final String EXTRA_ERROR_CODE = "android.media.intent.extra.ERROR_CODE";
+    field public static final String EXTRA_ITEM_CONTENT_POSITION = "android.media.intent.extra.ITEM_POSITION";
+    field public static final String EXTRA_ITEM_HTTP_HEADERS = "android.media.intent.extra.HTTP_HEADERS";
+    field public static final String EXTRA_ITEM_ID = "android.media.intent.extra.ITEM_ID";
+    field public static final String EXTRA_ITEM_METADATA = "android.media.intent.extra.ITEM_METADATA";
+    field public static final String EXTRA_ITEM_STATUS = "android.media.intent.extra.ITEM_STATUS";
+    field public static final String EXTRA_ITEM_STATUS_UPDATE_RECEIVER = "android.media.intent.extra.ITEM_STATUS_UPDATE_RECEIVER";
+    field public static final String EXTRA_MESSAGE = "android.media.intent.extra.MESSAGE";
+    field public static final String EXTRA_MESSAGE_RECEIVER = "android.media.intent.extra.MESSAGE_RECEIVER";
+    field public static final String EXTRA_SESSION_ID = "android.media.intent.extra.SESSION_ID";
+    field public static final String EXTRA_SESSION_STATUS = "android.media.intent.extra.SESSION_STATUS";
+    field public static final String EXTRA_SESSION_STATUS_UPDATE_RECEIVER = "android.media.intent.extra.SESSION_STATUS_UPDATE_RECEIVER";
+  }
+
+  public final class MediaItemMetadata {
+    field public static final String KEY_ALBUM_ARTIST = "android.media.metadata.ALBUM_ARTIST";
+    field public static final String KEY_ALBUM_TITLE = "android.media.metadata.ALBUM_TITLE";
+    field public static final String KEY_ARTIST = "android.media.metadata.ARTIST";
+    field public static final String KEY_ARTWORK_URI = "android.media.metadata.ARTWORK_URI";
+    field public static final String KEY_AUTHOR = "android.media.metadata.AUTHOR";
+    field public static final String KEY_COMPOSER = "android.media.metadata.COMPOSER";
+    field public static final String KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
+    field public static final String KEY_DURATION = "android.media.metadata.DURATION";
+    field public static final String KEY_TITLE = "android.media.metadata.TITLE";
+    field public static final String KEY_TRACK_NUMBER = "android.media.metadata.TRACK_NUMBER";
+    field public static final String KEY_YEAR = "android.media.metadata.YEAR";
+  }
+
+  public final class MediaItemStatus {
+    method public android.os.Bundle asBundle();
+    method public static androidx.mediarouter.media.MediaItemStatus? fromBundle(android.os.Bundle?);
+    method public long getContentDuration();
+    method public long getContentPosition();
+    method public android.os.Bundle? getExtras();
+    method public int getPlaybackState();
+    method public long getTimestamp();
+    field public static final String EXTRA_HTTP_RESPONSE_HEADERS = "android.media.status.extra.HTTP_RESPONSE_HEADERS";
+    field public static final String EXTRA_HTTP_STATUS_CODE = "android.media.status.extra.HTTP_STATUS_CODE";
+    field public static final int PLAYBACK_STATE_BUFFERING = 3; // 0x3
+    field public static final int PLAYBACK_STATE_CANCELED = 5; // 0x5
+    field public static final int PLAYBACK_STATE_ERROR = 7; // 0x7
+    field public static final int PLAYBACK_STATE_FINISHED = 4; // 0x4
+    field public static final int PLAYBACK_STATE_INVALIDATED = 6; // 0x6
+    field public static final int PLAYBACK_STATE_PAUSED = 2; // 0x2
+    field public static final int PLAYBACK_STATE_PENDING = 0; // 0x0
+    field public static final int PLAYBACK_STATE_PLAYING = 1; // 0x1
+  }
+
+  public static final class MediaItemStatus.Builder {
+    ctor public MediaItemStatus.Builder(androidx.mediarouter.media.MediaItemStatus);
+    ctor public MediaItemStatus.Builder(int);
+    method public androidx.mediarouter.media.MediaItemStatus build();
+    method public androidx.mediarouter.media.MediaItemStatus.Builder setContentDuration(long);
+    method public androidx.mediarouter.media.MediaItemStatus.Builder setContentPosition(long);
+    method public androidx.mediarouter.media.MediaItemStatus.Builder setExtras(android.os.Bundle?);
+    method public androidx.mediarouter.media.MediaItemStatus.Builder setPlaybackState(int);
+    method public androidx.mediarouter.media.MediaItemStatus.Builder setTimestamp(long);
+  }
+
+  public final class MediaRouteDescriptor {
+    method public android.os.Bundle asBundle();
+    method public boolean canDisconnectAndKeepPlaying();
+    method public static androidx.mediarouter.media.MediaRouteDescriptor? fromBundle(android.os.Bundle?);
+    method public java.util.Set<java.lang.String!> getAllowedPackages();
+    method public int getConnectionState();
+    method public java.util.List<android.content.IntentFilter!> getControlFilters();
+    method public java.util.Set<java.lang.String!> getDeduplicationIds();
+    method public String? getDescription();
+    method public int getDeviceType();
+    method public android.os.Bundle? getExtras();
+    method public android.net.Uri? getIconUri();
+    method public String getId();
+    method public String getName();
+    method public int getPlaybackStream();
+    method public int getPlaybackType();
+    method public int getPresentationDisplayId();
+    method public android.content.IntentSender? getSettingsActivity();
+    method public int getVolume();
+    method public int getVolumeHandling();
+    method public int getVolumeMax();
+    method @Deprecated public boolean isConnecting();
+    method public boolean isDynamicGroupRoute();
+    method public boolean isEnabled();
+    method public boolean isSystemRoute();
+    method public boolean isValid();
+    method public boolean isVisibilityPublic();
+  }
+
+  public static final class MediaRouteDescriptor.Builder {
+    ctor public MediaRouteDescriptor.Builder(androidx.mediarouter.media.MediaRouteDescriptor);
+    ctor public MediaRouteDescriptor.Builder(String, String);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder addControlFilter(android.content.IntentFilter);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder addControlFilters(java.util.Collection<android.content.IntentFilter!>);
+    method public androidx.mediarouter.media.MediaRouteDescriptor build();
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder clearControlFilters();
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setCanDisconnect(boolean);
+    method @Deprecated public androidx.mediarouter.media.MediaRouteDescriptor.Builder setConnecting(boolean);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setConnectionState(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setDeduplicationIds(java.util.Set<java.lang.String!>);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setDescription(String?);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setDeviceType(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setEnabled(boolean);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setExtras(android.os.Bundle?);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setIconUri(android.net.Uri);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setId(String);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setIsDynamicGroupRoute(boolean);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setName(String);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setPlaybackStream(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setPlaybackType(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setPresentationDisplayId(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setSettingsActivity(android.content.IntentSender?);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setVisibilityPublic();
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setVisibilityRestricted(java.util.Set<java.lang.String!>);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setVolume(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setVolumeHandling(int);
+    method public androidx.mediarouter.media.MediaRouteDescriptor.Builder setVolumeMax(int);
+  }
+
+  public final class MediaRouteDiscoveryRequest {
+    ctor public MediaRouteDiscoveryRequest(androidx.mediarouter.media.MediaRouteSelector, boolean);
+    method public android.os.Bundle asBundle();
+    method public static androidx.mediarouter.media.MediaRouteDiscoveryRequest? fromBundle(android.os.Bundle?);
+    method public androidx.mediarouter.media.MediaRouteSelector getSelector();
+    method public boolean isActiveScan();
+    method public boolean isValid();
+  }
+
+  public abstract class MediaRouteProvider {
+    ctor public MediaRouteProvider(android.content.Context);
+    method public final android.content.Context getContext();
+    method public final androidx.mediarouter.media.MediaRouteProviderDescriptor? getDescriptor();
+    method public final androidx.mediarouter.media.MediaRouteDiscoveryRequest? getDiscoveryRequest();
+    method public final android.os.Handler getHandler();
+    method public final androidx.mediarouter.media.MediaRouteProvider.ProviderMetadata getMetadata();
+    method public androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController? onCreateDynamicGroupRouteController(String);
+    method public androidx.mediarouter.media.MediaRouteProvider.RouteController? onCreateRouteController(String);
+    method public void onDiscoveryRequestChanged(androidx.mediarouter.media.MediaRouteDiscoveryRequest?);
+    method public final void setCallback(androidx.mediarouter.media.MediaRouteProvider.Callback?);
+    method public final void setDescriptor(androidx.mediarouter.media.MediaRouteProviderDescriptor?);
+    method public final void setDiscoveryRequest(androidx.mediarouter.media.MediaRouteDiscoveryRequest?);
+  }
+
+  public abstract static class MediaRouteProvider.Callback {
+    ctor public MediaRouteProvider.Callback();
+    method public void onDescriptorChanged(androidx.mediarouter.media.MediaRouteProvider, androidx.mediarouter.media.MediaRouteProviderDescriptor?);
+  }
+
+  public abstract static class MediaRouteProvider.DynamicGroupRouteController extends androidx.mediarouter.media.MediaRouteProvider.RouteController {
+    ctor public MediaRouteProvider.DynamicGroupRouteController();
+    method public String? getGroupableSelectionTitle();
+    method public String? getTransferableSectionTitle();
+    method public final void notifyDynamicRoutesChanged(androidx.mediarouter.media.MediaRouteDescriptor, java.util.Collection<androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor!>);
+    method @Deprecated public final void notifyDynamicRoutesChanged(java.util.Collection<androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor!>);
+    method public abstract void onAddMemberRoute(String);
+    method public abstract void onRemoveMemberRoute(String);
+    method public abstract void onUpdateMemberRoutes(java.util.List<java.lang.String!>?);
+  }
+
+  public static final class MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor {
+    method public androidx.mediarouter.media.MediaRouteDescriptor getRouteDescriptor();
+    method public int getSelectionState();
+    method public boolean isGroupable();
+    method public boolean isTransferable();
+    method public boolean isUnselectable();
+    field public static final int SELECTED = 3; // 0x3
+    field public static final int SELECTING = 2; // 0x2
+    field public static final int UNSELECTED = 1; // 0x1
+    field public static final int UNSELECTING = 0; // 0x0
+  }
+
+  public static final class MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder {
+    ctor public MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder(androidx.mediarouter.media.MediaRouteDescriptor);
+    ctor public MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder(androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor);
+    method public androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor build();
+    method public androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder setIsGroupable(boolean);
+    method public androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder setIsTransferable(boolean);
+    method public androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder setIsUnselectable(boolean);
+    method public androidx.mediarouter.media.MediaRouteProvider.DynamicGroupRouteController.DynamicRouteDescriptor.Builder setSelectionState(int);
+  }
+
+  public static final class MediaRouteProvider.ProviderMetadata {
+    method public android.content.ComponentName getComponentName();
+    method public String getPackageName();
+  }
+
+  public abstract static class MediaRouteProvider.RouteController {
+    ctor public MediaRouteProvider.RouteController();
+    method public boolean onControlRequest(android.content.Intent, androidx.mediarouter.media.MediaRouter.ControlRequestCallback?);
+    method public void onRelease();
+    method public void onSelect();
+    method public void onSetVolume(int);
+    method @Deprecated public void onUnselect();
+    method public void onUnselect(int);
+    method public void onUpdateVolume(int);
+  }
+
+  public final class MediaRouteProviderDescriptor {
+    method public android.os.Bundle asBundle();
+    method public static androidx.mediarouter.media.MediaRouteProviderDescriptor? fromBundle(android.os.Bundle?);
+    method public java.util.List<androidx.mediarouter.media.MediaRouteDescriptor!> getRoutes();
+    method public boolean isValid();
+    method public boolean supportsDynamicGroupRoute();
+  }
+
+  public static final class MediaRouteProviderDescriptor.Builder {
+    ctor public MediaRouteProviderDescriptor.Builder();
+    ctor public MediaRouteProviderDescriptor.Builder(androidx.mediarouter.media.MediaRouteProviderDescriptor);
+    method public androidx.mediarouter.media.MediaRouteProviderDescriptor.Builder addRoute(androidx.mediarouter.media.MediaRouteDescriptor);
+    method public androidx.mediarouter.media.MediaRouteProviderDescriptor.Builder addRoutes(java.util.Collection<androidx.mediarouter.media.MediaRouteDescriptor!>);
+    method public androidx.mediarouter.media.MediaRouteProviderDescriptor build();
+    method public androidx.mediarouter.media.MediaRouteProviderDescriptor.Builder setSupportsDynamicGroupRoute(boolean);
+  }
+
+  public abstract class MediaRouteProviderService extends android.app.Service {
+    ctor public MediaRouteProviderService();
+    method public androidx.mediarouter.media.MediaRouteProvider? getMediaRouteProvider();
+    method public android.os.IBinder? onBind(android.content.Intent);
+    method public abstract androidx.mediarouter.media.MediaRouteProvider? onCreateMediaRouteProvider();
+    field public static final String SERVICE_INTERFACE = "android.media.MediaRouteProviderService";
+  }
+
+  public final class MediaRouteSelector {
+    method public android.os.Bundle asBundle();
+    method public boolean contains(androidx.mediarouter.media.MediaRouteSelector);
+    method public static androidx.mediarouter.media.MediaRouteSelector? fromBundle(android.os.Bundle?);
+    method public java.util.List<java.lang.String!> getControlCategories();
+    method public boolean hasControlCategory(String?);
+    method public boolean isEmpty();
+    method public boolean isValid();
+    method public boolean matchesControlFilters(java.util.List<android.content.IntentFilter!>?);
+    field public static final androidx.mediarouter.media.MediaRouteSelector! EMPTY;
+  }
+
+  public static final class MediaRouteSelector.Builder {
+    ctor public MediaRouteSelector.Builder();
+    ctor public MediaRouteSelector.Builder(androidx.mediarouter.media.MediaRouteSelector);
+    method public androidx.mediarouter.media.MediaRouteSelector.Builder addControlCategories(java.util.Collection<java.lang.String!>);
+    method public androidx.mediarouter.media.MediaRouteSelector.Builder addControlCategory(String);
+    method public androidx.mediarouter.media.MediaRouteSelector.Builder addSelector(androidx.mediarouter.media.MediaRouteSelector);
+    method public androidx.mediarouter.media.MediaRouteSelector build();
+  }
+
+  public final class MediaRouter {
+    method @MainThread public void addCallback(androidx.mediarouter.media.MediaRouteSelector, androidx.mediarouter.media.MediaRouter.Callback);
+    method @MainThread public void addCallback(androidx.mediarouter.media.MediaRouteSelector, androidx.mediarouter.media.MediaRouter.Callback, int);
+    method @MainThread public void addProvider(androidx.mediarouter.media.MediaRouteProvider);
+    method @Deprecated @MainThread public void addRemoteControlClient(Object);
+    method @MainThread public androidx.mediarouter.media.MediaRouter.RouteInfo? getBluetoothRoute();
+    method @MainThread public androidx.mediarouter.media.MediaRouter.RouteInfo getDefaultRoute();
+    method @MainThread public static androidx.mediarouter.media.MediaRouter getInstance(android.content.Context);
+    method public android.support.v4.media.session.MediaSessionCompat.Token? getMediaSessionToken();
+    method @MainThread public java.util.List<androidx.mediarouter.media.MediaRouter.ProviderInfo!> getProviders();
+    method @MainThread public androidx.mediarouter.media.MediaRouterParams? getRouterParams();
+    method @MainThread public java.util.List<androidx.mediarouter.media.MediaRouter.RouteInfo!> getRoutes();
+    method @MainThread public androidx.mediarouter.media.MediaRouter.RouteInfo getSelectedRoute();
+    method @MainThread public boolean isRouteAvailable(androidx.mediarouter.media.MediaRouteSelector, int);
+    method @MainThread public void removeCallback(androidx.mediarouter.media.MediaRouter.Callback);
+    method @MainThread public void removeProvider(androidx.mediarouter.media.MediaRouteProvider);
+    method @Deprecated @MainThread public void removeRemoteControlClient(Object);
+    method @MainThread public void selectRoute(androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method @MainThread public void setMediaSession(Object?);
+    method @MainThread public void setMediaSessionCompat(android.support.v4.media.session.MediaSessionCompat?);
+    method @MainThread public void setOnPrepareTransferListener(androidx.mediarouter.media.MediaRouter.OnPrepareTransferListener?);
+    method @MainThread public void setRouteListingPreference(androidx.mediarouter.media.RouteListingPreference?);
+    method @MainThread public void setRouterParams(androidx.mediarouter.media.MediaRouterParams?);
+    method @MainThread public void unselect(int);
+    method @MainThread public androidx.mediarouter.media.MediaRouter.RouteInfo updateSelectedRoute(androidx.mediarouter.media.MediaRouteSelector);
+    field public static final int AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE = 1; // 0x1
+    field public static final int AVAILABILITY_FLAG_REQUIRE_MATCH = 2; // 0x2
+    field public static final int CALLBACK_FLAG_FORCE_DISCOVERY = 8; // 0x8
+    field public static final int CALLBACK_FLAG_PERFORM_ACTIVE_SCAN = 1; // 0x1
+    field public static final int CALLBACK_FLAG_REQUEST_DISCOVERY = 4; // 0x4
+    field public static final int CALLBACK_FLAG_UNFILTERED_EVENTS = 2; // 0x2
+    field public static final int UNSELECT_REASON_DISCONNECTED = 1; // 0x1
+    field public static final int UNSELECT_REASON_ROUTE_CHANGED = 3; // 0x3
+    field public static final int UNSELECT_REASON_STOPPED = 2; // 0x2
+    field public static final int UNSELECT_REASON_UNKNOWN = 0; // 0x0
+  }
+
+  public abstract static class MediaRouter.Callback {
+    ctor public MediaRouter.Callback();
+    method public void onProviderAdded(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.ProviderInfo);
+    method public void onProviderChanged(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.ProviderInfo);
+    method public void onProviderRemoved(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.ProviderInfo);
+    method public void onRouteAdded(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void onRouteChanged(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void onRoutePresentationDisplayChanged(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void onRouteRemoved(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method @Deprecated public void onRouteSelected(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void onRouteSelected(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo, int);
+    method public void onRouteSelected(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo, int, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method @Deprecated public void onRouteUnselected(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void onRouteUnselected(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo, int);
+    method public void onRouteVolumeChanged(androidx.mediarouter.media.MediaRouter, androidx.mediarouter.media.MediaRouter.RouteInfo);
+  }
+
+  public abstract static class MediaRouter.ControlRequestCallback {
+    ctor public MediaRouter.ControlRequestCallback();
+    method public void onError(String?, android.os.Bundle?);
+    method public void onResult(android.os.Bundle?);
+  }
+
+  public static interface MediaRouter.OnPrepareTransferListener {
+    method @MainThread public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!>? onPrepareTransfer(androidx.mediarouter.media.MediaRouter.RouteInfo, androidx.mediarouter.media.MediaRouter.RouteInfo);
+  }
+
+  public static final class MediaRouter.ProviderInfo {
+    method public android.content.ComponentName getComponentName();
+    method public String getPackageName();
+    method @MainThread public androidx.mediarouter.media.MediaRouteProvider getProviderInstance();
+    method @MainThread public java.util.List<androidx.mediarouter.media.MediaRouter.RouteInfo!> getRoutes();
+  }
+
+  public static class MediaRouter.RouteInfo {
+    method public boolean canDisconnect();
+    method public int getConnectionState();
+    method public java.util.List<android.content.IntentFilter!> getControlFilters();
+    method public String? getDescription();
+    method public int getDeviceType();
+    method public android.os.Bundle? getExtras();
+    method public android.net.Uri? getIconUri();
+    method public String getId();
+    method public String getName();
+    method public int getPlaybackStream();
+    method public int getPlaybackType();
+    method @MainThread public android.view.Display? getPresentationDisplay();
+    method public androidx.mediarouter.media.MediaRouter.ProviderInfo getProvider();
+    method public android.content.IntentSender? getSettingsIntent();
+    method public int getVolume();
+    method public int getVolumeHandling();
+    method public int getVolumeMax();
+    method @MainThread public boolean isBluetooth();
+    method @Deprecated public boolean isConnecting();
+    method @MainThread public boolean isDefault();
+    method public boolean isDeviceSpeaker();
+    method public boolean isEnabled();
+    method @MainThread public boolean isSelected();
+    method public boolean isSystemRoute();
+    method @MainThread public boolean matchesSelector(androidx.mediarouter.media.MediaRouteSelector);
+    method @MainThread public void requestSetVolume(int);
+    method @MainThread public void requestUpdateVolume(int);
+    method @MainThread public void select();
+    method @MainThread public void sendControlRequest(android.content.Intent, androidx.mediarouter.media.MediaRouter.ControlRequestCallback?);
+    method @MainThread public boolean supportsControlAction(String, String);
+    method @MainThread public boolean supportsControlCategory(String);
+    method @MainThread public boolean supportsControlRequest(android.content.Intent);
+    field public static final int CONNECTION_STATE_CONNECTED = 2; // 0x2
+    field public static final int CONNECTION_STATE_CONNECTING = 1; // 0x1
+    field public static final int CONNECTION_STATE_DISCONNECTED = 0; // 0x0
+    field public static final int DEVICE_TYPE_AUDIO_VIDEO_RECEIVER = 4; // 0x4
+    field public static final int DEVICE_TYPE_BLE_HEADSET = 22; // 0x16
+    field public static final int DEVICE_TYPE_BLUETOOTH_A2DP = 3; // 0x3
+    field public static final int DEVICE_TYPE_BUILTIN_SPEAKER = 12; // 0xc
+    field public static final int DEVICE_TYPE_CAR = 9; // 0x9
+    field public static final int DEVICE_TYPE_COMPUTER = 7; // 0x7
+    field public static final int DEVICE_TYPE_DOCK = 19; // 0x13
+    field public static final int DEVICE_TYPE_GAME_CONSOLE = 8; // 0x8
+    field public static final int DEVICE_TYPE_GROUP = 1000; // 0x3e8
+    field public static final int DEVICE_TYPE_HDMI = 16; // 0x10
+    field public static final int DEVICE_TYPE_HDMI_ARC = 23; // 0x17
+    field public static final int DEVICE_TYPE_HDMI_EARC = 24; // 0x18
+    field public static final int DEVICE_TYPE_HEARING_AID = 21; // 0x15
+    field public static final int DEVICE_TYPE_REMOTE_SPEAKER = 2; // 0x2
+    field public static final int DEVICE_TYPE_SMARTPHONE = 11; // 0xb
+    field public static final int DEVICE_TYPE_SMARTWATCH = 10; // 0xa
+    field @Deprecated public static final int DEVICE_TYPE_SPEAKER = 2; // 0x2
+    field public static final int DEVICE_TYPE_TABLET = 5; // 0x5
+    field public static final int DEVICE_TYPE_TABLET_DOCKED = 6; // 0x6
+    field public static final int DEVICE_TYPE_TV = 1; // 0x1
+    field public static final int DEVICE_TYPE_USB_ACCESSORY = 18; // 0x12
+    field public static final int DEVICE_TYPE_USB_DEVICE = 17; // 0x11
+    field public static final int DEVICE_TYPE_USB_HEADSET = 20; // 0x14
+    field public static final int DEVICE_TYPE_WIRED_HEADPHONES = 14; // 0xe
+    field public static final int DEVICE_TYPE_WIRED_HEADSET = 13; // 0xd
+    field public static final int PLAYBACK_TYPE_LOCAL = 0; // 0x0
+    field public static final int PLAYBACK_TYPE_REMOTE = 1; // 0x1
+    field public static final int PLAYBACK_VOLUME_FIXED = 0; // 0x0
+    field public static final int PLAYBACK_VOLUME_VARIABLE = 1; // 0x1
+  }
+
+  public class MediaRouterParams {
+    method public int getDialogType();
+    method public boolean isMediaTransferReceiverEnabled();
+    method public boolean isOutputSwitcherEnabled();
+    method public boolean isTransferToLocalEnabled();
+    field public static final int DIALOG_TYPE_DEFAULT = 1; // 0x1
+    field public static final int DIALOG_TYPE_DYNAMIC_GROUP = 2; // 0x2
+    field public static final String ENABLE_GROUP_VOLUME_UX = "androidx.mediarouter.media.MediaRouterParams.ENABLE_GROUP_VOLUME_UX";
+  }
+
+  public static final class MediaRouterParams.Builder {
+    ctor public MediaRouterParams.Builder();
+    ctor public MediaRouterParams.Builder(androidx.mediarouter.media.MediaRouterParams);
+    method public androidx.mediarouter.media.MediaRouterParams build();
+    method public androidx.mediarouter.media.MediaRouterParams.Builder setDialogType(int);
+    method public androidx.mediarouter.media.MediaRouterParams.Builder setMediaTransferReceiverEnabled(boolean);
+    method public androidx.mediarouter.media.MediaRouterParams.Builder setOutputSwitcherEnabled(boolean);
+    method public androidx.mediarouter.media.MediaRouterParams.Builder setTransferToLocalEnabled(boolean);
+  }
+
+  public final class MediaSessionStatus {
+    method public android.os.Bundle asBundle();
+    method public static androidx.mediarouter.media.MediaSessionStatus? fromBundle(android.os.Bundle?);
+    method public android.os.Bundle? getExtras();
+    method public int getSessionState();
+    method public long getTimestamp();
+    method public boolean isQueuePaused();
+    field public static final int SESSION_STATE_ACTIVE = 0; // 0x0
+    field public static final int SESSION_STATE_ENDED = 1; // 0x1
+    field public static final int SESSION_STATE_INVALIDATED = 2; // 0x2
+  }
+
+  public static final class MediaSessionStatus.Builder {
+    ctor public MediaSessionStatus.Builder(androidx.mediarouter.media.MediaSessionStatus);
+    ctor public MediaSessionStatus.Builder(int);
+    method public androidx.mediarouter.media.MediaSessionStatus build();
+    method public androidx.mediarouter.media.MediaSessionStatus.Builder setExtras(android.os.Bundle?);
+    method public androidx.mediarouter.media.MediaSessionStatus.Builder setQueuePaused(boolean);
+    method public androidx.mediarouter.media.MediaSessionStatus.Builder setSessionState(int);
+    method public androidx.mediarouter.media.MediaSessionStatus.Builder setTimestamp(long);
+  }
+
+  public final class MediaTransferReceiver extends android.content.BroadcastReceiver {
+    ctor public MediaTransferReceiver();
+    method public void onReceive(android.content.Context, android.content.Intent);
+  }
+
+  public class RemotePlaybackClient {
+    ctor public RemotePlaybackClient(android.content.Context, androidx.mediarouter.media.MediaRouter.RouteInfo);
+    method public void endSession(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+    method public void enqueue(android.net.Uri, String?, android.os.Bundle?, long, android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.ItemActionCallback?);
+    method public String? getSessionId();
+    method public void getSessionStatus(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+    method public void getStatus(String, android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.ItemActionCallback?);
+    method public boolean hasSession();
+    method public boolean isMessagingSupported();
+    method public boolean isQueuingSupported();
+    method public boolean isRemotePlaybackSupported();
+    method public boolean isSessionManagementSupported();
+    method public void pause(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+    method public void play(android.net.Uri, String?, android.os.Bundle?, long, android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.ItemActionCallback?);
+    method public void release();
+    method public void remove(String, android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.ItemActionCallback?);
+    method public void resume(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+    method public void seek(String, long, android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.ItemActionCallback?);
+    method public void sendMessage(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+    method public void setOnMessageReceivedListener(androidx.mediarouter.media.RemotePlaybackClient.OnMessageReceivedListener?);
+    method public void setSessionId(String?);
+    method public void setStatusCallback(androidx.mediarouter.media.RemotePlaybackClient.StatusCallback?);
+    method public void startSession(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+    method public void stop(android.os.Bundle?, androidx.mediarouter.media.RemotePlaybackClient.SessionActionCallback?);
+  }
+
+  public abstract static class RemotePlaybackClient.ActionCallback {
+    ctor public RemotePlaybackClient.ActionCallback();
+    method public void onError(String?, int, android.os.Bundle?);
+  }
+
+  public abstract static class RemotePlaybackClient.ItemActionCallback extends androidx.mediarouter.media.RemotePlaybackClient.ActionCallback {
+    ctor public RemotePlaybackClient.ItemActionCallback();
+    method public void onResult(android.os.Bundle, String, androidx.mediarouter.media.MediaSessionStatus?, String, androidx.mediarouter.media.MediaItemStatus);
+  }
+
+  public static interface RemotePlaybackClient.OnMessageReceivedListener {
+    method public void onMessageReceived(String, android.os.Bundle?);
+  }
+
+  public abstract static class RemotePlaybackClient.SessionActionCallback extends androidx.mediarouter.media.RemotePlaybackClient.ActionCallback {
+    ctor public RemotePlaybackClient.SessionActionCallback();
+    method public void onResult(android.os.Bundle, String, androidx.mediarouter.media.MediaSessionStatus?);
+  }
+
+  public abstract static class RemotePlaybackClient.StatusCallback {
+    ctor public RemotePlaybackClient.StatusCallback();
+    method public void onItemStatusChanged(android.os.Bundle?, String, androidx.mediarouter.media.MediaSessionStatus?, String, androidx.mediarouter.media.MediaItemStatus);
+    method public void onSessionChanged(String?);
+    method public void onSessionStatusChanged(android.os.Bundle?, String, androidx.mediarouter.media.MediaSessionStatus?);
+  }
+
+  public final class RouteListingPreference {
+    method public java.util.List<androidx.mediarouter.media.RouteListingPreference.Item!> getItems();
+    method public android.content.ComponentName? getLinkedItemComponentName();
+    method public boolean isSystemOrderingEnabled();
+    field public static final String ACTION_TRANSFER_MEDIA = "android.media.action.TRANSFER_MEDIA";
+    field public static final String EXTRA_ROUTE_ID = "android.media.extra.ROUTE_ID";
+  }
+
+  public static final class RouteListingPreference.Builder {
+    ctor public RouteListingPreference.Builder();
+    method public androidx.mediarouter.media.RouteListingPreference build();
+    method public androidx.mediarouter.media.RouteListingPreference.Builder setItems(java.util.List<androidx.mediarouter.media.RouteListingPreference.Item!>);
+    method public androidx.mediarouter.media.RouteListingPreference.Builder setLinkedItemComponentName(android.content.ComponentName?);
+    method public androidx.mediarouter.media.RouteListingPreference.Builder setSystemOrderingEnabled(boolean);
+  }
+
+  public static final class RouteListingPreference.Item {
+    method public CharSequence? getCustomSubtextMessage();
+    method public int getFlags();
+    method public String getRouteId();
+    method public int getSelectionBehavior();
+    method public int getSubText();
+    field public static final int FLAG_ONGOING_SESSION = 1; // 0x1
+    field public static final int FLAG_ONGOING_SESSION_MANAGED = 2; // 0x2
+    field public static final int FLAG_SUGGESTED = 4; // 0x4
+    field public static final int SELECTION_BEHAVIOR_GO_TO_APP = 2; // 0x2
+    field public static final int SELECTION_BEHAVIOR_NONE = 0; // 0x0
+    field public static final int SELECTION_BEHAVIOR_TRANSFER = 1; // 0x1
+    field public static final int SUBTEXT_AD_ROUTING_DISALLOWED = 4; // 0x4
+    field public static final int SUBTEXT_CUSTOM = 10000; // 0x2710
+    field public static final int SUBTEXT_DEVICE_LOW_POWER = 5; // 0x5
+    field public static final int SUBTEXT_DOWNLOADED_CONTENT_ROUTING_DISALLOWED = 3; // 0x3
+    field public static final int SUBTEXT_ERROR_UNKNOWN = 1; // 0x1
+    field public static final int SUBTEXT_NONE = 0; // 0x0
+    field public static final int SUBTEXT_SUBSCRIPTION_REQUIRED = 2; // 0x2
+    field public static final int SUBTEXT_TRACK_UNSUPPORTED = 7; // 0x7
+    field public static final int SUBTEXT_UNAUTHORIZED = 6; // 0x6
+  }
+
+  public static final class RouteListingPreference.Item.Builder {
+    ctor public RouteListingPreference.Item.Builder(String);
+    method public androidx.mediarouter.media.RouteListingPreference.Item build();
+    method public androidx.mediarouter.media.RouteListingPreference.Item.Builder setCustomSubtextMessage(CharSequence?);
+    method public androidx.mediarouter.media.RouteListingPreference.Item.Builder setFlags(int);
+    method public androidx.mediarouter.media.RouteListingPreference.Item.Builder setSelectionBehavior(int);
+    method public androidx.mediarouter.media.RouteListingPreference.Item.Builder setSubText(int);
+  }
+
+}
+
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/CallbacksApiGeneratorDiffTest.kt b/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/CallbacksApiGeneratorDiffTest.kt
index 7907500..2398d20 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/CallbacksApiGeneratorDiffTest.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/CallbacksApiGeneratorDiffTest.kt
@@ -27,6 +27,7 @@
         "com/sdkwithcallbacks/ISdkCallback.java",
         "com/sdkwithcallbacks/ISdkService.java",
         "com/sdkwithcallbacks/ParcelableResponse.java",
+        "com/sdkwithcallbacks/ParcelableMyEnum.java",
         "com/sdkwithcallbacks/IMyUiInterface.java",
         "com/sdkwithcallbacks/IMyUiInterfaceCoreLibInfoAndBinderWrapper.java"
     )
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/input/com/sdkwithcallbacks/SdkService.kt b/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/input/com/sdkwithcallbacks/SdkService.kt
index 5c45597..5c2718b 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/input/com/sdkwithcallbacks/SdkService.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/input/com/sdkwithcallbacks/SdkService.kt
@@ -26,7 +26,10 @@
 }
 
 @PrivacySandboxValue
-data class Response(val response: String, val uiInterface: MyUiInterface)
+data class Response(val response: String, val uiInterface: MyUiInterface, val myEnum: MyEnum)
+
+@PrivacySandboxValue
+enum class MyEnum { FLIP, FLOP }
 
 @PrivacySandboxInterface
 interface MyInterface {
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/MyEnum.kt b/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/MyEnum.kt
new file mode 100644
index 0000000..1e0af70
--- /dev/null
+++ b/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/MyEnum.kt
@@ -0,0 +1,6 @@
+package com.sdkwithcallbacks
+
+public enum class MyEnum {
+    FLIP,
+    FLOP,
+}
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/MyEnumConverter.kt b/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/MyEnumConverter.kt
new file mode 100644
index 0000000..9554eaf
--- /dev/null
+++ b/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/MyEnumConverter.kt
@@ -0,0 +1,12 @@
+package com.sdkwithcallbacks
+
+public object MyEnumConverter {
+    public fun fromParcelable(parcelable: ParcelableMyEnum): MyEnum =
+            MyEnum.entries[parcelable.variant_ordinal]
+
+    public fun toParcelable(annotatedValue: MyEnum): ParcelableMyEnum {
+        val parcelable = ParcelableMyEnum()
+        parcelable.variant_ordinal = annotatedValue.ordinal
+        return parcelable
+    }
+}
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/Response.kt b/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/Response.kt
index a449083..752bbeb 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/Response.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/Response.kt
@@ -3,4 +3,5 @@
 public data class Response(
     public val response: String,
     public val uiInterface: MyUiInterface,
+    public val myEnum: MyEnum,
 )
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/ResponseConverter.kt b/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/ResponseConverter.kt
index e5105f8..4a42a82 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/ResponseConverter.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/test-data/callbacks/output/com/sdkwithcallbacks/ResponseConverter.kt
@@ -5,7 +5,8 @@
         val annotatedValue = Response(
                 response = parcelable.response,
                 uiInterface = MyUiInterfaceClientProxy(parcelable.uiInterface.binder,
-                        parcelable.uiInterface.coreLibInfo))
+                        parcelable.uiInterface.coreLibInfo),
+                myEnum = com.sdkwithcallbacks.MyEnumConverter.fromParcelable(parcelable.myEnum))
         return annotatedValue
     }
 
@@ -15,6 +16,7 @@
         parcelable.uiInterface =
                 IMyUiInterfaceCoreLibInfoAndBinderWrapperConverter.toParcelable((annotatedValue.uiInterface
                 as MyUiInterfaceClientProxy).coreLibInfo, annotatedValue.uiInterface.remote)
+        parcelable.myEnum = com.sdkwithcallbacks.MyEnumConverter.toParcelable(annotatedValue.myEnum)
         return parcelable
     }
 }
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java
index 3d98913c..aad4cc0 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/MultiInstanceInvalidationTest.java
@@ -120,6 +120,8 @@
         }
     }
 
+    // TODO(324609478): broken test
+    @Ignore
     @Test
     public void invalidateInAnotherInstance() throws Exception {
         final SampleDatabase db1 = openDatabase(true);
@@ -134,6 +136,8 @@
         assertTrue(changed1.await(3, TimeUnit.SECONDS));
     }
 
+    // TODO(324274513): broken test
+    @Ignore
     @Test
     public void invalidateInAnotherInstanceFts() throws Exception {
         final SampleFtsDatabase db1 = openFtsDatabase(true);
diff --git a/room/room-runtime/build.gradle b/room/room-runtime/build.gradle
index 7972af6..88190e2 100644
--- a/room/room-runtime/build.gradle
+++ b/room/room-runtime/build.gradle
@@ -33,6 +33,7 @@
     id("AndroidXPlugin")
     id("com.android.library")
     id("androidx.stableaidl")
+    id("com.google.devtools.ksp")
 }
 
 def nativeEnabled = KmpPlatformsKt.enableNative(project)
@@ -196,6 +197,11 @@
 dependencies {
     lintChecks(project(":room:room-runtime-lint"))
     sqliteSharedArchive(project(":sqlite:sqlite-bundled"))
+    add("kspAndroidAndroidTest", project(path: ":room:room-compiler", configuration: "shadowAndImplementation"))
+}
+
+ksp {
+    arg("room.generateKotlin", "true")
 }
 
 androidx {
diff --git a/room/room-runtime/src/androidInstrumentedTest/kotlin/androidx/room/MultiInstanceInvalidationTest.kt b/room/room-runtime/src/androidInstrumentedTest/kotlin/androidx/room/MultiInstanceInvalidationTest.kt
new file mode 100644
index 0000000..36c22ac
--- /dev/null
+++ b/room/room-runtime/src/androidInstrumentedTest/kotlin/androidx/room/MultiInstanceInvalidationTest.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room
+
+import android.app.ActivityManager
+import android.content.Context
+import android.os.Build
+import androidx.kruth.assertThat
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.SdkSuppress
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
+import kotlin.test.Test
+import org.junit.Before
+
+class MultiInstanceInvalidationTest {
+    @Entity
+    data class SampleEntity(
+        @PrimaryKey
+        val pk: Int
+    )
+
+    @Database(
+        entities = [SampleEntity::class],
+        version = 1,
+        exportSchema = false
+    )
+    abstract class SampleDatabase : RoomDatabase()
+
+    private lateinit var autoCloseDb: SampleDatabase
+
+    @Suppress("DEPRECATION") // For `getRunningServices()`
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
+    fun invalidateInAnotherInstanceAutoCloser() {
+        val latch = CountDownLatch(1)
+        val context = ApplicationProvider.getApplicationContext<Context>()
+        val manager = context.getSystemService(
+            ActivityManager::class.java
+        )
+        val autoCloseHelper = autoCloseDb.openHelper as AutoClosingRoomOpenHelper
+        val autoCloser = autoCloseHelper.autoCloser
+        autoCloseHelper.writableDatabase
+        // Make sure the service is running.
+        assertThat(manager.getRunningServices(100)).isNotEmpty()
+
+        // Let Room call setAutoCloseCallback
+        val trackerCallback = autoCloser.onAutoCloseCallback
+        autoCloser.setAutoCloseCallback {
+            trackerCallback?.run()
+            // At this point in time InvalidationTracker's callback has run and unbind should have
+            // been invoked.
+            latch.countDown()
+        }
+        latch.await()
+
+        // Make sure the service is no longer running.
+        assertThat(manager.getRunningServices(100)).isEmpty()
+        autoCloseDb.close()
+    }
+
+    @OptIn(ExperimentalRoomApi::class)
+    @Before
+    fun initDb() {
+        val context: Context = ApplicationProvider.getApplicationContext()
+        autoCloseDb = Room.databaseBuilder(
+            context,
+            SampleDatabase::class.java,
+            "MyDb"
+        )
+            .enableMultiInstanceInvalidation()
+            .setAutoCloseTimeout(200, TimeUnit.MILLISECONDS)
+            .build()
+    }
+}
diff --git a/room/room-runtime/src/androidMain/kotlin/androidx/room/InvalidationTracker.android.kt b/room/room-runtime/src/androidMain/kotlin/androidx/room/InvalidationTracker.android.kt
index c1192db..be39682 100644
--- a/room/room-runtime/src/androidMain/kotlin/androidx/room/InvalidationTracker.android.kt
+++ b/room/room-runtime/src/androidMain/kotlin/androidx/room/InvalidationTracker.android.kt
@@ -88,6 +88,9 @@
 
     private val trackerLock = Any()
 
+    /** The initialization state for restarting invalidation after auto-close. */
+    private var multiInstanceClientInitState: MultiInstanceClientInitState? = null
+
     init {
         tableIdLookup = mutableMapOf()
         tablesNames = Array(tableNames.size) { id ->
@@ -161,6 +164,11 @@
                 return
             }
 
+            multiInstanceClientInitState?.let {
+                // Start multi-instance invalidation, based in info from the saved initState.
+                startMultiInstanceInvalidation()
+            }
+
             // These actions are not in a transaction because temp_store is not allowed to be
             // performed on a transaction, and recursive_triggers is not affected by transactions.
             database.execSQL("PRAGMA temp_store = MEMORY;")
@@ -174,27 +182,28 @@
 
     private fun onAutoCloseCallback() {
         synchronized(trackerLock) {
+            val isObserverMapEmpty = observerMap.filterNot { it.key.isRemote }.isEmpty()
+            if (multiInstanceInvalidationClient != null && isObserverMapEmpty) {
+                stopMultiInstanceInvalidation()
+            }
             initialized = false
             observedTableTracker.resetTriggerState()
             cleanupStatement?.close()
         }
     }
 
-    internal fun startMultiInstanceInvalidation(
-        context: Context,
-        name: String,
-        serviceIntent: Intent
-    ) {
+    private fun startMultiInstanceInvalidation() {
+        val state = checkNotNull(multiInstanceClientInitState)
         multiInstanceInvalidationClient = MultiInstanceInvalidationClient(
-            context = context,
-            name = name,
-            serviceIntent = serviceIntent,
+            context = state.context,
+            name = state.name,
+            serviceIntent = state.serviceIntent,
             invalidationTracker = this,
             executor = database.queryExecutor
         )
     }
 
-    internal fun stopMultiInstanceInvalidation() {
+    private fun stopMultiInstanceInvalidation() {
         multiInstanceInvalidationClient?.stop()
         multiInstanceInvalidationClient = null
     }
@@ -582,6 +591,22 @@
         )
     }
 
+    internal fun initMultiInstanceInvalidation(
+        context: Context,
+        name: String,
+        serviceIntent: Intent
+    ) {
+        multiInstanceClientInitState = MultiInstanceClientInitState(
+            context = context,
+            name = name,
+            serviceIntent = serviceIntent
+        )
+    }
+
+    internal fun stop() {
+        stopMultiInstanceInvalidation()
+    }
+
     /**
      * Wraps an observer and keeps the table information.
      *
@@ -844,3 +869,12 @@
         }
     }
 }
+
+/**
+ * Stores needed info to restart the invalidation after it was auto-closed.
+ */
+internal data class MultiInstanceClientInitState(
+    val context: Context,
+    val name: String,
+    val serviceIntent: Intent
+)
diff --git a/room/room-runtime/src/androidMain/kotlin/androidx/room/RoomDatabase.android.kt b/room/room-runtime/src/androidMain/kotlin/androidx/room/RoomDatabase.android.kt
index 6d22589..450ae01 100644
--- a/room/room-runtime/src/androidMain/kotlin/androidx/room/RoomDatabase.android.kt
+++ b/room/room-runtime/src/androidMain/kotlin/androidx/room/RoomDatabase.android.kt
@@ -250,7 +250,7 @@
         // Configure multi-instance invalidation, if enabled
         if (configuration.multiInstanceInvalidationServiceIntent != null) {
             requireNotNull(configuration.name)
-            invalidationTracker.startMultiInstanceInvalidation(
+            invalidationTracker.initMultiInstanceInvalidation(
                 configuration.context,
                 configuration.name,
                 configuration.multiInstanceInvalidationServiceIntent
@@ -517,7 +517,7 @@
             val closeLock: Lock = readWriteLock.writeLock()
             closeLock.lock()
             try {
-                invalidationTracker.stopMultiInstanceInvalidation()
+                invalidationTracker.stop()
                 connectionManager.close()
             } finally {
                 closeLock.unlock()
diff --git a/samples/MediaRoutingDemo/lint-baseline.xml b/samples/MediaRoutingDemo/lint-baseline.xml
index 020dd5f..c274efc 100644
--- a/samples/MediaRoutingDemo/lint-baseline.xml
+++ b/samples/MediaRoutingDemo/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="RestrictedApiAndroidX"
@@ -12,15 +12,6 @@
 
     <issue
         id="RestrictedApiAndroidX"
-        message="RouteInfo.DEVICE_TYPE_BLUETOOTH can only be accessed from within the same library (androidx.mediarouter:mediarouter)"
-        errorLine1="        BLUETOOTH(MediaRouter.RouteInfo.DEVICE_TYPE_BLUETOOTH),"
-        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/com/example/androidx/mediarouting/data/RouteItem.java"/>
-    </issue>
-
-    <issue
-        id="RestrictedApiAndroidX"
         message="RouteInfo.DEVICE_TYPE_UNKNOWN can only be accessed from within the same library (androidx.mediarouter:mediarouter)"
         errorLine1="        UNKNOWN(MediaRouter.RouteInfo.DEVICE_TYPE_UNKNOWN);"
         errorLine2="                                      ~~~~~~~~~~~~~~~~~~~">
diff --git a/settings.gradle b/settings.gradle
index 21bbb5a..7c7abd3 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -509,11 +509,13 @@
 includeProject(":compose:lint:common", [BuildType.COMPOSE])
 includeProject(":compose:lint:common-test", [BuildType.COMPOSE])
 includeProject(":compose:material", [BuildType.COMPOSE])
+includeProject(":compose:material3:adaptive:adaptive", [BuildType.COMPOSE])
+includeProject(":compose:material3:adaptive:adaptive-layout", [BuildType.COMPOSE])
+includeProject(":compose:material3:adaptive:adaptive-navigation", [BuildType.COMPOSE])
+includeProject(":compose:material3:adaptive:adaptive-samples", "compose/material3/adaptive/samples", [BuildType.COMPOSE])
+includeProject(":compose:material3:adaptive:adaptive-benchmark", "compose/material3/adaptive/benchmark", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3", [BuildType.COMPOSE])
 includeProject(":compose:material3:benchmark", [BuildType.COMPOSE])
-includeProject(":compose:material3:material3-adaptive", [BuildType.COMPOSE])
-includeProject(":compose:material3:material3-adaptive:material3-adaptive-samples", "compose/material3/material3-adaptive/samples", [BuildType.COMPOSE])
-includeProject(":compose:material3:material3-adaptive:material3-adaptive-benchmark", "compose/material3/material3-adaptive/benchmark", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3-adaptive-navigation-suite", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3-adaptive-navigation-suite:material3-adaptive-navigation-suite-samples", "compose/material3/material3-adaptive-navigation-suite/samples", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3-common", [BuildType.COMPOSE])
@@ -1111,7 +1113,6 @@
 includeProject(":internal-testutils-macrobenchmark", "testutils/testutils-macrobenchmark", [BuildType.MAIN, BuildType.COMPOSE])
 includeProject(":internal-testutils-navigation", "testutils/testutils-navigation", [BuildType.MAIN, BuildType.COMPOSE, BuildType.FLAN])
 includeProject(":internal-testutils-paging", "testutils/testutils-paging", [BuildType.MAIN, BuildType.COMPOSE])
-includeProject(":internal-testutils-paparazzi", "testutils/testutils-paparazzi", [BuildType.COMPOSE])
 includeProject(":internal-testutils-gradle-plugin", "testutils/testutils-gradle-plugin", [BuildType.MAIN, BuildType.FLAN, BuildType.COMPOSE, BuildType.TOOLS])
 includeProject(":internal-testutils-mockito", "testutils/testutils-mockito", [BuildType.MAIN, BuildType.MEDIA, BuildType.FLAN, BuildType.COMPOSE])
 includeProject(":kruth:kruth", [BuildType.MAIN, BuildType.INFRAROGUE, BuildType.KMP, BuildType.COMPOSE])
@@ -1144,8 +1145,6 @@
 includeProject(":external:libyuv", [BuildType.CAMERA])
 includeProject(":noto-emoji-compat-font", new File(externalRoot, "noto-fonts/emoji-compat"), [BuildType.MAIN])
 includeProject(":noto-emoji-compat-flatbuffers", new File(externalRoot, "noto-fonts/emoji-compat-flatbuffers"), [BuildType.MAIN, BuildType.COMPOSE])
-includeProject(":external:paparazzi:paparazzi", [BuildType.COMPOSE])
-includeProject(":external:paparazzi:paparazzi-agent", [BuildType.COMPOSE])
 
 if (isAllProjects()) {
     includeProject(":docs-tip-of-tree")
diff --git a/stableaidl/stableaidl-gradle-plugin/lint-baseline.xml b/stableaidl/stableaidl-gradle-plugin/lint-baseline.xml
deleted file mode 100644
index aec53bc..0000000
--- a/stableaidl/stableaidl-gradle-plugin/lint-baseline.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
-
-    <issue
-        id="EagerGradleConfiguration"
-        message="Avoid using eager method findByName"
-        errorLine1="    val incoming = project.configurations.findByName(&quot;${variant.name}CompileClasspath&quot;)?.incoming"
-        errorLine2="                                          ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/stableaidl/StableAidlPlugin.kt"/>
-    </issue>
-
-    <issue
-        id="EagerGradleConfiguration"
-        message="Avoid using eager method findByName"
-        errorLine1="    project.configurations.findByName(targetConfig)?.outgoing?.variants { variants ->"
-        errorLine2="                           ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/stableaidl/StableAidlTasks.kt"/>
-    </issue>
-
-</issues>
diff --git a/testutils/testutils-paparazzi/build.gradle b/testutils/testutils-paparazzi/build.gradle
deleted file mode 100644
index 68d62b0..0000000
--- a/testutils/testutils-paparazzi/build.gradle
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * This file was created using the `create_project.py` script located in the
- * `<AndroidX root>/development/project-creator` directory.
- *
- * Please use that script when creating a new project, rather than copying an existing project and
- * modifying its settings.
- */
-import androidx.build.BundleInsideHelper
-import androidx.build.LibraryType
-
-plugins {
-    id("AndroidXPlugin")
-    id("kotlin")
-}
-
-BundleInsideHelper.forInsideJar(
-        project,
-        "com.google.protobuf",
-        // b/268288856 untangle this mess.
-        // Currently this has to match test/screenshot/screenshot/build.gradle because sometimes
-        // both :internal-testutils-paparazzi and :test:screenshot:screenshot are added to the
-        // classpath and picking a different package will cause missing class exceptions due to
-        // class shadowing
-        "androidx.test.screenshot.protobuf",
-        // proto-lite dependency includes .proto files, which are not used and would clash if
-        // users also use proto library directly
-        /* dropResourcesWithSuffix = */ ".proto"
-)
-
-dependencies {
-    api(project(":external:paparazzi:paparazzi"))
-    bundleInside(project(path: ":test:screenshot:screenshot-proto"))
-
-    testImplementation(libs.junit)
-    testImplementation(libs.kotlinTestJunit)
-}
-
-androidx {
-    type = LibraryType.INTERNAL_HOST_TEST_LIBRARY
-}
\ No newline at end of file
diff --git a/testutils/testutils-paparazzi/src/main/kotlin/androidx/testutils/paparazzi/AndroidXPaparazzi.kt b/testutils/testutils-paparazzi/src/main/kotlin/androidx/testutils/paparazzi/AndroidXPaparazzi.kt
deleted file mode 100644
index 510b7f2..0000000
--- a/testutils/testutils-paparazzi/src/main/kotlin/androidx/testutils/paparazzi/AndroidXPaparazzi.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.testutils.paparazzi
-
-import app.cash.paparazzi.DeviceConfig
-import app.cash.paparazzi.Environment
-import app.cash.paparazzi.Paparazzi
-import com.android.ide.common.rendering.api.SessionParams.RenderingMode
-import java.io.File
-
-/**
- * Creates a [Paparazzi] test rule configured from system properties for AndroidX tests with the
- * `AndroidXPaparazziPlugin` Gradle plugin applied.
- *
- * Golden images used with this framework are expected to have a one-to-one relationship to test
- * functions. This helps ensure isolation between test functions and facilitates updating golden
- * images programmatically via the `:updateGolden` Gradle task or CI.
- *
- * To this end, golden images are named by the qualified name of their test function, instead of
- * a secondary identifier. Additionally, the returned [Paparazzi] instance will enforce a limit of
- * one snapshot per test function.
- */
-fun androidxPaparazzi(
-    deviceConfig: DeviceConfig = DeviceConfig.PIXEL_6.copy(softButtons = false),
-    theme: String = "android:Theme.Material.NoActionBar.Fullscreen",
-    renderingMode: RenderingMode = RenderingMode.SHRINK,
-    imageDiffer: ImageDiffer = ImageDiffer.MSSIMMatcher
-) = Paparazzi(
-    deviceConfig = deviceConfig,
-    theme = theme,
-    renderingMode = renderingMode,
-    environment = Environment(
-        platformDir = systemProperty("platformDir"),
-        resDir = systemProperty("resDir"),
-        assetsDir = systemProperty("assetsDir"),
-        compileSdkVersion = systemProperty("compileSdkVersion").toInt(),
-        resourcePackageNames = systemProperty("resourcePackageNames").split(","),
-        appTestDir = System.getProperty("user.dir")!!
-    ),
-    snapshotHandler = GoldenVerifier(
-        modulePath = systemProperty("modulePath"),
-        goldenRootDirectory = File(systemProperty("goldenRootDir")),
-        reportDirectory = File(systemProperty("reportDir")),
-        imageDiffer = imageDiffer
-    )
-)
-
-/** Package name used for resolving system properties */
-internal const val PACKAGE_NAME = "androidx.testutils.paparazzi"
-
-/** Name of the internal Gradle plugin */
-private const val PLUGIN_NAME = "AndroidXPaparazziPlugin"
-
-/** Name of the module containing this library */
-private const val MODULE_NAME = ":internal-testutils-paparazzi"
-
-/** Read a system property with [PACKAGE_NAME] prefix, throwing an exception if missing */
-private fun systemProperty(name: String) = checkNotNull(System.getProperty("$PACKAGE_NAME.$name")) {
-    if (System.getProperty("$PACKAGE_NAME.gradlePluginApplied").toBoolean()) {
-        "Missing required system property: $PACKAGE_NAME.$name. This is likely due to version " +
-            "mismatch between $PLUGIN_NAME and $MODULE_NAME."
-    } else {
-        "Paparazzi system properties not set. Please ensure $PLUGIN_NAME is applied to your build."
-    }
-}
diff --git a/testutils/testutils-paparazzi/src/main/kotlin/androidx/testutils/paparazzi/GoldenVerifier.kt b/testutils/testutils-paparazzi/src/main/kotlin/androidx/testutils/paparazzi/GoldenVerifier.kt
deleted file mode 100644
index 8282bd9d..0000000
--- a/testutils/testutils-paparazzi/src/main/kotlin/androidx/testutils/paparazzi/GoldenVerifier.kt
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.testutils.paparazzi
-
-import androidx.test.screenshot.proto.ScreenshotResultProto.ScreenshotResult
-import androidx.test.screenshot.proto.ScreenshotResultProto.ScreenshotResult.Status
-import app.cash.paparazzi.Snapshot
-import app.cash.paparazzi.SnapshotHandler
-import app.cash.paparazzi.TestName
-import java.awt.image.BufferedImage
-import java.io.File
-import javax.imageio.ImageIO
-
-/**
- * This [SnapshotHandler] implements AndroidX-specific logic for screenshot testing. Specifically,
- * it writes a report to [reportDirectory] at every comparison just before throwing an exception,
- * even on successful comparison. The report contains text and binary protos containing the status
- * of the comparison and relative paths to actual, expected (copy of golden), and difference
- * (magenta highlights) images as applicable. CI consumes these reports to allow updating golden
- * images from the web UI. Golden images can also be updated by the `:updateGolden` Gradle task,
- * which copies actual images to their expected location in the golden repo.
- *
- * It also knows that the AndroidX golden repo, located at [goldenRootDirectory], is partitioned
- * by Gradle project path or [modulePath] and loads images from it.
- *
- * As noted in documentation on [androidxPaparazzi], the verifier is the component to enforce a
- * one-to-one relationship between test functions and golden images. This isn't strictly necessary,
- * but CI currently expects reports to be generated as a side effect of a regular test invocation.
- * Enforcing a one-to-one relationship avoids a situation where a failing assertion earlier in the
- * test would stop a later assertion from executing and generating its report as a side effect,
- * requiring multiple rounds of updating golden images to get the test passing.
- *
- * Additionally, CI currently only supports one comparison per report (note the [ScreenshotResult]
- * proto is not repeated). If this limit is lifted in the future, we would need to devise a scheme
- * for naming additional golden images such as an index of the order they were invoked and wrap the
- * test rule with something like an `ErrorCollector` to ensure later assertions are always
- * reachable.
- *
- * @property modulePath Unique path for the module, derived from Gradle project path. The verifier
- * will search for golden images in this directory relative to [goldenRootDirectory].
- *
- * @property goldenRootDirectory Location on disk of the golden images repo. Golden images for this
- * module are found in the [modulePath] directory under this directory.
- *
- * @property reportDirectory Directory to write reports, including protos, actual and expected
- * images, and image diffs.
- *
- * @property imageDiffer An [ImageDiffer] for comparing images.
- *
- * @property goldenRepoName Name of the repo containing golden images. Used for CI
- */
-internal class GoldenVerifier(
-    val modulePath: String,
-    val goldenRootDirectory: File,
-    val reportDirectory: File,
-    val imageDiffer: ImageDiffer = ImageDiffer.PixelPerfect,
-    val goldenRepoName: String = ANDROIDX_GOLDEN_REPO_NAME
-) : SnapshotHandler {
-    /** Directory containing golden images for this module. */
-    val goldenDirectory = goldenRootDirectory.resolve(modulePath)
-
-    /** The set of tests seen by this verifier, used to enforce single assertion per test. */
-    private val attemptedTests = mutableSetOf<TestName>()
-
-    /**
-     * Asserts that the [actual] matches the expected golden for the test described in [snapshot].
-     * As a side effect, this writes the report proto, actual, expected, and difference images to
-     * [reportDirectory] as appropriate.
-     */
-    fun assertMatchesGolden(snapshot: Snapshot, actual: BufferedImage) {
-        check(snapshot.testName !in attemptedTests) {
-            "Snapshot already taken for test \"${snapshot.testName.methodName}\". Taking " +
-                "multiple snapshots per test is not currently supported."
-        }
-        attemptedTests += snapshot.testName
-
-        val expected = snapshot.toGoldenFile().takeIf { it.canRead() }?.let { ImageIO.read(it) }
-        val analysis = analyze(expected, actual)
-
-        fun updateMessage() = "To update golden images for this test module, run " +
-            "${updateGoldenGradleCommand()}."
-
-        writeReport(snapshot, analysis)
-
-        when (analysis) {
-            is AnalysisResult.Passed -> { /** Test passed, don't need to throw anything */ }
-            is AnalysisResult.Failed -> throw AssertionError(
-                "Actual image differs from golden image: ${analysis.imageDiff.description}. " +
-                    updateMessage()
-            )
-            is AnalysisResult.SizeMismatch -> throw AssertionError(
-                "Actual image has different dimensions than golden image. " +
-                    "Actual: ${analysis.actual.width}x${analysis.actual.height}. " +
-                    "Golden: ${analysis.expected.width}x${analysis.expected.height}. " +
-                    updateMessage()
-            )
-            is AnalysisResult.MissingGolden -> throw AssertionError(
-                "Expected golden image for test \"${snapshot.testName.methodName}\" does not " +
-                    "exist. Run ${updateGoldenGradleCommand()} " +
-                    "to create it and update all golden images for this test module."
-            )
-        }
-    }
-
-    /** Compare [expected] golden image to [actual] image and return an [AnalysisResult] */
-    fun analyze(expected: BufferedImage?, actual: BufferedImage): AnalysisResult {
-        if (expected == null) {
-            return AnalysisResult.MissingGolden(actual)
-        }
-
-        if (actual.width != expected.width || actual.height != expected.height) {
-            return AnalysisResult.SizeMismatch(actual, expected)
-        }
-
-        return when (val diff = imageDiffer.diff(actual, expected)) {
-            is ImageDiffer.DiffResult.Similar -> AnalysisResult.Passed(actual, expected, diff)
-            is ImageDiffer.DiffResult.Different -> AnalysisResult.Failed(actual, expected, diff)
-        }
-    }
-
-    /**
-     * Write the [analysis] for test described by [snapshot] to [reportDirectory] as both binary
-     * and text proto, including actual, expected, and difference image files as appropriate.
-     */
-    fun writeReport(snapshot: Snapshot, analysis: AnalysisResult) {
-        val actualFile = snapshot.toActualFile().also { ImageIO.write(analysis.actual, "PNG", it) }
-        val goldenFile = snapshot.toGoldenFile()
-
-        val resultProto = ScreenshotResult.newBuilder().apply {
-            currentScreenshotFileName = actualFile.toRelativeString(reportDirectory)
-            repoRootPath = goldenRepoName
-            locationOfGoldenInRepo = goldenFile.toRelativeString(goldenRootDirectory)
-        }
-
-        fun diffFile(diff: BufferedImage) = snapshot.toDiffFile()
-            .also { ImageIO.write(diff, "PNG", it) }
-            .toRelativeString(reportDirectory)
-
-        fun expectedFile() = goldenFile.copyTo(snapshot.toExpectedFile())
-            .toRelativeString(reportDirectory)
-
-        when (analysis) {
-            is AnalysisResult.Passed -> resultProto.apply {
-                result = Status.PASSED
-                expectedImageFileName = expectedFile()
-                analysis.imageDiff.highlights?.let { diffImageFileName = diffFile(it) }
-                comparisonStatistics = analysis.imageDiff.taggedDescription()
-            }
-            is AnalysisResult.Failed -> resultProto.apply {
-                result = Status.FAILED
-                expectedImageFileName = expectedFile()
-                diffImageFileName = diffFile(analysis.imageDiff.highlights)
-                comparisonStatistics = analysis.imageDiff.taggedDescription()
-            }
-            is AnalysisResult.SizeMismatch -> resultProto.apply {
-                result = Status.SIZE_MISMATCH
-                expectedImageFileName = expectedFile()
-            }
-            is AnalysisResult.MissingGolden -> resultProto.apply {
-                result = Status.MISSING_GOLDEN
-            }
-        }
-
-        val result = resultProto.build()
-        snapshot.toResultProtoFile().outputStream().use { result.writeTo(it) }
-
-        // TODO(b/244200590): Remove text proto output, or replace with JSON
-        snapshot.toResultTextProtoFile().writeText(result.toString())
-    }
-
-    /**
-     * Analysis result ADT returned from [analyze], including actual and expected images and
-     * an [ImageDiffer.DiffResult].
-     */
-    sealed interface AnalysisResult {
-        val actual: BufferedImage
-
-        data class Passed(
-            override val actual: BufferedImage,
-            val expected: BufferedImage,
-            val imageDiff: ImageDiffer.DiffResult.Similar
-        ) : AnalysisResult
-
-        data class Failed(
-            override val actual: BufferedImage,
-            val expected: BufferedImage,
-            val imageDiff: ImageDiffer.DiffResult.Different
-        ) : AnalysisResult
-
-        data class SizeMismatch(
-            override val actual: BufferedImage,
-            val expected: BufferedImage
-        ) : AnalysisResult
-
-        data class MissingGolden(
-            override val actual: BufferedImage
-        ) : AnalysisResult
-    }
-
-    override fun newFrameHandler(
-        snapshot: Snapshot,
-        frameCount: Int,
-        fps: Int
-    ): SnapshotHandler.FrameHandler {
-        require(frameCount == 1) { "Videos are not yet supported" }
-
-        return object : SnapshotHandler.FrameHandler {
-            override fun handle(image: BufferedImage) {
-                assertMatchesGolden(snapshot, image)
-            }
-
-            override fun close() = Unit
-        }
-    }
-
-    override fun close() = Unit
-
-    /** Adds [ImageDiffer.name] as a prefix to [ImageDiffer.DiffResult.description]. */
-    private fun ImageDiffer.DiffResult.taggedDescription() =
-        "[${imageDiffer.name}]: $description"
-
-    // Filename templates based for a given snapshot
-    private fun Snapshot.toGoldenFile() = goldenDirectory.resolve("${toFileName()}_paparazzi.png")
-    private fun Snapshot.toExpectedFile() = reportDirectory.resolve("${toFileName()}_expected.png")
-    private fun Snapshot.toActualFile() = reportDirectory.resolve("${toFileName()}_actual.png")
-    private fun Snapshot.toDiffFile() = reportDirectory.resolve("${toFileName()}_diff.png")
-    private fun Snapshot.toResultProtoFile() =
-        reportDirectory.resolve("${toFileName()}_goldResult.pb")
-    private fun Snapshot.toResultTextProtoFile() =
-        reportDirectory.resolve("${toFileName()}_goldResult.textproto")
-
-    companion object {
-        /** Name of the AndroidX golden repo. */
-        const val ANDROIDX_GOLDEN_REPO_NAME = "platform/frameworks/support-golden"
-
-        /** Name of the updateGolden Gradle command for this module, via system properties. */
-        fun updateGoldenGradleCommand() =
-            "./gradlew ${
-                (System.getProperty("$PACKAGE_NAME.updateGoldenTask") ?: ":updateGolden")
-            } -Pandroidx.ignoreTestFailures=true"
-
-        /** Render test function name as a fully qualified string. */
-        fun TestName.toQualifiedName(): String {
-            return if (packageName.isEmpty()) {
-                "$className.$methodName"
-            } else {
-                "$packageName.$className.$methodName"
-            }
-        }
-
-        /** Get a file name with special characters removed from a snapshot. */
-        fun Snapshot.toFileName() = testName.toQualifiedName().replace(Regex("\\W+"), "_")
-    }
-}
diff --git a/testutils/testutils-paparazzi/src/main/kotlin/androidx/testutils/paparazzi/ImageDiffer.kt b/testutils/testutils-paparazzi/src/main/kotlin/androidx/testutils/paparazzi/ImageDiffer.kt
deleted file mode 100644
index 8902cb4..0000000
--- a/testutils/testutils-paparazzi/src/main/kotlin/androidx/testutils/paparazzi/ImageDiffer.kt
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.testutils.paparazzi
-
-import androidx.testutils.paparazzi.ImageDiffer.DiffResult.Similar
-import java.awt.image.BufferedImage
-import kotlin.math.pow
-
-@JvmDefaultWithCompatibility
-/**
- *  Functional interface to compare two images and returns a [ImageDiffer.DiffResult] ADT containing
- *  comparison statistics and a difference image, if applicable.
- */
-fun interface ImageDiffer {
-    /**
-     * Compare image [a] to image [b]. Implementations may assume [a] and [b] have the same
-     * dimensions.
-     */
-    fun diff(a: BufferedImage, b: BufferedImage): DiffResult
-
-    /** A name to be used in logs for this differ, defaulting to the class's simple name. */
-    val name
-        get() = requireNotNull(this::class.simpleName) {
-            "Could not determine ImageDiffer.name reflectively. Please override ImageDiffer.name."
-        }
-
-    /**
-     * Result ADT returned from [diff].
-     *
-     * A differ may permit a small amount of difference, even for [Similar] results. Similar results
-     * must include a [description], even if it's trivial, but may omit the [highlights] image if
-     * it would be fully transparent.
-     *
-     * @property description A human-readable description of how the images differed, such as the
-     * count of different pixels or percentage changed. Displayed in test failure messages and in
-     * CI.
-     *
-     * @property highlights An image with a transparent background, highlighting where the compared
-     * images differ, typically in shades of magenta. Displayed in CI.
-     */
-    sealed interface DiffResult {
-        val description: String
-        val highlights: BufferedImage?
-
-        data class Similar(
-            override val description: String,
-            override val highlights: BufferedImage? = null
-        ) : DiffResult
-
-        data class Different(
-            override val description: String,
-            override val highlights: BufferedImage
-        ) : DiffResult
-    }
-
-    /**
-     * Pixel perfect image differ requiring images to be identical.
-     *
-     * The alpha channel is treated as pre-multiplied, meaning RGB channels may differ if the alpha
-     * channel is 0 (fully transparent).
-     */
-    // TODO(b/244752233): Support wide gamut images.
-    object PixelPerfect : ImageDiffer {
-        override fun diff(a: BufferedImage, b: BufferedImage): DiffResult {
-            check(a.width == b.width && a.height == b.height) { "Images are different sizes" }
-            val width = a.width
-            val height = b.height
-            val highlights = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
-            var count = 0
-
-            for (x in 0 until width) {
-                for (y in 0 until height) {
-                    val aPixel = a.getRGB(x, y)
-                    val bPixel = b.getRGB(x, y)
-
-                    // Compare full ARGB pixels, but allow other channels to differ if alpha is 0
-                    if (aPixel == bPixel || (aPixel ushr 24 == 0 && bPixel ushr 24 == 0)) {
-                        highlights.setRGB(x, y, TRANSPARENT.toInt())
-                    } else {
-                        count++
-                        highlights.setRGB(x, y, MAGENTA.toInt())
-                    }
-                }
-            }
-
-            val description = "$count of ${width * height} pixels different"
-            return if (count > 0) {
-                DiffResult.Different(description, highlights)
-            } else {
-                DiffResult.Similar(description)
-            }
-        }
-    }
-
-    /**
-     * Image comparison using Structural Similarity Index, developed by Wang, Bovik, Sheikh, and
-     * Simoncelli. Details can be read in their paper:
-     * https://ece.uwaterloo.ca/~z70wang/publications/ssim.pdf
-     */
-    object MSSIMMatcher : ImageDiffer {
-        override fun diff(a: BufferedImage, b: BufferedImage): DiffResult {
-            val aIntArray = a.toIntArray()
-            val bIntArray = b.toIntArray()
-            val SSIMTotal = calculateSSIM(aIntArray, bIntArray, a.width, a.height)
-
-            val stats = "[MSSIM] Required SSIM: $SSIM_THRESHOLD, Actual " +
-                "SSIM: " + "%.3f".format(SSIMTotal)
-            if (SSIMTotal >= SSIM_THRESHOLD) {
-                return DiffResult.Similar(stats)
-            }
-            return PixelPerfect.diff(a, b)
-        }
-
-        internal fun calculateSSIM(
-            ideal: IntArray,
-            given: IntArray,
-            width: Int,
-            height: Int
-        ): Double {
-            return calculateSSIM(ideal, given, 0, width, width, height)
-        }
-
-        private fun calculateSSIM(
-            ideal: IntArray,
-            given: IntArray,
-            offset: Int,
-            stride: Int,
-            width: Int,
-            height: Int
-        ): Double {
-            var SSIMTotal = 0.0
-            var windows = 0
-            var currentWindowY = 0
-            while (currentWindowY < height) {
-                val windowHeight = computeWindowSize(currentWindowY, height)
-                var currentWindowX = 0
-                while (currentWindowX < width) {
-                    val windowWidth = computeWindowSize(currentWindowX, width)
-                    val start: Int =
-                        indexFromXAndY(currentWindowX, currentWindowY, stride, offset)
-                    if (isWindowWhite(ideal, start, stride, windowWidth, windowHeight) &&
-                        isWindowWhite(given, start, stride, windowWidth, windowHeight)
-                    ) {
-                        currentWindowX += WINDOW_SIZE
-                        continue
-                    }
-                    windows++
-                    val means =
-                        getMeans(ideal, given, start, stride, windowWidth, windowHeight)
-                    val meanX = means[0]
-                    val meanY = means[1]
-                    val variances = getVariances(
-                        ideal, given, meanX, meanY, start, stride,
-                        windowWidth, windowHeight
-                    )
-                    val varX = variances[0]
-                    val varY = variances[1]
-                    val stdBoth = variances[2]
-                    val SSIM = SSIM(meanX, meanY, varX, varY, stdBoth)
-                    SSIMTotal += SSIM
-                    currentWindowX += WINDOW_SIZE
-                }
-                currentWindowY += WINDOW_SIZE
-            }
-            if (windows == 0) {
-                return 1.0
-            }
-            return SSIMTotal / windows.toDouble()
-        }
-
-        /**
-         * Compute the size of the window. The window defaults to WINDOW_SIZE, but
-         * must be contained within dimension.
-         */
-        private fun computeWindowSize(coordinateStart: Int, dimension: Int): Int {
-            return if (coordinateStart + WINDOW_SIZE <= dimension) {
-                WINDOW_SIZE
-            } else {
-                dimension - coordinateStart
-            }
-        }
-
-        private fun isWindowWhite(
-            colors: IntArray,
-            start: Int,
-            stride: Int,
-            windowWidth: Int,
-            windowHeight: Int
-        ): Boolean {
-            for (y in 0 until windowHeight) {
-                for (x in 0 until windowWidth) {
-                    if (colors[indexFromXAndY(x, y, stride, start)] != WHITE) {
-                        return false
-                    }
-                }
-            }
-            return true
-        }
-
-        /**
-         * This calculates the position in an array that would represent a bitmap given the parameters.
-         */
-        private fun indexFromXAndY(x: Int, y: Int, stride: Int, offset: Int): Int {
-            return x + y * stride + offset
-        }
-
-        private fun SSIM(
-            muX: Double,
-            muY: Double,
-            sigX: Double,
-            sigY: Double,
-            sigXY: Double
-        ): Double {
-            var SSIM = (2 * muX * muY + CONSTANT_C1) * (2 * sigXY + CONSTANT_C2)
-            val denom = ((muX * muX + muY * muY + CONSTANT_C1) * (sigX + sigY + CONSTANT_C2))
-            SSIM /= denom
-            return SSIM
-        }
-
-        /**
-         * This method will find the mean of a window in both sets of pixels. The return is an array
-         * where the first double is the mean of the first set and the second double is the mean of the
-         * second set.
-         */
-        private fun getMeans(
-            pixels0: IntArray,
-            pixels1: IntArray,
-            start: Int,
-            stride: Int,
-            windowWidth: Int,
-            windowHeight: Int
-        ): DoubleArray {
-            var avg0 = 0.0
-            var avg1 = 0.0
-            for (y in 0 until windowHeight) {
-                for (x in 0 until windowWidth) {
-                    val index: Int = indexFromXAndY(x, y, stride, start)
-                    avg0 += getIntensity(pixels0[index])
-                    avg1 += getIntensity(pixels1[index])
-                }
-            }
-            avg0 /= windowWidth * windowHeight.toDouble()
-            avg1 /= windowWidth * windowHeight.toDouble()
-            return doubleArrayOf(avg0, avg1)
-        }
-
-        /**
-         * Finds the variance of the two sets of pixels, as well as the covariance of the windows. The
-         * return value is an array of doubles, the first is the variance of the first set of pixels,
-         * the second is the variance of the second set of pixels, and the third is the covariance.
-         */
-        private fun getVariances(
-            pixels0: IntArray,
-            pixels1: IntArray,
-            mean0: Double,
-            mean1: Double,
-            start: Int,
-            stride: Int,
-            windowWidth: Int,
-            windowHeight: Int
-        ): DoubleArray {
-            if (windowHeight == 1 && windowWidth == 1) {
-                // There is only one item. The variance of a single item would be 0.
-                // Since Bessel's correction is used below, it will return NaN instead of 0.
-                return doubleArrayOf(0.0, 0.0, 0.0)
-            }
-
-            var var0 = 0.0
-            var var1 = 0.0
-            var varBoth = 0.0
-            for (y in 0 until windowHeight) {
-                for (x in 0 until windowWidth) {
-                    val index: Int = indexFromXAndY(x, y, stride, start)
-                    val v0 = getIntensity(pixels0[index]) - mean0
-                    val v1 = getIntensity(pixels1[index]) - mean1
-                    var0 += v0 * v0
-                    var1 += v1 * v1
-                    varBoth += v0 * v1
-                }
-            }
-            // Using Bessel's correction. Hence, subtracting one.
-            val denominatorWithBesselsCorrection = windowWidth * windowHeight - 1.0
-            var0 /= denominatorWithBesselsCorrection
-            var1 /= denominatorWithBesselsCorrection
-            varBoth /= denominatorWithBesselsCorrection
-            return doubleArrayOf(var0, var1, varBoth)
-        }
-
-        /**
-         * Gets the intensity of a given pixel in RGB using luminosity formula
-         *
-         * l = 0.21R' + 0.72G' + 0.07B'
-         *
-         * The prime symbols dictate a gamma correction of 1.
-         */
-        private fun getIntensity(pixel: Int): Double {
-            val gamma = 1.0
-            var l = 0.0
-            l += 0.21f * (red(pixel) / 255f.toDouble()).pow(gamma)
-            l += 0.72f * (green(pixel) / 255f.toDouble()).pow(gamma)
-            l += 0.07f * (blue(pixel) / 255f.toDouble()).pow(gamma)
-            return l
-        }
-
-        /**
-         * Return the red component of a color int. This is the same as saying
-         * (color >> 16) & 0xFF
-         */
-        fun red(color: Int): Int {
-            return color shr 16 and 0xFF
-        }
-
-        /**
-         * Return the green component of a color int. This is the same as saying
-         * (color >> 8) & 0xFF
-         */
-        fun green(color: Int): Int {
-            return color shr 8 and 0xFF
-        }
-
-        /**
-         * Return the blue component of a color int. This is the same as saying
-         * color & 0xFF
-         */
-        fun blue(color: Int): Int {
-            return color and 0xFF
-        }
-
-        private fun BufferedImage.toIntArray(): IntArray {
-            val bitmapArray = IntArray(width * height)
-            for (x in 0 until width) {
-                for (y in 0 until height) {
-                    bitmapArray[y * width + x] = getRGB(x, y)
-                }
-            }
-            return bitmapArray
-        }
-    }
-
-    private companion object {
-        const val MAGENTA = 0xFF_FF_00_FFu
-        const val TRANSPARENT = 0x00_FF_FF_FFu
-        const val WHITE = 0xFFFFFF
-
-        // These values were taken from the publication
-        private const val CONSTANT_L = 254.0
-        private const val CONSTANT_K1 = 0.00001
-        private const val CONSTANT_K2 = 0.00003
-        private val CONSTANT_C1 = (CONSTANT_L * CONSTANT_K1).pow(2.0)
-        private val CONSTANT_C2 = (CONSTANT_L * CONSTANT_K2).pow(2.0)
-        private const val WINDOW_SIZE = 10
-
-        private val SSIM_THRESHOLD: Double = 0.98
-    }
-}
diff --git a/testutils/testutils-paparazzi/src/test/kotlin/androidx/testutils/paparazzi/GoldenVerifierTest.kt b/testutils/testutils-paparazzi/src/test/kotlin/androidx/testutils/paparazzi/GoldenVerifierTest.kt
deleted file mode 100644
index aee8a81..0000000
--- a/testutils/testutils-paparazzi/src/test/kotlin/androidx/testutils/paparazzi/GoldenVerifierTest.kt
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.testutils.paparazzi
-
-import androidx.test.screenshot.proto.ScreenshotResultProto.ScreenshotResult
-import androidx.test.screenshot.proto.ScreenshotResultProto.ScreenshotResult.Status
-import app.cash.paparazzi.Snapshot
-import java.awt.image.BufferedImage
-import java.io.File
-import java.util.Date
-import javax.imageio.ImageIO
-import kotlin.test.Test
-import kotlin.test.assertContains
-import kotlin.test.assertEquals
-import kotlin.test.assertFails
-import kotlin.test.assertFailsWith
-import kotlin.test.assertIs
-import org.junit.Rule
-import org.junit.rules.TemporaryFolder
-import org.junit.rules.TestName
-
-class GoldenVerifierTest {
-    @get:Rule
-    val testName = TestName()
-
-    @get:Rule
-    val goldenDirectory = TemporaryFolder()
-
-    @get:Rule
-    val reportDirectory = TemporaryFolder()
-
-    private val modulePath = "testutils/testutils-paparazzi"
-
-    @Test
-    fun `snapshot handler success`() {
-        createGolden("circle")
-        goldenVerifier().newFrameHandler(snapshot(), 1, 0).handle(loadTestImage("circle"))
-    }
-
-    @Test
-    fun `snapshot handler failure`() {
-        createGolden("star")
-        assertFails {
-            goldenVerifier().newFrameHandler(snapshot(), 1, 0).handle(loadTestImage("circle"))
-        }
-    }
-
-    @Test
-    fun `removes special characters in file names`() {
-        createGolden("circle")
-        // Test that createGolden/goldenFile match naming in verifier
-        goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("circle"))
-
-        assertEquals(
-            goldenFile().name,
-            "androidx_testutils_paparazzi_GoldenVerifierTest_" +
-                "removes_special_characters_in_file_names_paparazzi.png"
-        )
-    }
-
-    @Test
-    fun `writes report on success`() {
-        createGolden("circle")
-        goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("circle"))
-
-        val proto = reportProto()
-        assertEquals(Status.PASSED, proto.result)
-        assertEquals(reportFile("expected.png").name, proto.expectedImageFileName)
-        assertEquals("", proto.diffImageFileName)
-        assertEquals("[PixelPerfect]: 0 of 65536 pixels different", proto.comparisonStatistics)
-        assertContains(reportFile("goldResult.textproto").readText(), "PASSED")
-    }
-
-    @Test
-    fun `writes actual image on success`() {
-        createGolden("circle")
-        goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("circle"))
-        assertEquals(loadTestImage("circle"), reportFile("actual.png").readImage())
-    }
-
-    @Test
-    fun `writes expected image on success`() {
-        createGolden("circle")
-        goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("circle"))
-        assertEquals(loadTestImage("circle"), reportFile("expected.png").readImage())
-    }
-
-    @Test
-    fun `analysis of success`() {
-        val analysis = goldenVerifier().analyze(loadTestImage("circle"), loadTestImage("circle"))
-        assertIs<GoldenVerifier.AnalysisResult.Passed>(analysis)
-        assertEquals(loadTestImage("circle"), analysis.actual)
-        assertEquals(loadTestImage("circle"), analysis.expected)
-    }
-
-    @Test
-    fun `asserts on failure`() {
-        createGolden("star")
-        val message = "Actual image differs from golden image: 17837 of 65536 pixels different. " +
-            "To update golden images for this test module, run ./gradlew :updateGolden " +
-            "-Pandroidx.ignoreTestFailures=true."
-
-        assertFailsWithMessage(message) {
-            goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("circle"))
-        }
-    }
-
-    @Test
-    fun `writes result proto on failure`() {
-        createGolden("star")
-        assertFails { goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("circle")) }
-
-        val proto = reportProto()
-        assertEquals(Status.FAILED, proto.result)
-        assertEquals(reportFile("expected.png").name, proto.expectedImageFileName)
-        assertEquals(reportFile("diff.png").name, proto.diffImageFileName)
-        assertEquals("[PixelPerfect]: 17837 of 65536 pixels different", proto.comparisonStatistics)
-        assertContains(reportFile("goldResult.textproto").readText(), "FAILED")
-    }
-
-    @Test
-    fun `writes actual image on failure`() {
-        createGolden("star")
-        assertFails { goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("circle")) }
-        assertEquals(loadTestImage("circle"), reportFile("actual.png").readImage())
-    }
-
-    @Test
-    fun `writes expected image on failure`() {
-        createGolden("star")
-        assertFails { goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("circle")) }
-        assertEquals(loadTestImage("star"), reportFile("expected.png").readImage())
-    }
-
-    @Test
-    fun `writes diff image on failure`() {
-        createGolden("star")
-        assertFails { goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("circle")) }
-        assertEquals(loadTestImage("PixelPerfect_diff"), reportFile("diff.png").readImage())
-    }
-
-    @Test
-    fun `analysis of failure`() {
-        val analysis = goldenVerifier().analyze(loadTestImage("circle"), loadTestImage("star"))
-        assertIs<GoldenVerifier.AnalysisResult.Failed>(analysis)
-        assertEquals(loadTestImage("star"), analysis.actual)
-        assertEquals(loadTestImage("circle"), analysis.expected)
-        assertEquals(loadTestImage("PixelPerfect_diff"), analysis.imageDiff.highlights)
-    }
-
-    @Test
-    fun `asserts on size mismatch`() {
-        createGolden("horizontal_rectangle")
-        val message = "Actual image has different dimensions than golden image. Actual: 72x128. " +
-            "Golden: 128x72. To update golden images for this test module, run ./gradlew " +
-            ":updateGolden -Pandroidx.ignoreTestFailures=true."
-
-        assertFailsWithMessage(message) {
-            goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("vertical_rectangle"))
-        }
-    }
-
-    @Test
-    fun `writes result proto for size mismatch`() {
-        createGolden("horizontal_rectangle")
-        assertFails {
-            goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("vertical_rectangle"))
-        }
-
-        val proto = reportProto()
-        assertEquals(Status.SIZE_MISMATCH, proto.result)
-        assertEquals(reportFile("expected.png").name, proto.expectedImageFileName)
-        assertEquals("", proto.diffImageFileName)
-        assertEquals("", proto.comparisonStatistics)
-        assertContains(reportFile("goldResult.textproto").readText(), "SIZE_MISMATCH")
-    }
-
-    @Test
-    fun `writes actual image for size mismatch`() {
-        createGolden("horizontal_rectangle")
-        assertFails {
-            goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("vertical_rectangle"))
-        }
-
-        assertEquals(loadTestImage("vertical_rectangle"), reportFile("actual.png").readImage())
-    }
-
-    @Test
-    fun `writes expected image for size mismatch`() {
-        createGolden("horizontal_rectangle")
-        assertFails {
-            goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("vertical_rectangle"))
-        }
-
-        assertEquals(loadTestImage("horizontal_rectangle"), reportFile("expected.png").readImage())
-    }
-
-    @Test
-    fun `analysis of size mismatch`() {
-        val analysis = goldenVerifier()
-            .analyze(loadTestImage("horizontal_rectangle"), loadTestImage("vertical_rectangle"))
-        assertIs<GoldenVerifier.AnalysisResult.SizeMismatch>(analysis)
-        assertEquals(loadTestImage("vertical_rectangle"), analysis.actual)
-        assertEquals(loadTestImage("horizontal_rectangle"), analysis.expected)
-    }
-
-    @Test
-    fun `asserts on missing golden`() {
-        val message = "Expected golden image for test \"asserts on missing golden\" does not " +
-            "exist. Run ./gradlew :updateGolden -Pandroidx.ignoreTestFailures=true to create it " +
-            "and update all golden images for this test module."
-
-        assertFailsWithMessage(message) {
-            goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("circle"))
-        }
-    }
-
-    @Test
-    fun `writes result proto for missing golden`() {
-        assertFails { goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("circle")) }
-
-        val proto = reportProto()
-        assertEquals(Status.MISSING_GOLDEN, proto.result)
-        assertEquals("", proto.expectedImageFileName)
-        assertEquals("", proto.diffImageFileName)
-        assertEquals("", proto.comparisonStatistics)
-        assertContains(reportFile("goldResult.textproto").readText(), "MISSING_GOLDEN")
-    }
-
-    @Test
-    fun `writes actual image for missing golden`() {
-        assertFails { goldenVerifier().assertMatchesGolden(snapshot(), loadTestImage("circle")) }
-        assertEquals(loadTestImage("circle"), reportFile("actual.png").readImage())
-    }
-
-    @Test
-    fun `analysis of missing golden`() {
-        val analysis = goldenVerifier().analyze(null, loadTestImage("circle"))
-        assertIs<GoldenVerifier.AnalysisResult.MissingGolden>(analysis)
-        assertEquals(loadTestImage("circle"), analysis.actual)
-    }
-
-    @Test
-    fun `ensures single snapshot per method`() {
-        val verifier = goldenVerifier()
-        createGolden("circle")
-
-        verifier.assertMatchesGolden(snapshot(), loadTestImage("circle"))
-        assertFails { verifier.assertMatchesGolden(snapshot(), loadTestImage("circle")) }
-    }
-
-    private fun goldenVerifier() = GoldenVerifier(
-        modulePath = modulePath,
-        goldenRootDirectory = goldenDirectory.root,
-        reportDirectory = reportDirectory.root
-    )
-
-    /** Assert [block] throws an [AssertionError] with supplied [message]. */
-    private inline fun assertFailsWithMessage(message: String, block: () -> Unit) {
-        assertEquals(message, assertFailsWith<AssertionError> { block() }.message)
-    }
-
-    /** Compare two images using [ImageDiffer.PixelPerfect]. */
-    private fun assertEquals(expected: BufferedImage, actual: BufferedImage) {
-        assertIs<ImageDiffer.DiffResult.Similar>(
-            ImageDiffer.PixelPerfect.diff(expected, actual),
-            message = "Expected images to be identical, but they were not."
-        )
-    }
-
-    private fun snapshot() = Snapshot(
-        name = null,
-        testName = app.cash.paparazzi.TestName(
-            packageName = this::class.java.packageName,
-            className = this::class.simpleName!!,
-            methodName = testName.methodName
-        ),
-        timestamp = Date()
-    )
-
-    /** Create a golden image for this test from the supplied test image [name]. */
-    private fun createGolden(name: String) = javaClass.getResourceAsStream("$name.png")!!
-            .copyTo(goldenFile().apply { parentFile!!.mkdirs() }.outputStream())
-
-    /** Relative path to golden image for this test. */
-    private fun goldenPath() = "$modulePath/${testName()}_paparazzi.png"
-
-    /** Resolve the file path for a golden image for this test under [goldenDirectory]. */
-    private fun goldenFile() = goldenDirectory.root.resolve(goldenPath()).canonicalFile
-
-    /** Read the binary result proto under for this test and check common fields. */
-    private fun reportProto() =
-        ScreenshotResult.parseFrom(reportFile("goldResult.pb").inputStream()).also { proto ->
-            assertEquals(reportFile("actual.png").name, proto.currentScreenshotFileName)
-            assertEquals(GoldenVerifier.ANDROIDX_GOLDEN_REPO_NAME, proto.repoRootPath)
-            assertEquals(goldenPath(), proto.locationOfGoldenInRepo)
-        }
-
-    /** Resolve the file path for a report file with provided [suffix] under [reportDirectory]. */
-    private fun reportFile(suffix: String) =
-        reportDirectory.root.resolve("${testName()}_$suffix").canonicalFile
-
-    /** Convenience function to read an image from a file. */
-    private fun File.readImage() = ImageIO.read(this)
-
-    /** Fully qualified test ID with special characters replaced for this test. */
-    private fun testName() = "${this::class.qualifiedName!!}_${testName.methodName}"
-        .replace(Regex("\\W+"), "_")
-
-    /** Load a test image from resources. */
-    private fun loadTestImage(name: String) =
-        ImageIO.read(javaClass.getResourceAsStream("$name.png")!!)
-}
diff --git a/testutils/testutils-paparazzi/src/test/kotlin/androidx/testutils/paparazzi/ImageDifferTest.kt b/testutils/testutils-paparazzi/src/test/kotlin/androidx/testutils/paparazzi/ImageDifferTest.kt
deleted file mode 100644
index 8b67607..0000000
--- a/testutils/testutils-paparazzi/src/test/kotlin/androidx/testutils/paparazzi/ImageDifferTest.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.testutils.paparazzi
-
-import androidx.testutils.paparazzi.ImageDiffer.DiffResult.Different
-import androidx.testutils.paparazzi.ImageDiffer.DiffResult.Similar
-import androidx.testutils.paparazzi.ImageDiffer.PixelPerfect
-import javax.imageio.ImageIO
-import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.test.assertIs
-import kotlin.test.assertNull
-
-class ImageDifferTest {
-    @Test
-    fun `PixelPerfect similar`() {
-        val result = PixelPerfect.diff(loadTestImage("circle"), loadTestImage("circle"))
-        assertIs<Similar>(result)
-        assertEquals("0 of 65536 pixels different", result.description)
-        assertNull(result.highlights)
-    }
-
-    @Test
-    fun `PixelPerfect different`() {
-        val result = PixelPerfect.diff(loadTestImage("circle"), loadTestImage("star"))
-        assertIs<Different>(result)
-        assertEquals("17837 of 65536 pixels different", result.description)
-        assertIs<Similar>(
-            PixelPerfect.diff(result.highlights, loadTestImage("PixelPerfect_diff"))
-        )
-    }
-
-    @Test
-    fun `PixelPerfect name`() {
-        assertEquals("PixelPerfect", PixelPerfect.name)
-    }
-
-    private fun loadTestImage(name: String) =
-        ImageIO.read(javaClass.getResourceAsStream("$name.png")!!)
-}
diff --git a/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/PixelPerfect_diff.png b/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/PixelPerfect_diff.png
deleted file mode 100644
index 8e3b7b8..0000000
--- a/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/PixelPerfect_diff.png
+++ /dev/null
Binary files differ
diff --git a/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/circle.png b/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/circle.png
deleted file mode 100644
index e6d58321..0000000
--- a/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/circle.png
+++ /dev/null
Binary files differ
diff --git a/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/horizontal_rectangle.png b/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/horizontal_rectangle.png
deleted file mode 100644
index a13221a..0000000
--- a/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/horizontal_rectangle.png
+++ /dev/null
Binary files differ
diff --git a/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/star.png b/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/star.png
deleted file mode 100644
index 61b0c64..0000000
--- a/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/star.png
+++ /dev/null
Binary files differ
diff --git a/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/vertical_rectangle.png b/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/vertical_rectangle.png
deleted file mode 100644
index 91a607e..0000000
--- a/testutils/testutils-paparazzi/src/test/resources/androidx/testutils/paparazzi/vertical_rectangle.png
+++ /dev/null
Binary files differ
diff --git a/testutils/testutils-runtime/src/main/java/androidx/testutils/ActivityTestRule.kt b/testutils/testutils-runtime/src/main/java/androidx/testutils/ActivityTestRule.kt
index afc6573..3f167df 100644
--- a/testutils/testutils-runtime/src/main/java/androidx/testutils/ActivityTestRule.kt
+++ b/testutils/testutils-runtime/src/main/java/androidx/testutils/ActivityTestRule.kt
@@ -18,6 +18,8 @@
 
 import android.app.Activity
 import android.os.Looper
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
 
 /**
  * Wait for execution, by default waiting 2 cycles to ensure that posted transitions are
@@ -38,6 +40,23 @@
     }
 }
 
+/**
+ * Delay execution to future frames. This is important for something like pointer input where there
+ * can be a delayed post to push event to future frame (see AndroidComposeView). We need to be able
+ * to test that without sleeping the thread.
+ */
+@Suppress("DEPRECATION")
+fun androidx.test.rule.ActivityTestRule<out Activity>.waitForFutureFrame(frames: Int = 1) {
+    repeat(frames) {
+        val countDownLatch = CountDownLatch(1)
+        activity.window.decorView.postOnAnimation {
+            countDownLatch.countDown()
+        }
+        countDownLatch.await(1L, TimeUnit.SECONDS)
+        runOnUiThreadRethrow {}
+    }
+}
+
 @Suppress("DEPRECATION")
 fun androidx.test.rule.ActivityTestRule<out Activity>.runOnUiThreadRethrow(block: () -> Unit) {
     if (Looper.getMainLooper() == Looper.myLooper()) {
diff --git a/tv/tv-foundation/src/main/java/androidx/tv/foundation/ScrollableWithPivot.kt b/tv/tv-foundation/src/main/java/androidx/tv/foundation/ScrollableWithPivot.kt
index 1857244..ff46bd7 100644
--- a/tv/tv-foundation/src/main/java/androidx/tv/foundation/ScrollableWithPivot.kt
+++ b/tv/tv-foundation/src/main/java/androidx/tv/foundation/ScrollableWithPivot.kt
@@ -53,6 +53,7 @@
 
 @OptIn(ExperimentalFoundationApi::class)
 @ExperimentalTvFoundationApi
+@Suppress("DEPRECATION")
 fun Modifier.scrollableWithPivot(
     state: ScrollableState,
     orientation: Orientation,
diff --git a/vectordrawable/integration-tests/testapp/lint-baseline.xml b/vectordrawable/integration-tests/testapp/lint-baseline.xml
index b35bd65..3e6d21b 100644
--- a/vectordrawable/integration-tests/testapp/lint-baseline.xml
+++ b/vectordrawable/integration-tests/testapp/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="NewApi"
@@ -121,8 +121,8 @@
     <issue
         id="InvalidVectorPath"
         message="Use -0.001 instead of -.001 to avoid crashes on some devices"
-        errorLine1="                M 3.65, 6.125"
-        errorLine2="          ~~~~~">
+        errorLine1="                m-.001, 0"
+        errorLine2="                 ~~~~~">
         <location
             file="src/main/res/drawable/vector_drawable04.xml"/>
     </issue>
@@ -130,8 +130,8 @@
     <issue
         id="InvalidVectorPath"
         message="Use 0.001 instead of .001 to avoid crashes on some devices"
-        errorLine1="                m-.001, 0"
-        errorLine2="       ~~~~">
+        errorLine1="                a .001,.001 0 1,0 .002,0"
+        errorLine2="                  ~~~~">
         <location
             file="src/main/res/drawable/vector_drawable04.xml"/>
     </issue>
@@ -139,8 +139,8 @@
     <issue
         id="InvalidVectorPath"
         message="Use 0.001 instead of .001 to avoid crashes on some devices"
-        errorLine1="                m-.001, 0"
-        errorLine2="            ~~~~">
+        errorLine1="                a .001,.001 0 1,0 .002,0"
+        errorLine2="                       ~~~~">
         <location
             file="src/main/res/drawable/vector_drawable04.xml"/>
     </issue>
@@ -148,8 +148,8 @@
     <issue
         id="InvalidVectorPath"
         message="Use 0.002 instead of .002 to avoid crashes on some devices"
-        errorLine1="                m-.001, 0"
-        errorLine2="                       ^">
+        errorLine1="                a .001,.001 0 1,0 .002,0"
+        errorLine2="                                  ~~~~">
         <location
             file="src/main/res/drawable/vector_drawable04.xml"/>
     </issue>
@@ -157,8 +157,8 @@
     <issue
         id="InvalidVectorPath"
         message="Use -0.002 instead of -.002 to avoid crashes on some devices"
-        errorLine1="                a .001,.001 0 1,0 .002,0"
-        errorLine2="                                     ^">
+        errorLine1="                a .001,.001 0 1,0-.002,0z&quot; />"
+        errorLine2="                                 ~~~~~">
         <location
             file="src/main/res/drawable/vector_drawable04.xml"/>
     </issue>
@@ -166,8 +166,8 @@
     <issue
         id="InvalidVectorPath"
         message="Use 0.001 instead of .001 to avoid crashes on some devices"
-        errorLine1="                a .001,.001 0 1,0 .002,0"
-        errorLine2="                      ~~~~">
+        errorLine1="                a .001,.001 0 1,0-.002,0z&quot; />"
+        errorLine2="                  ~~~~">
         <location
             file="src/main/res/drawable/vector_drawable04.xml"/>
     </issue>
@@ -175,8 +175,8 @@
     <issue
         id="InvalidVectorPath"
         message="Use 0.001 instead of .001 to avoid crashes on some devices"
-        errorLine1="                a .001,.001 0 1,0 .002,0"
-        errorLine2="                           ~~~~">
+        errorLine1="                a .001,.001 0 1,0-.002,0z&quot; />"
+        errorLine2="                       ~~~~">
         <location
             file="src/main/res/drawable/vector_drawable04.xml"/>
     </issue>
diff --git a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Placeholder.kt b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Placeholder.kt
index 4cb7df0..81cba40 100644
--- a/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Placeholder.kt
+++ b/wear/compose/compose-material/src/main/java/androidx/wear/compose/material/Placeholder.kt
@@ -394,7 +394,7 @@
  * @param shape the shape to apply to the placeholder
  * @param color the color of the placeholder.
  */
-@Suppress("ComposableModifierFactory")
+@Suppress("ComposableModifierFactory", "DEPRECATION")
 @ExperimentalWearMaterialApi
 @Composable
 public fun Modifier.placeholder(
@@ -445,7 +445,7 @@
  * @param color the color to use in the shimmer.
  */
 
-@Suppress("ComposableModifierFactory")
+@Suppress("ComposableModifierFactory", "DEPRECATION")
 @ExperimentalWearMaterialApi
 @OptIn(ExperimentalWearFoundationApi::class)
 @Composable
diff --git a/wear/compose/integration-tests/demos/build.gradle b/wear/compose/integration-tests/demos/build.gradle
index c2f20c3..912149c 100644
--- a/wear/compose/integration-tests/demos/build.gradle
+++ b/wear/compose/integration-tests/demos/build.gradle
@@ -68,6 +68,7 @@
     androidTestImplementation(project(":activity:activity"))
     androidTestImplementation(project(":activity:activity-compose"))
     androidTestImplementation(project(":activity:activity-ktx"))
+    androidTestImplementation(project(":compose:runtime:runtime"))
     androidTestImplementation(project(":compose:ui:ui-test-junit4"))
     androidTestImplementation("androidx.lifecycle:lifecycle-runtime:2.7.0")
     androidTestImplementation("androidx.lifecycle:lifecycle-common:2.7.0")
diff --git a/wear/watchface/watchface-style/lint-baseline.xml b/wear/watchface/watchface-style/lint-baseline.xml
deleted file mode 100644
index 4e453d5..0000000
--- a/wear/watchface/watchface-style/lint-baseline.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.2.0-alpha14" type="baseline" client="cli" dependencies="false" name="AGP (8.2.0-alpha14)" variant="all" version="8.2.0-alpha14">
-
-    <issue
-        id="NewApi"
-        message="Class requires API level 33 (current min is 26): `LargeCustomValueUserStyleSetting`"
-        errorLine1="                is UserStyleSetting.LargeCustomValueUserStyleSetting ->"
-        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/wear/watchface/style/CurrentUserStyleRepository.kt"/>
-    </issue>
-
-</issues>
diff --git a/work/work-runtime/lint-baseline.xml b/work/work-runtime/lint-baseline.xml
index e57c7ec..d7d9e69 100644
--- a/work/work-runtime/lint-baseline.xml
+++ b/work/work-runtime/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.3.0-beta01" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.0-beta01)" variant="all" version="8.3.0-beta01">
+<issues format="6" by="lint 8.4.0-alpha07" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha07)" variant="all" version="8.4.0-alpha07">
 
     <issue
         id="BanSynchronizedMethods"
@@ -13,42 +13,6 @@
     <issue
         id="BanThreadSleep"
         message="Uses Thread.sleep()"
-        errorLine1="        Thread.sleep(TEST_TIMEOUT_IN_MS);"
-        errorLine2="               ~~~~~">
-        <location
-            file="src/androidTest/java/androidx/work/impl/workers/ConstraintTrackingWorkerTest.java"/>
-    </issue>
-
-    <issue
-        id="BanThreadSleep"
-        message="Uses Thread.sleep()"
-        errorLine1="        Thread.sleep(TEST_TIMEOUT_IN_MS);"
-        errorLine2="               ~~~~~">
-        <location
-            file="src/androidTest/java/androidx/work/impl/workers/ConstraintTrackingWorkerTest.java"/>
-    </issue>
-
-    <issue
-        id="BanThreadSleep"
-        message="Uses Thread.sleep()"
-        errorLine1="        Thread.sleep(TEST_TIMEOUT_IN_MS);"
-        errorLine2="               ~~~~~">
-        <location
-            file="src/androidTest/java/androidx/work/impl/workers/ConstraintTrackingWorkerTest.java"/>
-    </issue>
-
-    <issue
-        id="BanThreadSleep"
-        message="Uses Thread.sleep()"
-        errorLine1="        Thread.sleep(TEST_TIMEOUT_IN_MS);"
-        errorLine2="               ~~~~~">
-        <location
-            file="src/androidTest/java/androidx/work/impl/workers/ConstraintTrackingWorkerTest.java"/>
-    </issue>
-
-    <issue
-        id="BanThreadSleep"
-        message="Uses Thread.sleep()"
         errorLine1="            Thread.sleep(duration);"
         errorLine2="                   ~~~~~">
         <location