Merge "Introduce slots reuse logic in SubcomposeLayout" into androidx-main
diff --git a/activity/integration-tests/testapp/lint-baseline.xml b/activity/integration-tests/testapp/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/activity/integration-tests/testapp/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/ads/ads-identifier-benchmark/lint-baseline.xml b/ads/ads-identifier-benchmark/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/ads/ads-identifier-benchmark/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/ads/ads-identifier-provider/lint-baseline.xml b/ads/ads-identifier-provider/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/ads/ads-identifier-provider/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/ads/ads-identifier-testing/lint-baseline.xml b/ads/ads-identifier-testing/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/ads/ads-identifier-testing/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/ads/ads-identifier/lint-baseline.xml b/ads/ads-identifier/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/ads/ads-identifier/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/appcompat/appcompat-benchmark/lint-baseline.xml b/appcompat/appcompat-benchmark/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/appcompat/appcompat-benchmark/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/appcompat/appcompat-lint/lint-baseline.xml b/appcompat/appcompat-lint/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/appcompat/appcompat-lint/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/appcompat/integration-tests/receive-content-testapp/lint-baseline.xml b/appcompat/integration-tests/receive-content-testapp/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/appcompat/integration-tests/receive-content-testapp/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/appsearch/appsearch/lint-baseline.xml b/appsearch/appsearch/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/appsearch/appsearch/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/cts/GenericDocumentCtsTest.java b/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/cts/GenericDocumentCtsTest.java
index 164adad..4fa033a 100644
--- a/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/cts/GenericDocumentCtsTest.java
+++ b/appsearch/appsearch/src/androidTest/java/androidx/appsearch/app/cts/GenericDocumentCtsTest.java
@@ -22,6 +22,7 @@
 
 import androidx.appsearch.app.GenericDocument;
 
+import org.junit.Ignore;
 import org.junit.Test;
 
 public class GenericDocumentCtsTest {
@@ -174,6 +175,7 @@
                 .containsExactly(sDocumentProperties1, sDocumentProperties2);
     }
 
+    @Ignore
     @Test
     public void testDocument_toString() {
         GenericDocument document = new GenericDocument.Builder<>("uri1", "schemaType1")
diff --git a/appsearch/local-storage/lint-baseline.xml b/appsearch/local-storage/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/appsearch/local-storage/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/asynclayoutinflater/asynclayoutinflater/lint-baseline.xml b/asynclayoutinflater/asynclayoutinflater/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/asynclayoutinflater/asynclayoutinflater/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/benchmark/gradle-plugin/lint-baseline.xml b/benchmark/gradle-plugin/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/benchmark/gradle-plugin/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/benchmark/integration-tests/crystalball-experiment/lint-baseline.xml b/benchmark/integration-tests/crystalball-experiment/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/benchmark/integration-tests/crystalball-experiment/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/benchmark/integration-tests/dry-run-benchmark/lint-baseline.xml b/benchmark/integration-tests/dry-run-benchmark/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/benchmark/integration-tests/dry-run-benchmark/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/benchmark/integration-tests/startup-benchmark/lint-baseline.xml b/benchmark/integration-tests/startup-benchmark/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/benchmark/integration-tests/startup-benchmark/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/biometric/biometric-ktx/lint-baseline.xml b/biometric/biometric-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/biometric/biometric-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/biometric/biometric/lint-baseline.xml b/biometric/biometric/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/biometric/biometric/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/biometric/integration-tests/testapp/lint-baseline.xml b/biometric/integration-tests/testapp/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/biometric/integration-tests/testapp/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/buildSrc-tests/lint-baseline.xml b/buildSrc-tests/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/buildSrc-tests/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
index 9c8874d..b238e0c 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -52,7 +52,7 @@
     val CORE_ANIMATION = Version("1.0.0-alpha03")
     val CORE_ANIMATION_TESTING = Version("1.0.0-alpha03")
     val CORE_APPDIGEST = Version("1.0.0-alpha01")
-    val CORE_GOOGLE_SHORTCUTS = Version("1.0.0-alpha04")
+    val CORE_GOOGLE_SHORTCUTS = Version("1.0.0-beta01")
     val CORE_ROLE = Version("1.1.0-alpha02")
     val CURSORADAPTER = Version("1.1.0-alpha01")
     val CUSTOMVIEW = Version("1.2.0-alpha01")
diff --git a/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt b/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
index bf9cff9..08e2e98 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LintConfiguration.kt
@@ -195,22 +195,41 @@
             // be able to burn down existing violations. That's hard to enforce, though, so we'll
             // generally allow teams to update their baseline files with a publicly-known flag.
             if (updateLintBaseline) {
-                // Continue generating baselines regardless of errors
+                // Continue generating baselines regardless of errors.
                 isAbortOnError = false
-                // Avoid printing every single lint error to the terminal
+                // Avoid printing every single lint error to the terminal.
                 textReport = false
-                val lintDebugTask = tasks.named("lintDebug")
-                lintDebugTask.configure {
-                    it.doFirst {
-                        lintBaseline.delete()
+
+                listOf(
+                    tasks.named("lintDebug"),
+                    tasks.named("lint"),
+                ).forEach { task ->
+                    task.configure {
+                        // Delete any existing baseline so that we clear old obsolete entries.
+                        it.doFirst {
+                            lintBaseline.delete()
+                        }
+
+                        // Delete empty generated baselines because they are annoying.
+                        it.doLast {
+                            if (lintBaseline.exists()) {
+                                val hasAnyIssues = lintBaseline.reader().useLines { lines ->
+                                    lines.any { line ->
+                                        line.endsWith("<issue")
+                                    }
+                                }
+                                if (!hasAnyIssues) {
+                                    // Using println is consistent with lint's own output.
+                                    println(
+                                        "Removed empty baseline file ${lintBaseline.absolutePath}"
+                                    )
+                                    lintBaseline.delete()
+                                }
+                            }
+                        }
                     }
                 }
-                val lintTask = tasks.named("lint")
-                lintTask.configure {
-                    it.doFirst {
-                        lintBaseline.delete()
-                    }
-                }
+
                 // Continue running after errors or after creating a new, blank baseline file.
                 System.setProperty(LINT_BASELINE_CONTINUE, "true")
             }
diff --git a/camera/camera-camera2-pipe-integration/lint-baseline.xml b/camera/camera-camera2-pipe-integration/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/camera/camera-camera2-pipe-integration/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/camera/camera-camera2-pipe-testing/lint-baseline.xml b/camera/camera-camera2-pipe-testing/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/camera/camera-camera2-pipe-testing/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/camera/camera-lifecycle/lint-baseline.xml b/camera/camera-lifecycle/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/camera/camera-lifecycle/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/car/app/app-activity/lint-baseline.xml b/car/app/app-activity/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/car/app/app-activity/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/car/app/app-samples/helloworld/automotive/lint-baseline.xml b/car/app/app-samples/helloworld/automotive/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/car/app/app-samples/helloworld/automotive/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/car/app/app-samples/helloworld/mobile/lint-baseline.xml b/car/app/app-samples/helloworld/mobile/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/car/app/app-samples/helloworld/mobile/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/car/app/app-samples/places/common/lint-baseline.xml b/car/app/app-samples/places/common/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/car/app/app-samples/places/common/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/car/app/app-testing/lint-baseline.xml b/car/app/app-testing/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/car/app/app-testing/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/cardview/cardview/lint-baseline.xml b/cardview/cardview/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/cardview/cardview/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/collection/collection-benchmark/lint-baseline.xml b/collection/collection-benchmark/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/collection/collection-benchmark/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/collection/collection-ktx/lint-baseline.xml b/collection/collection-ktx/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/collection/collection-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/collection/integration-tests/testapp/lint-baseline.xml b/collection/integration-tests/testapp/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/collection/integration-tests/testapp/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/AbstractIrTransformTest.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/AbstractIrTransformTest.kt
index a7e6062..5f0aad8 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/AbstractIrTransformTest.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/AbstractIrTransformTest.kt
@@ -206,6 +206,11 @@
                     "${it.groupValues[1]}<>"
                 }
             }
+            .replace(
+                Regex("(sourceInformationMarkerStart\\(%composer, )([-\\d]+)")
+            ) {
+                "${it.groupValues[1]}<>"
+            }
             // replace source information with source it references
             .replace(
                 Regex(
@@ -214,10 +219,15 @@
                 )
             ) {
                 "${it.groupValues[1]}\"${
-                generateSourceInfo(it.groupValues[3], source)
+                generateSourceInfo(it.groupValues[4], source)
                 }\")"
             }
             .replace(
+                Regex("(sourceInformation(MarkerStart)?\\(.*)\"(.*)\"\\)")
+            ) {
+                "${it.groupValues[1]}\"${generateSourceInfo(it.groupValues[3], source)}\")"
+            }
+            .replace(
                 Regex(
                     "(composableLambda[N]?\\" +
                         "([^\"\\n]*)\"(.*)\"\\)"
@@ -235,16 +245,15 @@
             ) {
                 "${it.groupValues[1]}<>"
             }
-            // composableLambdaInstance(<>, true, )
+            // composableLambdaInstance(<>, true)
             .replace(
                 Regex(
-                    "(composableLambdaInstance\\()([-\\d]+, (true|false), (null|\"(.*)\")\\))"
+                    "(composableLambdaInstance\\()([-\\d]+, (true|false))"
                 )
             ) {
                 val callStart = it.groupValues[1]
                 val tracked = it.groupValues[3]
-                val sourceInfo = it.groupValues[5]
-                "$callStart<>, $tracked, \"${generateSourceInfo(sourceInfo, source)}\")"
+                "$callStart<>, $tracked"
             }
             // composableLambda(%composer, <>, true)
             .replace(
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ClassStabilityTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ClassStabilityTransformTests.kt
index 0c6ce92..9cddb39 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ClassStabilityTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ClassStabilityTransformTests.kt
@@ -543,7 +543,8 @@
         """
             @Composable
             fun A(y: Any?, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A)<A()>,<A(Empt...>,<A(Sing...>,<A(Sing...>,<A(Sing...>,<A(Sing...>,<A(Sing...>,<A(Sing...>,<A(Doub...>,<A(Doub...>,<A(Doub...>,<A(Doub...>,<A(X(li...>,<A(X(li...>,<A(NonB...>,<A(NonB...>,<A(Stab...>,<A(Unst...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A)<A()>,<A(Empt...>,<A(Sing...>,<A(Sing...>,<A(Sing...>,<A(Sing...>,<A(Sing...>,<A(Sing...>,<A(Doub...>,<A(Doub...>,<A(Doub...>,<A(Doub...>,<A(X(li...>,<A(X(li...>,<A(NonB...>,<A(NonB...>,<A(Stab...>,<A(Unst...>:Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0010
@@ -674,7 +675,8 @@
             }
             @Composable
             fun A(y: Any, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A)<A(X(li...>,<A(Stab...>,<A(Unst...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A)<A(X(li...>,<A(Stab...>,<A(Unst...>:Test.kt")
               used(y)
               A(X(listOf(StableClass())), %composer, 0b1000)
               A(StableDelegateProp(), %composer, 0)
@@ -708,7 +710,8 @@
         """
             @Composable
             fun A(y: Any, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A)<A(Wrap...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A)<A(Wrap...>:Test.kt")
               used(y)
               A(Wrapper(Foo()), %composer, Wrapper.%stable)
               %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
@@ -746,7 +749,8 @@
         """
             @Composable
             fun <V> B(value: V, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(B)<A(Wrap...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(B)<A(Wrap...>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(value)) 0b0100 else 0b0010
@@ -762,7 +766,8 @@
             }
             @Composable
             fun <T> X(items: List<T>, itemContent: Function3<T, Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(X)P(1)*<itemCo...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(X)P(1)*<itemCo...>:Test.kt")
               val %dirty = %changed
               val tmp0_iterator = items.iterator()
               while (tmp0_iterator.hasNext()) {
@@ -775,14 +780,16 @@
             }
             @Composable
             fun C(items: List<String>, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(C)<X(item...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(C)<X(item...>:Test.kt")
               X(items, ComposableSingletons%TestKt.lambda-1, %composer, 0b1000)
               %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
                 C(items, %composer, %changed or 0b0001)
               }
             }
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function3<String, Composer, Int, Unit> = composableLambdaInstance(<>, false, "C<A(item...>,<A(Wrap...>:Test.kt") { item: String, %composer: Composer?, %changed: Int ->
+              val lambda-1: Function3<String, Composer, Int, Unit> = composableLambdaInstance(<>, false) { item: String, %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C<A(item...>,<A(Wrap...>:Test.kt")
                 val %dirty = %changed
                 if (%changed and 0b1110 === 0) {
                   %dirty = %dirty or if (%composer.changed(item)) 0b0100 else 0b0010
@@ -837,7 +844,8 @@
             }
             @Composable
             fun A(y: Int, x: Any, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A)P(1)<B(x)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A)P(1)<B(x)>:Test.kt")
               used(y)
               B(x, %composer, 0b1000)
               %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
@@ -846,7 +854,8 @@
             }
             @Composable
             fun B(x: Any, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(B):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(B):Test.kt")
               used(x)
               %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
                 B(x, %composer, %changed or 0b0001)
@@ -876,7 +885,8 @@
             }
             @Composable
             fun A(y: Int, x: Foo, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A)P(1)<B(x)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A)P(1)<B(x)>:Test.kt")
               used(y)
               B(x, %composer, 0b1000)
               %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
@@ -885,7 +895,8 @@
             }
             @Composable
             fun B(x: Any, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(B):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(B):Test.kt")
               used(x)
               %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
                 B(x, %composer, %changed or 0b0001)
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ComposerParamTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ComposerParamTransformTests.kt
index 26c88f32..ae972e1 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ComposerParamTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ComposerParamTransformTests.kt
@@ -67,7 +67,8 @@
             val bar: Int
               @Composable @JvmName(name = "getBar")
               get() {
-                %composer.startReplaceableGroup(<>, "C:Test.kt#2487m")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "C:Test.kt#2487m")
                 val tmp0 = 123
                 %composer.endReplaceableGroup()
                 return tmp0
@@ -75,7 +76,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<bar>:Test.kt#2487m")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<bar>:Test.kt#2487m")
               bar
               %composer.endReplaceableGroup()
             }
@@ -110,7 +112,8 @@
               @NonRestartableComposable
               @Composable
               override fun bar(%composer: Composer?, %changed: Int) {
-                %composer.startReplaceableGroup(<>, "C(bar):Test.kt#2487m")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "C(bar):Test.kt#2487m")
                 %composer.endReplaceableGroup()
               }
               static val %stable: Int = 0
@@ -143,18 +146,21 @@
             @NonRestartableComposable
             @Composable
             fun Wat(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Wat):Test.kt#2487m")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Wat):Test.kt#2487m")
               %composer.endReplaceableGroup()
             }
             @NonRestartableComposable
             @Composable
             fun Foo(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Foo)<Wat()>,<goo()>,<baz()>:Test.kt#2487m")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Foo)<Wat()>,<goo()>,<baz()>:Test.kt#2487m")
               Wat(%composer, 0)
               @NonRestartableComposable
               @Composable
               fun goo(%composer: Composer?, %changed: Int) {
-                %composer.startReplaceableGroup(<>, "C(goo)<Wat()>:Test.kt#2487m")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "C(goo)<Wat()>:Test.kt#2487m")
                 Wat(%composer, 0)
                 %composer.endReplaceableGroup()
               }
@@ -162,7 +168,8 @@
                 @NonRestartableComposable
                 @Composable
                 fun baz(%composer: Composer?, %changed: Int) {
-                  %composer.startReplaceableGroup(<>, "C(baz)<Wat()>:Test.kt#2487m")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "C(baz)<Wat()>:Test.kt#2487m")
                   Wat(%composer, 0)
                   %composer.endReplaceableGroup()
                 }
@@ -245,7 +252,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<Exampl...>:Test.kt#2487m")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<Exampl...>:Test.kt#2487m")
               Example(%composer, 0)
               %composer.endReplaceableGroup()
             }
@@ -267,16 +275,19 @@
         """
             @Composable
             fun Example(content: Function2<Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<conten...>:Test.kt#2487m")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<conten...>:Test.kt#2487m")
               content(%composer, 0b1110 and %changed)
               %composer.endReplaceableGroup()
             }
             @NonRestartableComposable
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Test)<Exampl...>:Test.kt#2487m")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Test)<Exampl...>:Test.kt#2487m")
               Example({ %composer: Composer?, %changed: Int ->
-                %composer.startReplaceableGroup(<>, "C:Test.kt#2487m")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "C:Test.kt#2487m")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   Unit
                 } else {
@@ -300,7 +311,8 @@
             val myProperty: Function0<Unit>
               @Composable @JvmName(name = "getMyProperty")
               get() {
-                %composer.startReplaceableGroup(<>, "C:Test.kt#2487m")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "C:Test.kt#2487m")
                 val tmp0 = {
                 }
                 %composer.endReplaceableGroup()
@@ -369,7 +381,8 @@
             """
                 @Composable
                 fun Wrapper(block: Function2<Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
-                  %composer = %composer.startRestartGroup(<>, "C(Wrapper)<block(...>:Test.kt#2487m")
+                  %composer = %composer.startRestartGroup(<>)
+                  sourceInformation(%composer, "C(Wrapper)<block(...>:Test.kt#2487m")
                   val %dirty = %changed
                   if (%changed and 0b1110 === 0) {
                     %dirty = %dirty or if (%composer.changed(block)) 0b0100 else 0b0010
@@ -385,7 +398,8 @@
                 }
                 @Composable
                 fun Leaf(text: String, %composer: Composer?, %changed: Int) {
-                  %composer = %composer.startRestartGroup(<>, "C(Leaf):Test.kt#2487m")
+                  %composer = %composer.startRestartGroup(<>)
+                  sourceInformation(%composer, "C(Leaf):Test.kt#2487m")
                   val %dirty = %changed
                   if (%changed and 0b1110 === 0) {
                     %dirty = %dirty or if (%composer.changed(text)) 0b0100 else 0b0010
@@ -401,14 +415,17 @@
                 }
                 @Composable
                 fun Test(value: Int, %composer: Composer?, %changed: Int) {
-                  %composer = %composer.startRestartGroup(<>, "C(Test):Test.kt#2487m")
+                  %composer = %composer.startRestartGroup(<>)
+                  sourceInformation(%composer, "C(Test):Test.kt#2487m")
                   val %dirty = %changed
                   if (%changed and 0b1110 === 0) {
                     %dirty = %dirty or if (%composer.changed(value)) 0b0100 else 0b0010
                   }
                   if (%dirty and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
-                    %composer.startMovableGroup(<>, value, "<Wrappe...>")
-                    Wrapper(composableLambda(%composer, <>, true, "C<Leaf("...>:Test.kt#2487m") { %composer: Composer?, %changed: Int ->
+                    %composer.startMovableGroup(<>, value)
+                    sourceInformation(%composer, "<Wrappe...>")
+                    Wrapper(composableLambda(%composer, <>, true) { %composer: Composer?, %changed: Int ->
+                      sourceInformation(%composer, "C<Leaf("...>:Test.kt#2487m")
                       if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                         Leaf("Value %value", %composer, 0)
                       } else {
@@ -486,17 +503,20 @@
             """
                 @Composable
                 fun composeVector(composable: Function2<Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
-                  %composer = %composer.startRestartGroup(<>, "C(composeVector)<emit>:Test.kt#2487m")
+                  %composer = %composer.startRestartGroup(<>)
+                  sourceInformation(%composer, "C(composeVector)<emit>:Test.kt#2487m")
                   val %dirty = %changed
                   if (%changed and 0b1110 === 0) {
                     %dirty = %dirty or if (%composer.changed(composable)) 0b0100 else 0b0010
                   }
                   if (%dirty and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                     emit({ %composer: Composer?, %changed: Int ->
-                      %composer.startReplaceableGroup(<>, "C<emit>:Test.kt#2487m")
+                      %composer.startReplaceableGroup(<>)
+                      sourceInformation(%composer, "C<emit>:Test.kt#2487m")
                       if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                         emit({ %composer: Composer?, %changed: Int ->
-                          %composer.startReplaceableGroup(<>, "C<compos...>:Test.kt#2487m")
+                          %composer.startReplaceableGroup(<>)
+                          sourceInformation(%composer, "C<compos...>:Test.kt#2487m")
                           if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                             composable(%composer, 0b1110 and %dirty)
                           } else {
@@ -518,7 +538,8 @@
                 }
                 @Composable
                 fun emit(composable: Function2<Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
-                  %composer.startReplaceableGroup(<>, "C(emit)<compos...>:Test.kt#2487m")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "C(emit)<compos...>:Test.kt#2487m")
                   composable(%composer, 0b1110 and %changed)
                   %composer.endReplaceableGroup()
                 }
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ControlFlowTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ControlFlowTransformTests.kt
index 53823d7..943df22 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ControlFlowTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ControlFlowTransformTests.kt
@@ -35,7 +35,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               if (x > 0) {
                 NA()
               }
@@ -61,9 +62,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               if (x > 0) {
-                %composer.startReplaceableGroup(<>, "<A()>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<A()>")
                 A(%composer, 0)
                 %composer.endReplaceableGroup()
               } else {
@@ -94,13 +97,16 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               if (x > 0) {
-                %composer.startReplaceableGroup(<>, "<A(a)>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<A(a)>")
                 A(a, %composer, 0)
                 %composer.endReplaceableGroup()
               } else {
-                %composer.startReplaceableGroup(<>, "<A(b)>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<A(b)>")
                 A(b, %composer, 0)
                 %composer.endReplaceableGroup()
               }
@@ -128,7 +134,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<B()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<B()>:Test.kt")
               if (B(%composer, 0)) {
                 NA()
               } else {
@@ -162,13 +169,16 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
-              if (%composer.startReplaceableGroup(<>, "<B(a)>")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
+              if (%composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "<B(a)>")
               val tmp0_group = B(a, %composer, 0)
               %composer.endReplaceableGroup()
               tmp0_group) {
                 NA()
-              } else if (%composer.startReplaceableGroup(<>, "<B(b)>")
+              } else if (%composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "<B(b)>")
               val tmp1_group = B(b, %composer, 0)
               %composer.endReplaceableGroup()
               tmp1_group) {
@@ -198,7 +208,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               val tmp0_subject = x
               when {
                 tmp0_subject == 0 -> {
@@ -235,21 +246,25 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               val tmp0_subject = x
               when {
                 tmp0_subject == 0 -> {
-                  %composer.startReplaceableGroup(<>, "<A(a)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<A(a)>")
                   A(a, %composer, 0)
                   %composer.endReplaceableGroup()
                 }
                 tmp0_subject == 0b0001 -> {
-                  %composer.startReplaceableGroup(<>, "<A(b)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<A(b)>")
                   A(b, %composer, 0)
                   %composer.endReplaceableGroup()
                 }
                 else -> {
-                  %composer.startReplaceableGroup(<>, "<A(c)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<A(c)>")
                   A(c, %composer, 0)
                   %composer.endReplaceableGroup()
                 }
@@ -278,23 +293,27 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               val y = val tmp0_subject = x
               when {
                 tmp0_subject == 0 -> {
-                  %composer.startReplaceableGroup(<>, "<R(a)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<R(a)>")
                   val tmp0_group = R(a, %composer, 0)
                   %composer.endReplaceableGroup()
                   tmp0_group
                 }
                 tmp0_subject == 0b0001 -> {
-                  %composer.startReplaceableGroup(<>, "<R(b)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<R(b)>")
                   val tmp1_group = R(b, %composer, 0)
                   %composer.endReplaceableGroup()
                   tmp1_group
                 }
                 else -> {
-                  %composer.startReplaceableGroup(<>, "<R(c)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<R(c)>")
                   val tmp2_group = R(c, %composer, 0)
                   %composer.endReplaceableGroup()
                   tmp2_group
@@ -324,20 +343,24 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               when {
                 x < 0 -> {
-                  %composer.startReplaceableGroup(<>, "<A(a)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<A(a)>")
                   A(a, %composer, 0)
                   %composer.endReplaceableGroup()
                 }
                 x > 30 -> {
-                  %composer.startReplaceableGroup(<>, "<A(b)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<A(b)>")
                   A(b, %composer, 0)
                   %composer.endReplaceableGroup()
                 }
                 else -> {
-                  %composer.startReplaceableGroup(<>, "<A(c)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<A(c)>")
                   A(c, %composer, 0)
                   %composer.endReplaceableGroup()
                 }
@@ -366,10 +389,12 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               when {
                 x < 0 -> {
-                  %composer.startReplaceableGroup(<>, "<A(a)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<A(a)>")
                   A(a, %composer, 0)
                   %composer.endReplaceableGroup()
                 }
@@ -379,7 +404,8 @@
                   NA()
                 }
                 else -> {
-                  %composer.startReplaceableGroup(<>, "<A(b)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<A(b)>")
                   A(b, %composer, 0)
                   %composer.endReplaceableGroup()
                 }
@@ -409,15 +435,18 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               when {
-                %composer.startReplaceableGroup(<>, "<R(a)>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<R(a)>")
                 val tmp0_group = x == R(a, %composer, 0)
                 %composer.endReplaceableGroup()
                 tmp0_group -> {
                   NA()
                 }
-                %composer.startReplaceableGroup(<>, "<R(b)>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<R(b)>")
                 val tmp1_group = x > R(b, %composer, 0)
                 %composer.endReplaceableGroup()
                 tmp1_group -> {
@@ -452,16 +481,20 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<A()>:Test.kt")
-              %composer.startReplaceableGroup(<>, "")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "")
               when {
-                %composer.startReplaceableGroup(<>, "<R(a)>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<R(a)>")
                 val tmp0_group = x == R(a, %composer, 0)
                 %composer.endReplaceableGroup()
                 tmp0_group -> {
                   NA()
                 }
-                %composer.startReplaceableGroup(<>, "<R(b)>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<R(b)>")
                 val tmp1_group = x > R(b, %composer, 0)
                 %composer.endReplaceableGroup()
                 tmp1_group -> {
@@ -492,7 +525,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int?, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               val tmp0_safe_receiver = x
               when {
                 tmp0_safe_receiver == null -> {
@@ -501,7 +535,8 @@
                   null
                 }
                 else -> {
-                  %composer.startReplaceableGroup(<>, "<A()>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<A()>")
                   tmp0_safe_receiver.A(%composer, 0b1110 and %changed)
                   %composer.endReplaceableGroup()
                 }
@@ -525,11 +560,13 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int?, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               val y = val tmp0_elvis_lhs = x
               when {
                 tmp0_elvis_lhs == null -> {
-                  %composer.startReplaceableGroup(<>, "<R()>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<R()>")
                   val tmp0_group = R(%composer, 0)
                   %composer.endReplaceableGroup()
                   tmp0_group
@@ -562,7 +599,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(items: List<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<P(i)>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<P(i)>:Test.kt")
               val tmp0_iterator = items.iterator()
               while (tmp0_iterator.hasNext()) {
                 val i = tmp0_iterator.next()
@@ -590,8 +628,10 @@
             @NonRestartableComposable
             @Composable
             fun Example(items: List<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<A()>:Test.kt")
-              %composer.startReplaceableGroup(<>, "*<P(i)>")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "*<P(i)>")
               val tmp0_iterator = items.iterator()
               while (tmp0_iterator.hasNext()) {
                 val i = tmp0_iterator.next()
@@ -620,7 +660,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<L()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<L()>:Test.kt")
               val tmp0_iterator = L(%composer, 0).iterator()
               while (tmp0_iterator.hasNext()) {
                 val i = tmp0_iterator.next()
@@ -650,7 +691,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(items: MutableList<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<P(item...>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<P(item...>:Test.kt")
               while (items.isNotEmpty()) {
                 val item = items.removeAt(items.size - 1)
                 P(item, %composer, 0)
@@ -679,8 +721,10 @@
             @NonRestartableComposable
             @Composable
             fun Example(items: MutableList<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<A()>:Test.kt")
-              %composer.startReplaceableGroup(<>, "*<P(item...>")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "*<P(item...>")
               while (items.isNotEmpty()) {
                 val item = items.removeAt(items.size - 1)
                 P(item, %composer, 0)
@@ -709,7 +753,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<B()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<B()>:Test.kt")
               while (B(%composer, 0)) {
                 print("hello world")
               }
@@ -735,8 +780,10 @@
             @NonRestartableComposable
             @Composable
             fun Example(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<A()>:Test.kt")
-              %composer.startReplaceableGroup(<>, "*<B()>")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "*<B()>")
               while (B(%composer, 0)) {
                 print("hello world")
               }
@@ -764,7 +811,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<B()>,<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<B()>,<A()>:Test.kt")
               while (B(%composer, 0)) {
                 A(%composer, 0)
               }
@@ -791,8 +839,10 @@
             @NonRestartableComposable
             @Composable
             fun Example(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<A(b)>:Test.kt")
-              %composer.startReplaceableGroup(<>, "*<B()>,<A(a)>")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<A(b)>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "*<B()>,<A(a)>")
               while (B(%composer, 0)) {
                 A(a, %composer, 0)
               }
@@ -820,9 +870,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               if (x > 0) {
-                %composer.startReplaceableGroup(<>, "<A()>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<A()>")
                 A(%composer, 0)
                 %composer.endReplaceableGroup()
                 %composer.endReplaceableGroup()
@@ -853,7 +905,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<A()>:Test.kt")
               if (x > 0) {
                 %composer.endReplaceableGroup()
                 return
@@ -880,9 +933,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int): Int {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               if (x > 0) {
-                %composer.startReplaceableGroup(<>, "<A()>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<A()>")
                 A(%composer, 0)
                 val tmp1_return = 1
                 %composer.endReplaceableGroup()
@@ -915,7 +970,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int): Int {
-              %composer.startReplaceableGroup(<>, "C(Example)<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<A()>:Test.kt")
               if (x > 0) {
                 val tmp1_return = 1
                 %composer.endReplaceableGroup()
@@ -944,7 +1000,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(%composer: Composer?, %changed: Int): Int {
-              %composer.startReplaceableGroup(<>, "C(Example)<A()>,<R()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<A()>,<R()>:Test.kt")
               A(%composer, 0)
               val tmp0 = R(%composer, 0)
               %composer.endReplaceableGroup()
@@ -968,9 +1025,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int): Int {
-              %composer.startReplaceableGroup(<>, "C(Example)<R()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<R()>:Test.kt")
               if (x > 0) {
-                %composer.startReplaceableGroup(<>, "<R()>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<R()>")
                 val tmp1_return = R(%composer, 0)
                 %composer.endReplaceableGroup()
                 %composer.endReplaceableGroup()
@@ -1011,7 +1070,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<P(i)>,<P(l)>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<P(i)>,<P(l)>:Test.kt")
               while (items.hasNext()) {
                 val i = items.next()
                 val j = i
@@ -1019,13 +1079,15 @@
                 val l = i
                 P(i, %composer, 0)
                 if (i == 0) {
-                  %composer.startReplaceableGroup(<>, "<P(j)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<P(j)>")
                   P(j, %composer, 0)
                   %composer.endReplaceableGroup()
                   %composer.endReplaceableGroup()
                   return
                 } else {
-                  %composer.startReplaceableGroup(<>, "<P(k)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<P(k)>")
                   P(k, %composer, 0)
                   %composer.endReplaceableGroup()
                 }
@@ -1060,7 +1122,8 @@
         """
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example)*<P(i)>,<P(l)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example)*<P(i)>,<P(l)>:Test.kt")
               while (items.hasNext()) {
                 val i = items.next()
                 val j = i
@@ -1068,7 +1131,8 @@
                 val l = i
                 P(i, %composer, 0)
                 if (i == 0) {
-                  %composer.startReplaceableGroup(<>, "<P(j)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<P(j)>")
                   P(j, %composer, 0)
                   %composer.endReplaceableGroup()
                   %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
@@ -1076,7 +1140,8 @@
                   }
                   return
                 } else {
-                  %composer.startReplaceableGroup(<>, "<P(k)>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<P(k)>")
                   P(k, %composer, 0)
                   %composer.endReplaceableGroup()
                 }
@@ -1107,7 +1172,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<P(i)>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<P(i)>:Test.kt")
               while (items.hasNext()) {
                 val i = items.next()
                 if (i == 0) {
@@ -1138,7 +1204,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<P(i)>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<P(i)>:Test.kt")
               while (items.hasNext()) {
                 val i = items.next()
                 P(i, %composer, 0)
@@ -1172,7 +1239,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<P(i)>,<P(j)>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<P(i)>,<P(j)>:Test.kt")
               while (items.hasNext()) {
                 val i = items.next()
                 val j = i
@@ -1208,8 +1276,10 @@
             @NonRestartableComposable
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<A()>:Test.kt")
-              %composer.startReplaceableGroup(<>, "*<P(i)>,<P(i)>")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "*<P(i)>,<P(i)>")
               while (items.hasNext()) {
                 val i = items.next()
                 P(i, %composer, 0)
@@ -1243,9 +1313,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               while (items.hasNext()) {
-                %composer.startReplaceableGroup(<>, "<P(i)>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<P(i)>")
                 val i = items.next()
                 if (i == 0) {
                   %composer.endReplaceableGroup()
@@ -1278,9 +1350,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               while (items.hasNext()) {
-                %composer.startReplaceableGroup(<>, "<P(i)>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<P(i)>")
                 val i = items.next()
                 P(i, %composer, 0)
                 if (i == 0) {
@@ -1314,9 +1388,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(items: Iterator<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               while (items.hasNext()) {
-                %composer.startReplaceableGroup(<>, "<P(i)>,<P(i)>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<P(i)>,<P(i)>")
                 val i = items.next()
                 P(i, %composer, 0)
                 if (i == 0) {
@@ -1349,7 +1425,8 @@
             @NonRestartableComposable
             @Composable
             fun Example(a: Iterator<Int>, b: Iterator<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<A()>:Test.kt")
               while (a.hasNext()) {
                 val x = a.next()
                 if (x > 100) {
@@ -1385,10 +1462,12 @@
             @NonRestartableComposable
             @Composable
             fun Example(a: Iterator<Int>, b: Iterator<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<A()>:Test.kt")
               a@while (a.hasNext()) {
                 val x = a.next()
-                %composer.startReplaceableGroup(<>, "*<A()>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "*<A()>")
                 b@while (b.hasNext()) {
                   val y = b.next()
                   if (y == x) {
@@ -1436,13 +1515,15 @@
             @NonRestartableComposable
             @Composable
             fun Example(a: Iterator<Int>, b: Iterator<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<A()>:Test.kt")
               a@while (a.hasNext()) {
                 val x = a.next()
                 if (x == 0) {
                   break
                 }
-                %composer.startReplaceableGroup(<>, "*<A()>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "*<A()>")
                 b@while (b.hasNext()) {
                   val y = b.next()
                   if (y == 0) {
@@ -1485,10 +1566,13 @@
             @NonRestartableComposable
             @Composable
             fun Example(a: Iterator<Int>, b: Iterator<Int>, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<A()>:Test.kt")
-              %composer.startReplaceableGroup(<>, "*<A()>")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "*<A()>")
               a@while (a.hasNext()) {
-                %composer.startReplaceableGroup(<>, "*<A()>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "*<A()>")
                 b@while (b.hasNext()) {
                   A(%composer, 0)
                 }
@@ -1519,10 +1603,13 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               if (x > 0) {
-                %composer.startReplaceableGroup(<>, "<A()>")
-                %composer.startReplaceableGroup(<>, "*<A()>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<A()>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "*<A()>")
                 while (x > 0) {
                   A(%composer, 0)
                 }
@@ -1555,9 +1642,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               if (x > 0) {
-                %composer.startReplaceableGroup(<>, "<A()>,*<A()>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<A()>,*<A()>")
                 A(%composer, 0)
                 while (x > 0) {
                   A(%composer, 0)
@@ -1588,9 +1677,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               if (x > 0) {
-                %composer.startReplaceableGroup(<>, "*<A()>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "*<A()>")
                 while (x > 0) {
                   A(%composer, 0)
                 }
@@ -1620,9 +1711,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               while (x > 0) {
-                %composer.startMovableGroup(<>, x, "<A()>")
+                %composer.startMovableGroup(<>, x)
+                sourceInformation(%composer, "<A()>")
                 A(%composer, 0)
                 %composer.endMovableGroup()
               }
@@ -1650,12 +1743,15 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               while (x > 0) {
-                %composer.startMovableGroup(<>, x, "<A(a)>")
+                %composer.startMovableGroup(<>, x)
+                sourceInformation(%composer, "<A(a)>")
                 A(a, %composer, 0)
                 %composer.endMovableGroup()
-                %composer.startMovableGroup(<>, x + 1, "<A(b)>")
+                %composer.startMovableGroup(<>, x + 1)
+                sourceInformation(%composer, "<A(b)>")
                 A(b, %composer, 0)
                 %composer.endMovableGroup()
               }
@@ -1681,9 +1777,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<A(b)>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<A(b)>:Test.kt")
               while (x > 0) {
-                %composer.startMovableGroup(<>, x, "<A(a)>")
+                %composer.startMovableGroup(<>, x)
+                sourceInformation(%composer, "<A(a)>")
                 A(a, %composer, 0)
                 %composer.endMovableGroup()
                 A(b, %composer, 0)
@@ -1710,10 +1808,12 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<A(a)>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<A(a)>:Test.kt")
               while (x > 0) {
                 A(a, %composer, 0)
-                %composer.startMovableGroup(<>, x, "<A(b)>")
+                %composer.startMovableGroup(<>, x)
+                sourceInformation(%composer, "<A(b)>")
                 A(b, %composer, 0)
                 %composer.endMovableGroup()
               }
@@ -1740,10 +1840,12 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<A(a)>,<A(c)>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<A(a)>,<A(c)>:Test.kt")
               while (x > 0) {
                 A(a, %composer, 0)
-                %composer.startMovableGroup(<>, x, "<A(b)>")
+                %composer.startMovableGroup(<>, x)
+                sourceInformation(%composer, "<A(b)>")
                 A(b, %composer, 0)
                 %composer.endMovableGroup()
                 A(c, %composer, 0)
@@ -1767,8 +1869,10 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
-              %composer.startMovableGroup(<>, x, "<A()>")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
+              %composer.startMovableGroup(<>, x)
+              sourceInformation(%composer, "<A()>")
               A(%composer, 0)
               %composer.endMovableGroup()
               %composer.endReplaceableGroup()
@@ -1791,8 +1895,10 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<A(b)>:Test.kt")
-              %composer.startMovableGroup(<>, x, "<A(a)>")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<A(b)>:Test.kt")
+              %composer.startMovableGroup(<>, x)
+              sourceInformation(%composer, "<A(a)>")
               A(a, %composer, 0)
               %composer.endMovableGroup()
               A(b, %composer, 0)
@@ -1816,9 +1922,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<A(a)>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<A(a)>:Test.kt")
               A(a, %composer, 0)
-              %composer.startMovableGroup(<>, x, "<A(b)>")
+              %composer.startMovableGroup(<>, x)
+              sourceInformation(%composer, "<A(b)>")
               A(b, %composer, 0)
               %composer.endMovableGroup()
               %composer.endReplaceableGroup()
@@ -1842,10 +1950,13 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               if (x > 0) {
-                %composer.startReplaceableGroup(<>, "")
-                %composer.startMovableGroup(<>, x, "<A()>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "")
+                %composer.startMovableGroup(<>, x)
+                sourceInformation(%composer, "<A()>")
                 A(%composer, 0)
                 %composer.endMovableGroup()
                 %composer.endReplaceableGroup()
@@ -1875,10 +1986,13 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               if (x > 0) {
-                %composer.startReplaceableGroup(<>, "<A(b)>")
-                %composer.startMovableGroup(<>, x, "<A(a)>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<A(b)>")
+                %composer.startMovableGroup(<>, x)
+                sourceInformation(%composer, "<A(a)>")
                 A(a, %composer, 0)
                 %composer.endMovableGroup()
                 A(b, %composer, 0)
@@ -1909,11 +2023,14 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               if (x > 0) {
-                %composer.startReplaceableGroup(<>, "<A(a)>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<A(a)>")
                 A(a, %composer, 0)
-                %composer.startMovableGroup(<>, x, "<A(b)>")
+                %composer.startMovableGroup(<>, x)
+                sourceInformation(%composer, "<A(b)>")
                 A(b, %composer, 0)
                 %composer.endMovableGroup()
                 %composer.endReplaceableGroup()
@@ -1940,8 +2057,10 @@
             @NonRestartableComposable
             @Composable
             fun Example(a: Int, b: Int, c: Int, d: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
-              %composer.startMovableGroup(<>, %composer.joinKey(%composer.joinKey(%composer.joinKey(a, b), c), d), "<A()>")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
+              %composer.startMovableGroup(<>, %composer.joinKey(%composer.joinKey(%composer.joinKey(a, b), c), d))
+              sourceInformation(%composer, "<A()>")
               A(%composer, 0)
               %composer.endMovableGroup()
               %composer.endReplaceableGroup()
@@ -1965,9 +2084,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)*<R()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)*<R()>:Test.kt")
               while (x > 0) {
-                %composer.startMovableGroup(<>, R(%composer, 0), "<A()>")
+                %composer.startMovableGroup(<>, R(%composer, 0))
+                sourceInformation(%composer, "<A()>")
                 A(%composer, 0)
                 %composer.endMovableGroup()
               }
@@ -1989,9 +2110,11 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<P(y)>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<P(y)>:Test.kt")
               val y =
-              %composer.startMovableGroup(<>, x, "<R()>")
+              %composer.startMovableGroup(<>, x)
+              sourceInformation(%composer, "<R()>")
               val tmp0 = R(%composer, 0)
               %composer.endMovableGroup()
               tmp0
@@ -2017,14 +2140,18 @@
             @NonRestartableComposable
             @Composable
             fun Example(x: Int, %composer: Composer?, %changed: Int): Int {
-              %composer.startReplaceableGroup(<>, "C(Example):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               val tmp0 = if (x > 0) {
-                %composer.startReplaceableGroup(<>, "")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "")
                 val tmp4_group =
-                val tmp3_group = if (%composer.startReplaceableGroup(<>, "<B()>")
+                val tmp3_group = if (%composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<B()>")
                 val tmp1_group = B(%composer, 0)
                 %composer.endReplaceableGroup()
-                tmp1_group) 1 else if (%composer.startReplaceableGroup(<>, "<B()>")
+                tmp1_group) 1 else if (%composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<B()>")
                 val tmp2_group = B(%composer, 0)
                 %composer.endReplaceableGroup()
                 tmp2_group) 2 else 3
@@ -2091,8 +2218,10 @@
             @NonRestartableComposable
             @Composable
             fun Simple(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Simple)<A()>:Test.kt")
-              %composer.startReplaceableGroup(<>, "*<A()>")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Simple)<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "*<A()>")
               run {
                 A(%composer, 0)
               }
@@ -2103,8 +2232,10 @@
             @NonRestartableComposable
             @Composable
             fun WithReturn(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(WithReturn)<A()>:Test.kt")
-              %composer.startReplaceableGroup(<>, "*<A()>")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(WithReturn)<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "*<A()>")
               run {
                 A(%composer, 0)
                 %composer.endReplaceableGroup()
@@ -2118,7 +2249,8 @@
             @NonRestartableComposable
             @Composable
             fun NoCalls(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(NoCalls)<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(NoCalls)<A()>:Test.kt")
               run {
                 println("hello world")
               }
@@ -2128,7 +2260,8 @@
             @NonRestartableComposable
             @Composable
             fun NoCallsAfter(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(NoCallsAfter)*<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(NoCallsAfter)*<A()>:Test.kt")
               run {
                 A(%composer, 0)
               }
@@ -2154,7 +2287,8 @@
         """
             @Composable
             fun Example(x: Int?, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example)<A(c)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example)<A(c)>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -2168,10 +2302,12 @@
                     null
                   }
                   else -> {
-                    %composer.startReplaceableGroup(<>, "*<A(b)>")
+                    %composer.startReplaceableGroup(<>)
+                    sourceInformation(%composer, "*<A(b)>")
                     tmp0_safe_receiver.let { it: Int ->
                       if (it > 0) {
-                        %composer.startReplaceableGroup(<>, "<A(a)>")
+                        %composer.startReplaceableGroup(<>)
+                        sourceInformation(%composer, "<A(a)>")
                         A(a, %composer, 0)
                         %composer.endReplaceableGroup()
                       } else {
@@ -2211,7 +2347,8 @@
         """
             @Composable
             fun Example(x: Int?, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example)<A()>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example)<A()>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -2249,7 +2386,8 @@
         """
             @Composable
             fun <T> provided(value: T, %composer: Composer?, %changed: Int): State<T> {
-              %composer.startReplaceableGroup(<>, "C(provided)*<rememb...>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(provided)*<rememb...>:Test.kt")
               val tmp0 = remember({
                 val tmp0_return = mutableStateOf(
                   value = value
@@ -2282,7 +2420,8 @@
         """
             @Composable
             fun Test(x: Int, %composer: Composer?, %changed: Int): Int {
-              %composer.startReplaceableGroup(<>, "C(Test)*<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Test)*<A()>:Test.kt")
               val tmp0 =
               val tmp1_group = x.let { it: Int ->
                 A(%composer, 0)
@@ -2309,7 +2448,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<W>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<W>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 W(ComposableSingletons%TestKt.lambda-1, %composer, 0)
               } else {
@@ -2320,7 +2460,8 @@
               }
             }
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "C<A()>:Test.kt") { %composer: Composer?, %changed: Int ->
+              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C<A()>:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   A(%composer, 0)
                 } else {
@@ -2344,10 +2485,12 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<IW>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<IW>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 IW({ %composer: Composer?, %changed: Int ->
-                  %composer.startReplaceableGroup(<>, "C<A()>:Test.kt")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "C<A()>:Test.kt")
                   if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                     A(%composer, 0)
                   } else {
@@ -2383,7 +2526,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<Wrap>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<Wrap>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 Wrap(ComposableSingletons%TestKt.lambda-1, %composer, 0)
               } else {
@@ -2394,9 +2538,11 @@
               }
             }
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "C<effect>:Test.kt") { %composer: Composer?, %changed: Int ->
+              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C<effect>:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
-                  %composer.startReplaceableGroup(<>, "*<effect>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "*<effect>")
                   repeat(number) { it: Int ->
                     effects[it] = effect({
                       0
@@ -2437,7 +2583,8 @@
         """
             @Composable
             fun Test(value: InlineClass, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)P(0:InlineClass)<A()>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)P(0:InlineClass)<A()>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(value.value)) 0b0100 else 0b0010
@@ -2606,7 +2753,8 @@
         """
             @Composable
             fun Test01(p0: Int, p1: Int, p2: Int, p3: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test01):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test01):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p0)) 0b0100 else 0b0010
@@ -2634,7 +2782,8 @@
             }
             @Composable
             fun Test02(p0: Int, p1: Int, p3: Int, p2: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test02)P(!2,3):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test02)P(!2,3):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p0)) 0b0100 else 0b0010
@@ -2662,7 +2811,8 @@
             }
             @Composable
             fun Test03(p0: Int, p2: Int, p1: Int, p3: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test03)P(!1,2):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test03)P(!1,2):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p0)) 0b0100 else 0b0010
@@ -2690,7 +2840,8 @@
             }
             @Composable
             fun Test04(p0: Int, p2: Int, p3: Int, p1: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test04)P(!1,2,3):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test04)P(!1,2,3):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p0)) 0b0100 else 0b0010
@@ -2718,7 +2869,8 @@
             }
             @Composable
             fun Test05(p0: Int, p3: Int, p1: Int, p2: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test05)P(!1,3):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test05)P(!1,3):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p0)) 0b0100 else 0b0010
@@ -2746,7 +2898,8 @@
             }
             @Composable
             fun Test06(p0: Int, p3: Int, p2: Int, p1: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test06)P(!1,3,2):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test06)P(!1,3,2):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p0)) 0b0100 else 0b0010
@@ -2774,7 +2927,8 @@
             }
             @Composable
             fun Test07(p1: Int, p0: Int, p2: Int, p3: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test07)P(1):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test07)P(1):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p1)) 0b0100 else 0b0010
@@ -2802,7 +2956,8 @@
             }
             @Composable
             fun Test08(p1: Int, p0: Int, p3: Int, p2: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test08)P(1!1,3):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test08)P(1!1,3):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p1)) 0b0100 else 0b0010
@@ -2830,7 +2985,8 @@
             }
             @Composable
             fun Test09(p1: Int, p2: Int, p0: Int, p3: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test09)P(1,2):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test09)P(1,2):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p1)) 0b0100 else 0b0010
@@ -2858,7 +3014,8 @@
             }
             @Composable
             fun Test00(p1: Int, p2: Int, p3: Int, p0: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test00)P(1,2,3):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test00)P(1,2,3):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p1)) 0b0100 else 0b0010
@@ -2886,7 +3043,8 @@
             }
             @Composable
             fun Test11(p1: Int, p3: Int, p0: Int, p2: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test11)P(1,3):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test11)P(1,3):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p1)) 0b0100 else 0b0010
@@ -2914,7 +3072,8 @@
             }
             @Composable
             fun Test12(p1: Int, p3: Int, p2: Int, p0: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test12)P(1,3,2):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test12)P(1,3,2):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p1)) 0b0100 else 0b0010
@@ -2942,7 +3101,8 @@
             }
             @Composable
             fun Test13(p2: Int, p0: Int, p1: Int, p3: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test13)P(2):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test13)P(2):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p2)) 0b0100 else 0b0010
@@ -2970,7 +3130,8 @@
             }
             @Composable
             fun Test14(p2: Int, p0: Int, p3: Int, p1: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test14)P(2!1,3):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test14)P(2!1,3):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p2)) 0b0100 else 0b0010
@@ -2998,7 +3159,8 @@
             }
             @Composable
             fun Test15(p2: Int, p1: Int, p0: Int, p3: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test15)P(2,1):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test15)P(2,1):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p2)) 0b0100 else 0b0010
@@ -3026,7 +3188,8 @@
             }
             @Composable
             fun Test16(p2: Int, p1: Int, p3: Int, p0: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test16)P(2,1,3):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test16)P(2,1,3):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p2)) 0b0100 else 0b0010
@@ -3054,7 +3217,8 @@
             }
             @Composable
             fun Test17(p2: Int, p3: Int, p0: Int, p1: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test17)P(2,3):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test17)P(2,3):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p2)) 0b0100 else 0b0010
@@ -3082,7 +3246,8 @@
             }
             @Composable
             fun Test18(p2: Int, p3: Int, p1: Int, p0: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test18)P(2,3,1):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test18)P(2,3,1):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p2)) 0b0100 else 0b0010
@@ -3110,7 +3275,8 @@
             }
             @Composable
             fun Test19(p3: Int, p0: Int, p1: Int, p2: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test19)P(3):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test19)P(3):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p3)) 0b0100 else 0b0010
@@ -3138,7 +3304,8 @@
             }
             @Composable
             fun Test20(p3: Int, p0: Int, p2: Int, p1: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test20)P(3!1,2):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test20)P(3!1,2):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p3)) 0b0100 else 0b0010
@@ -3166,7 +3333,8 @@
             }
             @Composable
             fun Test21(p3: Int, p1: Int, p0: Int, p2: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test21)P(3,1):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test21)P(3,1):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p3)) 0b0100 else 0b0010
@@ -3194,7 +3362,8 @@
             }
             @Composable
             fun Test22(p3: Int, p1: Int, p2: Int, p0: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test22)P(3,1,2):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test22)P(3,1,2):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p3)) 0b0100 else 0b0010
@@ -3222,7 +3391,8 @@
             }
             @Composable
             fun Test23(p3: Int, p2: Int, p0: Int, p1: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test23)P(3,2):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test23)P(3,2):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p3)) 0b0100 else 0b0010
@@ -3250,7 +3420,8 @@
             }
             @Composable
             fun Test24(p3: Int, p2: Int, p1: Int, p0: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test24)P(3,2,1):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test24)P(3,2,1):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(p3)) 0b0100 else 0b0010
@@ -3300,7 +3471,8 @@
         expectedTransformed = """
             @Composable
             fun Test(value: LocalInlineClass, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)P(0:c#runtime.tests.LocalInlineClass):Test.kt#992ot2")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)P(0:c#runtime.tests.LocalInlineClass):Test.kt#992ot2")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(value.value)) 0b0100 else 0b0010
@@ -3340,7 +3512,8 @@
         expectedTransformed = """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<b()>,<c()>,<d()>,<A(b(),>,<B()>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<b()>,<c()>,<d()>,<A(b(),>,<B()>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 A(b(%composer, 0), c(%composer, 0), d(%composer, 0), %composer, 0)
                 B(%composer, 0)
@@ -3388,7 +3561,8 @@
             class SomeClass {
               var a: String = "Test"
               fun onCreate() {
-                setContent(composableLambdaInstance(<>, true, "C<B(a)>,<B(a)>:Test.kt") { %composer: Composer?, %changed: Int ->
+                setContent(composableLambdaInstance(<>, true) { %composer: Composer?, %changed: Int ->
+                  sourceInformation(%composer, "C<B(a)>,<B(a)>:Test.kt")
                   if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                     B(a, %composer, 0)
                     B(a, %composer, 0)
@@ -3402,7 +3576,8 @@
             }
             fun Test() {
               var a = "Test"
-              setContent(composableLambdaInstance(<>, true, "C<B(a)>,<B(a)>:Test.kt") { %composer: Composer?, %changed: Int ->
+              setContent(composableLambdaInstance(<>, true) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C<B(a)>,<B(a)>:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   B(a, %composer, 0)
                   B(a, %composer, 0)
@@ -3443,7 +3618,8 @@
         expectedTransformed = """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<W>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<W>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 W(ComposableSingletons%TestKt.lambda-1, %composer, 0)
               } else {
@@ -3454,13 +3630,16 @@
               }
             }
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "C<IW>:Test.kt") { %composer: Composer?, %changed: Int ->
+              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C<IW>:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   IW({ %composer: Composer?, %changed: Int ->
-                    %composer.startReplaceableGroup(<>, "C<T(2)>,<T(4)>:Test.kt")
+                    %composer.startReplaceableGroup(<>)
+                    sourceInformation(%composer, "C<T(2)>,<T(4)>:Test.kt")
                     if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                       T(2, %composer, 0b0110)
-                      %composer.startReplaceableGroup(<>, "*<T(3)>")
+                      %composer.startReplaceableGroup(<>)
+                      sourceInformation(%composer, "*<T(3)>")
                       repeat(3) { it: Int ->
                         T(3, %composer, 0b0110)
                       }
@@ -3509,27 +3688,138 @@
             val current: Int
               @Composable @ReadOnlyComposable @JvmName(name = "getCurrent")
               get() {
-                %composer.startReplaceableGroup(<>, "C:Test.kt")
+                sourceInformationMarkerStart(%composer, <>, "C:Test.kt")
                 val tmp0 = 0
-                %composer.endReplaceableGroup()
+                sourceInformationMarkerEnd(%composer)
                 return tmp0
               }
             @Composable
             @ReadOnlyComposable
             fun calculateSometing(%composer: Composer?, %changed: Int): Int {
-              %composer.startReplaceableGroup(<>, "C(calculateSometing):Test.kt")
+              sourceInformationMarkerStart(%composer, <>, "C(calculateSometing):Test.kt")
               val tmp0 = 0
-              %composer.endReplaceableGroup()
+              sourceInformationMarkerEnd(%composer)
               return tmp0
             }
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<curren...>,<calcul...>,<Layout>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<curren...>,<calcul...>,<Layout>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 val c = current
                 val cl = calculateSometing(%composer, 0)
                 Layout({ %composer: Composer?, %changed: Int ->
-                  %composer.startReplaceableGroup(<>, "C<Text("...>:Test.kt")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "C<Text("...>:Test.kt")
+                  if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
+                    Text("%c %cl", %composer, 0)
+                  } else {
+                    %composer.skipToGroupEnd()
+                  }
+                  %composer.endReplaceableGroup()
+                }, %composer, 0)
+              } else {
+                %composer.skipToGroupEnd()
+              }
+              %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
+                Test(%composer, %changed or 0b0001)
+              }
+            }
+        """,
+        """
+            import androidx.compose.runtime.Composable
+
+            @Composable
+            inline fun Layout(content: @Composable () -> Unit) { content() }
+
+            @Composable
+            fun Text(text: String) { }
+        """
+    )
+
+    @Test
+    fun testReadOnlyInlineValSourceLocations() = verifyComposeIrTransform(
+        """
+            import androidx.compose.runtime.Composable
+            import androidx.compose.runtime.ReadOnlyComposable
+
+            class CurrentHolder {
+                inline val current: Int
+                    @ReadOnlyComposable
+                    @Composable
+                    get() = 0
+            }
+
+            class HolderHolder {
+                private val _currentHolder = CurrentHolder()
+                val current: Int
+                    @ReadOnlyComposable
+                    @Composable
+                    get() = _currentHolder.current
+            }
+
+            val holderHolder = HolderHolder()
+
+            @Composable
+            @ReadOnlyComposable
+            fun calculateSometing(): Int {
+                return 0;
+            }
+
+            @Composable
+            fun Test() {
+                val c = holderHolder.current
+                val cl = calculateSometing()
+                Layout {
+                    Text("${'$'}c ${'$'}cl")
+                }
+            }
+        """,
+        """
+            @StabilityInferred(parameters = 0)
+            class CurrentHolder {
+              val current: Int
+                @ReadOnlyComposable @Composable @JvmName(name = "getCurrent")
+                get() {
+                  sourceInformationMarkerStart(%composer, <>, "C:Test.kt")
+                  val tmp0 = 0
+                  sourceInformationMarkerEnd(%composer)
+                  return tmp0
+                }
+              static val %stable: Int = 0
+            }
+            @StabilityInferred(parameters = 0)
+            class HolderHolder {
+              val _currentHolder: CurrentHolder = CurrentHolder()
+              val current: Int
+                @ReadOnlyComposable @Composable @JvmName(name = "getCurrent")
+                get() {
+                  sourceInformationMarkerStart(%composer, <>, "C<curren...>:Test.kt")
+                  val tmp0 = _currentHolder.current
+                  sourceInformationMarkerEnd(%composer)
+                  return tmp0
+                }
+              static val %stable: Int = 0
+            }
+            val holderHolder: HolderHolder = HolderHolder()
+            @Composable
+            @ReadOnlyComposable
+            fun calculateSometing(%composer: Composer?, %changed: Int): Int {
+              sourceInformationMarkerStart(%composer, <>, "C(calculateSometing):Test.kt")
+              val tmp0 = 0
+              sourceInformationMarkerEnd(%composer)
+              return tmp0
+            }
+            @Composable
+            fun Test(%composer: Composer?, %changed: Int) {
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<curren...>,<calcul...>,<Layout>:Test.kt")
+              if (%changed !== 0 || !%composer.skipping) {
+                val c = holderHolder.current
+                val cl = calculateSometing(%composer, 0)
+                Layout({ %composer: Composer?, %changed: Int ->
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "C<Text("...>:Test.kt")
                   if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                     Text("%c %cl", %composer, 0)
                   } else {
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ControlFlowTransformTestsNoSource.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ControlFlowTransformTestsNoSource.kt
index 9b4fca9..8ccb434 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ControlFlowTransformTestsNoSource.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/ControlFlowTransformTestsNoSource.kt
@@ -33,7 +33,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)")
               if (%changed !== 0 || !%composer.skipping) {
                 A(a, %composer, 0)
                 A(b, %composer, 0)
@@ -86,7 +87,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)")
               if (%changed !== 0 || !%composer.skipping) {
                 W(ComposableSingletons%TestKt.lambda-1, %composer, 0)
               } else {
@@ -97,7 +99,7 @@
               }
             }
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "") { %composer: Composer?, %changed: Int ->
+              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   A(%composer, 0)
                 } else {
@@ -121,7 +123,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)")
               if (%changed !== 0 || !%composer.skipping) {
                 IW({ %composer: Composer?, %changed: Int ->
                   if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/DefaultParamTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/DefaultParamTransformTests.kt
index 1c8d410..0f07375 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/DefaultParamTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/DefaultParamTransformTests.kt
@@ -63,7 +63,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<A(1)>,<B()>,<B(2)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<A(1)>,<B()>,<B(2)>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 A(1, %composer, 0b0110)
                 B(0, %composer, 0, 0b0001)
@@ -96,7 +97,8 @@
         """
             @Composable
             fun Example(foo: Foo, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example)P(0:Foo):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example)P(0:Foo):Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -117,7 +119,8 @@
             }
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<Exampl...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<Exampl...>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 Example(Foo(0), %composer, 0, 0b0001)
               } else {
@@ -145,7 +148,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<A(0,>,<A(a>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<A(0,>,<A(a>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 A(0, 1, 2, 0, 0, %composer, 0b000110110110, 0b00011000)
                 A(0, 0, 2, 0, 0, %composer, 0b000110000110, 0b00011010)
@@ -173,7 +177,8 @@
         """
             @Composable
             fun Test(x: Int, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%default and 0b0001 === 0 && %composer.changed(x)) 0b0100 else 0b0010
@@ -217,7 +222,8 @@
         """
             @Composable
             fun A(a: Int, b: Int, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A):Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -331,7 +337,8 @@
         """
             @Composable
             fun Example(a00: Int, a01: Int, a02: Int, a03: Int, a04: Int, a05: Int, a06: Int, a07: Int, a08: Int, a09: Int, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int, a18: Int, a19: Int, a20: Int, a21: Int, a22: Int, a23: Int, a24: Int, a25: Int, a26: Int, a27: Int, a28: Int, a29: Int, a30: Int, %composer: Composer?, %changed: Int, %changed1: Int, %changed2: Int, %changed3: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               val %dirty = %changed
               val %dirty1 = %changed1
               val %dirty2 = %changed2
@@ -703,7 +710,8 @@
         """
             @Composable
             fun Example(a00: Int, a01: Int, a02: Int, a03: Int, a04: Int, a05: Int, a06: Int, a07: Int, a08: Int, a09: Int, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int, a18: Int, a19: Int, a20: Int, a21: Int, a22: Int, a23: Int, a24: Int, a25: Int, a26: Int, a27: Int, a28: Int, a29: Int, a30: Int, a31: Int, %composer: Composer?, %changed: Int, %changed1: Int, %changed2: Int, %changed3: Int, %default: Int, %default1: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               val %dirty = %changed
               val %dirty1 = %changed1
               val %dirty2 = %changed2
@@ -1085,7 +1093,8 @@
         """
             @Composable
             fun Example(a00: Int, a01: Int, a02: Int, a03: Int, a04: Int, a05: Int, a06: Int, a07: Int, a08: Int, a09: Foo?, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int, a18: Int, a19: Int, a20: Int, a21: Int, a22: Int, a23: Int, a24: Int, a25: Int, a26: Int, a27: Int, a28: Int, a29: Int, a30: Int, a31: Foo?, %composer: Composer?, %changed: Int, %changed1: Int, %changed2: Int, %changed3: Int, %default: Int, %default1: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               val %dirty = %changed
               val %dirty1 = %changed1
               val %dirty2 = %changed2
@@ -1419,7 +1428,8 @@
               @NonRestartableComposable
               @Composable
               fun foo(x: Int, %composer: Composer?, %changed: Int, %default: Int) {
-                %composer.startReplaceableGroup(<>, "C(foo):Test.kt")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "C(foo):Test.kt")
                 if (%default and 0b0001 !== 0) {
                   x = 0
                 }
@@ -1432,7 +1442,8 @@
               @NonRestartableComposable
               @Composable
               fun Example(%composer: Composer?, %changed: Int) {
-                %composer.startReplaceableGroup(<>, "C(Example)<foo()>:Test.kt")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "C(Example)<foo()>:Test.kt")
                 foo(0, %composer, 0b01110000 and %changed shl 0b0011, 0b0001)
                 %composer.endReplaceableGroup()
               }
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/FunctionBodySkippingTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/FunctionBodySkippingTransformTests.kt
index 44c68ac..de0dc0e 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/FunctionBodySkippingTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/FunctionBodySkippingTransformTests.kt
@@ -72,7 +72,8 @@
         """
             @Composable
             fun Test(x: Int, y: Int, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<Wrap>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<Wrap>:Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -92,14 +93,17 @@
                   y = 0
                 }
                 used(y)
-                Wrap(composableLambda(%composer, <>, true, "C:Test.kt") { %composer: Composer?, %changed: Int ->
+                Wrap(composableLambda(%composer, <>, true) { %composer: Composer?, %changed: Int ->
+                  sourceInformation(%composer, "C:Test.kt")
                   if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                     if (x > 0) {
-                      %composer.startReplaceableGroup(<>, "<A(x)>")
+                      %composer.startReplaceableGroup(<>)
+                      sourceInformation(%composer, "<A(x)>")
                       A(x, 0, %composer, 0b1110 and %dirty, 0b0010)
                       %composer.endReplaceableGroup()
                     } else {
-                      %composer.startReplaceableGroup(<>, "<A(x)>")
+                      %composer.startReplaceableGroup(<>)
+                      sourceInformation(%composer, "<A(x)>")
                       A(x, 0, %composer, 0b1110 and %dirty, 0b0010)
                       %composer.endReplaceableGroup()
                     }
@@ -136,7 +140,8 @@
               Example(class <no name provided> : A {
                 @Composable
                 override fun compute(it: Int, %composer: Composer?, %changed: Int) {
-                  %composer = %composer.startRestartGroup(<>, "C(compute)<comput...>:Test.kt")
+                  %composer = %composer.startRestartGroup(<>)
+                  sourceInformation(%composer, "C(compute)<comput...>:Test.kt")
                   val %dirty = %changed
                   if (%changed and 0b1110 === 0) {
                     %dirty = %dirty or if (%composer.changed(it)) 0b0100 else 0b0010
@@ -186,7 +191,8 @@
         """
             @Composable
             fun Button(colors: ButtonColors, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Button)<getCol...>,<Text("...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Button)<getCol...>,<Text("...>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(colors)) 0b0100 else 0b0010
@@ -202,12 +208,14 @@
             }
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<Button>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<Button>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 Button(class <no name provided> : ButtonColors {
                   @Composable
                   override fun getColor(%composer: Composer?, %changed: Int): Color {
-                    %composer.startReplaceableGroup(<>, "C(getColor)<condit...>:Test.kt")
+                    %composer.startReplaceableGroup(<>)
+                    sourceInformation(%composer, "C(getColor)<condit...>:Test.kt")
                     val tmp0 = if (condition(%composer, 0)) {
                       Companion.Red
                     } else {
@@ -308,7 +316,8 @@
         """
             @Composable
             fun RowColumnImpl(orientation: LayoutOrientation, modifier: Modifier?, arrangement: Vertical?, crossAxisAlignment: Horizontal?, crossAxisSize: SizeMode?, content: Function2<Composer, Int, Unit>, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(RowColumnImpl)P(5,4!1,2,3)<conten...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(RowColumnImpl)P(5,4!1,2,3)<conten...>:Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -376,7 +385,8 @@
             }
             @Composable
             fun Column(modifier: Modifier?, verticalArrangement: Vertical?, horizontalGravity: Horizontal?, content: Function2<Composer, Int, Unit>, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Column)P(2,3,1)<RowCol...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Column)P(2,3,1)<RowCol...>:Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -448,7 +458,8 @@
         """
             @Composable
             fun SimpleBox(modifier: Modifier?, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(SimpleBox):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(SimpleBox):Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -484,7 +495,8 @@
         """
             @Composable
             fun Example(a: Int, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%default and 0b0001 === 0 && %composer.changed(a)) 0b0100 else 0b0010
@@ -531,7 +543,8 @@
         """
             @Composable
             fun Example(a: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example)<Inner(...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example)<Inner(...>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(a)) 0b0100 else 0b0010
@@ -539,7 +552,8 @@
               if (%dirty and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                 @Composable
                 fun Inner(%composer: Composer?, %changed: Int) {
-                  %composer.startReplaceableGroup(<>, "C(Inner)<A(a)>:Test.kt")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "C(Inner)<A(a)>:Test.kt")
                   A(a, %composer, 0b1110 and %dirty)
                   %composer.endReplaceableGroup()
                 }
@@ -577,11 +591,13 @@
             @Composable
             @NonRestartableComposable
             fun Example(%composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(Example)<Call()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Example)<Call()>:Test.kt")
               Call(%composer, 0)
               val tmp0_iterator = 0 .. 1.iterator()
               while (tmp0_iterator.hasNext()) {
-                %composer.startReplaceableGroup(<>, "<Call()>,<Call()>")
+                %composer.startReplaceableGroup(<>)
+                sourceInformation(%composer, "<Call()>,<Call()>")
                 val index = tmp0_iterator.next()
                 Call(%composer, 0)
                 if (condition()) {
@@ -621,7 +637,8 @@
         """
             @Composable
             fun SimpleBox(modifier: Modifier?, shape: Shape?, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(SimpleBox):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(SimpleBox):Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -680,7 +697,8 @@
         """
             @Composable
             fun SimpleBox(modifier: Modifier?, content: Function2<Composer, Int, Unit>?, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(SimpleBox)P(1)<conten...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(SimpleBox)P(1)<conten...>:Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -717,7 +735,8 @@
               }
             }
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:Test.kt") { %composer: Composer?, %changed: Int ->
+              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   Unit
                 } else {
@@ -746,7 +765,8 @@
         """
             val foo: Function4<Int, Foo, Composer, Int, Unit> = ComposableSingletons%TestKt.lambda-1
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function4<Int, Foo, Composer, Int, Unit> = composableLambdaInstance(<>, false, "C<A(x)>,<B(y)>:") { x: Int, y: Foo, %composer: Composer?, %changed: Int ->
+              val lambda-1: Function4<Int, Foo, Composer, Int, Unit> = composableLambdaInstance(<>, false) { x: Int, y: Foo, %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C<A(x)>,<B(y)>:Test.kt")
                 val %dirty = %changed
                 if (%changed and 0b1110 === 0) {
                   %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -781,7 +801,8 @@
         """
             val foo: Function4<Int, Foo, Composer, Int, Unit> = ComposableSingletons%TestKt.lambda-1
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function4<Int, Foo, Composer, Int, Unit> = composableLambdaInstance(<>, false, "C<A(x)>,<B(y)>:") { x: Int, y: Foo, %composer: Composer?, %changed: Int ->
+              val lambda-1: Function4<Int, Foo, Composer, Int, Unit> = composableLambdaInstance(<>, false) { x: Int, y: Foo, %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C<A(x)>,<B(y)>:Test.kt")
                 A(x, %composer, 0b1110 and %changed)
                 B(y, %composer, 0b1000)
               }
@@ -806,7 +827,8 @@
         """
             @Composable
             fun SomeThing(content: Function2<Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(SomeThing)<conten...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(SomeThing)<conten...>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
@@ -822,7 +844,8 @@
             }
             @Composable
             fun Example(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example)<SomeTh...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example)<SomeTh...>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 SomeThing(ComposableSingletons%TestKt.lambda-1, %composer, 0)
               } else {
@@ -833,7 +856,8 @@
               }
             }
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:Test.kt") { %composer: Composer?, %changed: Int ->
+              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   val id = object
                 } else {
@@ -857,7 +881,8 @@
         """
             @Composable
             fun B(values: IntArray, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(B):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(B):Test.kt")
               val %dirty = %changed
               %composer.startReplaceableGroup(values.size)
               val tmp0_iterator = values.iterator()
@@ -896,7 +921,8 @@
         """
             @Composable
             fun B(values: Array<out Foo>, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(B):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(B):Test.kt")
               val %dirty = %changed
               %composer.startReplaceableGroup(values.size)
               val tmp0_iterator = values.iterator()
@@ -935,7 +961,8 @@
         """
             @Composable
             fun B(values: Array<out Foo>, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(B):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(B):Test.kt")
               print(values)
               %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
                 B(*values, %composer, %changed or 0b0001)
@@ -965,7 +992,8 @@
               var counter: Int = 0
               @Composable
               fun A(%composer: Composer?, %changed: Int) {
-                %composer = %composer.startRestartGroup(<>, "C(A):Test.kt")
+                %composer = %composer.startRestartGroup(<>)
+                sourceInformation(%composer, "C(A):Test.kt")
                 if (%changed and 0b0001 !== 0 || !%composer.skipping) {
                   print("hello world")
                 } else {
@@ -978,7 +1006,8 @@
               }
               @Composable
               fun B(%composer: Composer?, %changed: Int) {
-                %composer = %composer.startRestartGroup(<>, "C(B):Test.kt")
+                %composer = %composer.startRestartGroup(<>)
+                sourceInformation(%composer, "C(B):Test.kt")
                 print(counter)
                 val tmp0_rcvr = <this>
                 %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
@@ -1006,7 +1035,8 @@
         """
             @Composable
             fun Example(a: Int, b: Int, c: Int, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example)<makeIn...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example)<makeIn...>:Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -1075,7 +1105,8 @@
         """
             @Composable
             fun Wrap(y: Int, content: Function3<@[ParameterName(name = 'x')] Int, Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Wrap)P(1)<conten...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Wrap)P(1)<conten...>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(y)) 0b0100 else 0b0010
@@ -1094,7 +1125,8 @@
             }
             @Composable
             fun Test(x: Int, y: Int, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<Wrap(1...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<Wrap(1...>:Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -1114,7 +1146,8 @@
                   y = 0
                 }
                 used(y)
-                Wrap(10, composableLambda(%composer, <>, true, "C<A(x)>:Test.kt") { it: Int, %composer: Composer?, %changed: Int ->
+                Wrap(10, composableLambda(%composer, <>, true) { it: Int, %composer: Composer?, %changed: Int ->
+                  sourceInformation(%composer, "C<A(x)>:Test.kt")
                   val %dirty = %changed
                   if (%changed and 0b1110 === 0) {
                     %dirty = %dirty or if (%composer.changed(it)) 0b0100 else 0b0010
@@ -1151,7 +1184,8 @@
         """
             @Composable
             fun Test(x: Int, y: Int, %composer: Composer?, %changed: Int, %default: Int): Int {
-              %composer.startReplaceableGroup(<>, "C(Test)<A(x,>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Test)<A(x,>:Test.kt")
               if (%default and 0b0001 !== 0) {
                 x = 0
               }
@@ -1179,7 +1213,8 @@
         """
             val test: Function3<Int, Composer, Int, Unit> = ComposableSingletons%TestKt.lambda-1
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function3<Int, Composer, Int, Unit> = composableLambdaInstance(<>, false, "C<A(x)>:") { x: Int, %composer: Composer?, %changed: Int ->
+              val lambda-1: Function3<Int, Composer, Int, Unit> = composableLambdaInstance(<>, false) { x: Int, %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C<A(x)>:Test.kt")
                 val %dirty = %changed
                 if (%changed and 0b1110 === 0) {
                   %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -1205,7 +1240,8 @@
         """
             @Composable
             fun Test(x: Int, %composer: Composer?, %changed: Int): Int {
-              %composer.startReplaceableGroup(<>, "C(Test)<A()>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Test)<A()>:Test.kt")
               val tmp0 = A(0, 0, %composer, 0, 0b0011)
               %composer.endReplaceableGroup()
               return tmp0
@@ -1226,7 +1262,8 @@
         """
             @Composable
             fun Test(x: Int, y: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<A(y>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<A(y>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -1269,7 +1306,8 @@
         """
             @Composable
             fun CanSkip(a: Int, b: Foo?, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(CanSkip):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(CanSkip):Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -1308,7 +1346,8 @@
             }
             @Composable
             fun CannotSkip(a: Int, b: Foo, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(CannotSkip):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(CannotSkip):Test.kt")
               used(a)
               used(b)
               print("Hello World")
@@ -1318,7 +1357,8 @@
             }
             @Composable
             fun NoParams(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(NoParams):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(NoParams):Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 print("Hello World")
               } else {
@@ -1345,7 +1385,8 @@
         """
             @Composable
             fun Bar.CanSkip(b: Foo?, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(CanSkip):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(CanSkip):Test.kt")
               val %dirty = %changed
               if (%default.inv() and 0b0001 !== 0 || %dirty and 0b0001 !== 0 || !%composer.skipping) {
                 if (%changed and 0b0001 === 0 || %composer.defaultsInvalid) {
@@ -1387,7 +1428,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<A()>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<A()>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 A(%composer, 0)
               } else {
@@ -1414,7 +1456,8 @@
         """
             @Composable
             fun Test(x: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<A(x)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<A(x)>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -1455,7 +1498,8 @@
         """
             @Composable
             fun A(text: String, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A)<B(text...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A)<B(text...>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(text)) 0b0100 else 0b0010
@@ -1471,7 +1515,8 @@
             }
             @Composable
             fun B(text: String, color: Color, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(B)P(1,0:Color):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(B)P(1,0:Color):Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -1563,7 +1608,8 @@
         """
             @Composable
             fun A(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A)<D>,<C({})>,<C(stab...>,<C(16.d...>,<C(Dp(1...>,<C(16.d...>,<C(norm...>,<C(Int....>,<C(stab...>,<C(Modi...>,<C(Foo....>,<C(cons...>,<C(123)>,<C(123>,<C(x)>,<C(x>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A)<D>,<C({})>,<C(stab...>,<C(16.d...>,<C(Dp(1...>,<C(16.d...>,<C(norm...>,<C(Int....>,<C(stab...>,<C(Modi...>,<C(Foo....>,<C(cons...>,<C(123)>,<C(123>,<C(x)>,<C(x>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 val x = 123
                 D(ComposableSingletons%TestKt.lambda-1, %composer, 0)
@@ -1592,7 +1638,8 @@
             }
             @Composable
             fun B(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(B)<C(Math...>,<C(Math...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(B)<C(Math...>,<C(Math...>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 C(random(), %composer, 0)
                 C(random() / 100.0f, %composer, 0)
@@ -1604,7 +1651,8 @@
               }
             }
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:Test.kt") { %composer: Composer?, %changed: Int ->
+              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   Unit
                 } else {
@@ -1628,7 +1676,8 @@
         """
             @Composable
             fun Example(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example)<D>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example)<D>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 D(ComposableSingletons%TestKt.lambda-1, %composer, 0)
               } else {
@@ -1639,7 +1688,8 @@
               }
             }
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:Test.kt") { %composer: Composer?, %changed: Int ->
+              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   Unit
                 } else {
@@ -1664,7 +1714,8 @@
         """
             @Composable
             fun Test(x: Int, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<A(x)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<A(x)>:Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -1701,7 +1752,8 @@
         """
             @Composable
             fun Test(x: Int, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<I()>,<A(x)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<I()>,<A(x)>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%default and 0b0001 === 0 && %composer.changed(x)) 0b0100 else 0b0010
@@ -1746,7 +1798,8 @@
         """
             @Composable
             fun Test(x: Foo, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<A(x)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<A(x)>:Test.kt")
               A(x, %composer, 0b1000)
               %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
                 Test(x, %composer, %changed or 0b0001)
@@ -1770,7 +1823,8 @@
         """
             @Composable
             fun Test(x: Foo?, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<A(x)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<A(x)>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%default and 0b0001 === 0 && %composer.changed(x)) 0b0100 else 0b0010
@@ -1815,7 +1869,8 @@
         """
             @Composable
             fun Test(a: Int, b: Boolean, c: Int, d: Foo?, e: List<Int>?, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<A(a,>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<A(a,>:Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -1887,7 +1942,8 @@
         """
             @Composable
             fun X(x: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(X)<X(x>,<X(x)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(X)<X(x>,<X(x)>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -1948,7 +2004,8 @@
               itemsIndexed(items, ComposableSingletons%TestKt.lambda-1)
             }
             internal object ComposableSingletons%TestKt {
-              val lambda-1: @[ExtensionFunctionType] Function5<LazyItemScope, Int, User?, Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:Test.kt") { index: Int, user: User?, %composer: Composer?, %changed: Int ->
+              val lambda-1: @[ExtensionFunctionType] Function5<LazyItemScope, Int, User?, Composer, Int, Unit> = composableLambdaInstance(<>, false) { index: Int, user: User?, %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b0001010000000001 xor 0b010000000000 !== 0 || !%composer.skipping) {
                   print("Hello World")
                 } else {
@@ -1974,7 +2031,8 @@
         """
             @Composable
             fun Unstable.Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<doSome...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<doSome...>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(<this>)) 0b0100 else 0b0010
@@ -1990,7 +2048,8 @@
             }
             @Composable
             fun doSomething(x: Unstable, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(doSomething):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(doSomething):Test.kt")
               if (%changed and 0b0001 !== 0 || !%composer.skipping) {
               } else {
                 %composer.skipToGroupEnd()
@@ -2074,7 +2133,8 @@
         """
             @Composable
             fun A(x: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A)<B(>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A)<B(>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -2118,14 +2178,16 @@
             val stableUnused: @[ExtensionFunctionType] Function3<StableFoo, Composer, Int, Unit> = ComposableSingletons%TestKt.lambda-3
             val stableUsed: @[ExtensionFunctionType] Function3<StableFoo, Composer, Int, Unit> = ComposableSingletons%TestKt.lambda-4
             internal object ComposableSingletons%TestKt {
-              val lambda-1: @[ExtensionFunctionType] Function3<Foo, Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:") { %composer: Composer?, %changed: Int ->
+              val lambda-1: @[ExtensionFunctionType] Function3<Foo, Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b01010001 xor 0b00010000 !== 0 || !%composer.skipping) {
                   Unit
                 } else {
                   %composer.skipToGroupEnd()
                 }
               }
-              val lambda-2: @[ExtensionFunctionType] Function3<Foo, Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:") { %composer: Composer?, %changed: Int ->
+              val lambda-2: @[ExtensionFunctionType] Function3<Foo, Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 val %dirty = %changed
                 if (%changed and 0b1110 === 0) {
                   %dirty = %dirty or if (%composer.changed(%this%null)) 0b0100 else 0b0010
@@ -2136,14 +2198,16 @@
                   %composer.skipToGroupEnd()
                 }
               }
-              val lambda-3: @[ExtensionFunctionType] Function3<StableFoo, Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:") { %composer: Composer?, %changed: Int ->
+              val lambda-3: @[ExtensionFunctionType] Function3<StableFoo, Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b01010001 xor 0b00010000 !== 0 || !%composer.skipping) {
                   Unit
                 } else {
                   %composer.skipToGroupEnd()
                 }
               }
-              val lambda-4: @[ExtensionFunctionType] Function3<StableFoo, Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:") { %composer: Composer?, %changed: Int ->
+              val lambda-4: @[ExtensionFunctionType] Function3<StableFoo, Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 val %dirty = %changed
                 if (%changed and 0b1110 === 0) {
                   %dirty = %dirty or if (%composer.changed(%this%null)) 0b0100 else 0b0010
@@ -2179,19 +2243,22 @@
         """
             @Composable
             fun A(x: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A)<Provid...>,<B(x)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A)<Provid...>,<B(x)>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
               }
               if (%dirty and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
-                Provide(composableLambda(%composer, <>, true, "C<Provid...>,<B(x,>:Test.kt") { y: Int, %composer: Composer?, %changed: Int ->
+                Provide(composableLambda(%composer, <>, true) { y: Int, %composer: Composer?, %changed: Int ->
+                  sourceInformation(%composer, "C<Provid...>,<B(x,>:Test.kt")
                   val %dirty = %changed
                   if (%changed and 0b1110 === 0) {
                     %dirty = %dirty or if (%composer.changed(y)) 0b0100 else 0b0010
                   }
                   if (%dirty and 0b01011011 xor 0b00010010 !== 0 || !%composer.skipping) {
-                    Provide(composableLambda(%composer, <>, true, "C<B(x,>:Test.kt") { z: Int, %composer: Composer?, %changed: Int ->
+                    Provide(composableLambda(%composer, <>, true) { z: Int, %composer: Composer?, %changed: Int ->
+                      sourceInformation(%composer, "C<B(x,>:Test.kt")
                       val %dirty = %changed
                       if (%changed and 0b1110 === 0) {
                         %dirty = %dirty or if (%composer.changed(z)) 0b0100 else 0b0010
@@ -2235,7 +2302,8 @@
         """
             @Composable
             fun A(x: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A)<foo(x)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A)<foo(x)>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -2243,7 +2311,8 @@
               if (%dirty and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                 @Composable
                 fun foo(y: Int, %composer: Composer?, %changed: Int) {
-                  %composer.startReplaceableGroup(<>, "C(foo)<B(x,>:Test.kt")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "C(foo)<B(x,>:Test.kt")
                   B(x, y, %composer, 0b1110 and %dirty or 0b01110000 and %changed shl 0b0011)
                   %composer.endReplaceableGroup()
                 }
@@ -2322,7 +2391,8 @@
         """
             @Composable
             fun Example(a00: Int, a01: Int, a02: Int, a03: Int, a04: Int, a05: Int, a06: Int, a07: Int, a08: Int, a09: Int, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, %composer: Composer?, %changed: Int, %changed1: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example)<Exampl...>,<Exampl...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example)<Exampl...>,<Exampl...>:Test.kt")
               val %dirty = %changed
               val %dirty1 = %changed1
               if (%default and 0b0001 !== 0) {
@@ -2525,7 +2595,8 @@
         """
             @Composable
             fun Example(a00: Int, a01: Int, a02: Int, a03: Int, a04: Int, a05: Int, a06: Int, a07: Int, a08: Int, a09: Int, a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, %composer: Composer?, %changed: Int, %changed1: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example)<Exampl...>,<Exampl...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example)<Exampl...>,<Exampl...>:Test.kt")
               val %dirty = %changed
               val %dirty1 = %changed1
               if (%default and 0b0001 !== 0) {
@@ -2696,17 +2767,17 @@
               val current: Int
                 @Composable @ReadOnlyComposable @JvmName(name = "getCurrent")
                 get() {
-                  %composer.startReplaceableGroup(<>, "C:Test.kt")
+                  sourceInformationMarkerStart(%composer, <>, "C:Test.kt")
                   val tmp0 = %composer.hashCode()
-                  %composer.endReplaceableGroup()
+                  sourceInformationMarkerEnd(%composer)
                   return tmp0
                 }
               @ReadOnlyComposable
               @Composable
               fun getHashCode(%composer: Composer?, %changed: Int): Int {
-                %composer.startReplaceableGroup(<>, "C(getHashCode):Test.kt")
+                sourceInformationMarkerStart(%composer, <>, "C(getHashCode):Test.kt")
                 val tmp0 = %composer.hashCode()
-                %composer.endReplaceableGroup()
+                sourceInformationMarkerEnd(%composer)
                 return tmp0
               }
               static val %stable: Int = 0
@@ -2714,9 +2785,9 @@
             @ReadOnlyComposable
             @Composable
             fun getHashCode(%composer: Composer?, %changed: Int): Int {
-              %composer.startReplaceableGroup(<>, "C(getHashCode):Test.kt")
+              sourceInformationMarkerStart(%composer, <>, "C(getHashCode):Test.kt")
               val tmp0 = %composer.hashCode()
-              %composer.endReplaceableGroup()
+              sourceInformationMarkerEnd(%composer)
               return tmp0
             }
         """
@@ -2743,7 +2814,8 @@
         """
             @Composable
             fun Example(wontChange: Int, mightChange: Int, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example)P(1)<curren...>,<A(wont...>,<A(migh...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example)P(1)<curren...>,<A(wont...>,<A(migh...>:Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -2794,7 +2866,8 @@
         """
             @Composable
             fun Example(content: Function2<Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example)<invoke...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example)<invoke...>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
@@ -2854,7 +2927,8 @@
         """
             @Composable
             fun Box2(modifier: Modifier?, paddingStart: Dp, content: Function2<Composer, Int, Unit>?, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Box2)P(1,2:c#ui.unit.Dp)<conten...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Box2)P(1,2:c#ui.unit.Dp)<conten...>:Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -2902,7 +2976,8 @@
               }
             }
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:Test.kt") { %composer: Composer?, %changed: Int ->
+              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   Unit
                 } else {
@@ -2933,14 +3008,16 @@
         """
             @Composable
             fun Test(cond: Boolean, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(cond)) 0b0100 else 0b0010
               }
               if (%dirty and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                 if (cond) {
-                  %composer.startReplaceableGroup(<>, "<A()>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<A()>")
                   A(%composer, 0)
                   %composer.endReplaceableGroup()
                 } else {
@@ -2948,7 +3025,8 @@
                   %composer.endReplaceableGroup()
                 }
                 if (cond) {
-                  %composer.startReplaceableGroup(<>, "<B()>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<B()>")
                   B(%composer, 0)
                   %composer.endReplaceableGroup()
                 } else {
@@ -2991,7 +3069,8 @@
         """
             @Composable
             fun Unskippable(a: Unstable, b: Stable, c: MaybeStable, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Unskippable):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Unskippable):Test.kt")
               used(a)
               %composer.endRestartGroup()?.updateScope { %composer: Composer?, %force: Int ->
                 Unskippable(a, b, c, %composer, %changed or 0b0001)
@@ -2999,7 +3078,8 @@
             }
             @Composable
             fun Skippable1(a: Unstable, b: Stable, c: MaybeStable, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Skippable1):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Skippable1):Test.kt")
               val %dirty = %changed
               if (%changed and 0b01110000 === 0) {
                 %dirty = %dirty or if (%composer.changed(b)) 0b00100000 else 0b00010000
@@ -3015,7 +3095,8 @@
             }
             @Composable
             fun Skippable2(a: Unstable, b: Stable, c: MaybeStable, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Skippable2):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Skippable2):Test.kt")
               val %dirty = %changed
               if (%changed and 0b001110000000 === 0) {
                 %dirty = %dirty or if (%composer.changed(c)) 0b000100000000 else 0b10000000
@@ -3031,7 +3112,8 @@
             }
             @Composable
             fun Skippable3(a: Unstable, b: Stable, c: MaybeStable, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Skippable3):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Skippable3):Test.kt")
               if (%changed and 0b0001 !== 0 || !%composer.skipping) {
               } else {
                 %composer.skipToGroupEnd()
@@ -3061,7 +3143,8 @@
         """
             @Composable
             fun MaybeStable.example(x: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(example):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(example):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(<this>)) 0b0100 else 0b0010
@@ -3081,7 +3164,8 @@
             }
             val example: @[ExtensionFunctionType] Function4<MaybeStable, Int, Composer, Int, Unit> = ComposableSingletons%TestKt.lambda-1
             internal object ComposableSingletons%TestKt {
-              val lambda-1: @[ExtensionFunctionType] Function4<MaybeStable, Int, Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:") { it: Int, %composer: Composer?, %changed: Int ->
+              val lambda-1: @[ExtensionFunctionType] Function4<MaybeStable, Int, Composer, Int, Unit> = composableLambdaInstance(<>, false) { it: Int, %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 val %dirty = %changed
                 if (%changed and 0b1110 === 0) {
                   %dirty = %dirty or if (%composer.changed(%this%null)) 0b0100 else 0b0010
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/LambdaMemoizationTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/LambdaMemoizationTransformTests.kt
index 838f9bf..1946801 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/LambdaMemoizationTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/LambdaMemoizationTransformTests.kt
@@ -36,7 +36,8 @@
             @StabilityInferred(parameters = 0)
             class A {
               val b: String = ""
-              val c: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, true, "C:") { %composer: Composer?, %changed: Int ->
+              val c: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, true) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   print(b)
                 } else {
@@ -66,23 +67,28 @@
         """
             @Composable
             fun Example(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example):Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 @Composable
                 fun A(%composer: Composer?, %changed: Int) {
-                  %composer.startReplaceableGroup(<>, "C(A):Test.kt")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "C(A):Test.kt")
                   %composer.endReplaceableGroup()
                 }
                 @Composable
                 fun B(content: Function2<Composer, Int, Unit>, %composer: Composer?, %changed: Int) {
-                  %composer.startReplaceableGroup(<>, "C(B)<conten...>:Test.kt")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "C(B)<conten...>:Test.kt")
                   content(%composer, 0b1110 and %changed)
                   %composer.endReplaceableGroup()
                 }
                 @Composable
                 fun C(%composer: Composer?, %changed: Int) {
-                  %composer.startReplaceableGroup(<>, "C(C)<B>:Test.kt")
-                  B(composableLambda(%composer, <>, false, "C<A()>:Test.kt") { %composer: Composer?, %changed: Int ->
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "C(C)<B>:Test.kt")
+                  B(composableLambda(%composer, <>, false) { %composer: Composer?, %changed: Int ->
+                    sourceInformation(%composer, "C<A()>:Test.kt")
                     if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                       A(%composer, 0)
                     } else {
@@ -120,10 +126,12 @@
         """
             @Composable
             fun A(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A)<B>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A)<B>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 <<LOCALDELPROP>>
-                B(composableLambda(%composer, <>, true, "C:Test.kt") { %composer: Composer?, %changed: Int ->
+                B(composableLambda(%composer, <>, true) { %composer: Composer?, %changed: Int ->
+                  sourceInformation(%composer, "C:Test.kt")
                   if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                     print(<get-x>())
                   } else {
@@ -157,14 +165,16 @@
             val foo: Function2<Composer, Int, Unit> = ComposableSingletons%TestKt.lambda-1
             val bar: Function2<Composer, Int, Unit> = ComposableSingletons%TestKt.lambda-2
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:") { %composer: Composer?, %changed: Int ->
+              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   Unit
                 } else {
                   %composer.skipToGroupEnd()
                 }
               }
-              val lambda-2: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:") { %composer: Composer?, %changed: Int ->
+              val lambda-2: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   Unit
                 } else {
@@ -192,7 +202,8 @@
         """
             @Composable
             fun A(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A)<B(foo)>,<B(bar)>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A)<B(foo)>,<B(bar)>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 val foo = ComposableSingletons%TestKt.lambda-1
                 val bar = ComposableSingletons%TestKt.lambda-2
@@ -206,14 +217,16 @@
               }
             }
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:Test.kt") { %composer: Composer?, %changed: Int ->
+              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   Unit
                 } else {
                   %composer.skipToGroupEnd()
                 }
               }
-              val lambda-2: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:Test.kt") { %composer: Composer?, %changed: Int ->
+              val lambda-2: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   Unit
                 } else {
@@ -240,7 +253,8 @@
         """
             @Composable
             fun A(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(A)<B>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(A)<B>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 B(ComposableSingletons%TestKt.lambda-1, %composer, 0)
               } else {
@@ -251,7 +265,8 @@
               }
             }
             internal object ComposableSingletons%TestKt {
-              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false, "C:Test.kt") { %composer: Composer?, %changed: Int ->
+              val lambda-1: Function2<Composer, Int, Unit> = composableLambdaInstance(<>, false) { %composer: Composer?, %changed: Int ->
+                sourceInformation(%composer, "C:Test.kt")
                 if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                   Unit
                 } else {
@@ -282,7 +297,8 @@
         """
             @Composable
             fun Test(enabled: Boolean, content: Function2<Composer, Int, Unit>?, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)P(1)<Wrap(c...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)P(1)<Wrap(c...>:Test.kt")
               val %dirty = %changed
               if (%default and 0b0001 !== 0) {
                 %dirty = %dirty or 0b0110
@@ -296,7 +312,8 @@
               }
               if (%dirty and 0b01011011 xor 0b00010010 !== 0 || !%composer.skipping) {
                 if (%default and 0b0010 !== 0) {
-                  content = composableLambda(%composer, <>, true, "C<Displa...>:Test.kt") { %composer: Composer?, %changed: Int ->
+                  content = composableLambda(%composer, <>, true) { %composer: Composer?, %changed: Int ->
+                    sourceInformation(%composer, "C<Displa...>:Test.kt")
                     if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                       Display("%enabled", %composer, 0)
                     } else {
@@ -337,13 +354,15 @@
         """
             @Composable
             fun Test(enabled: Boolean, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<Wrap(c...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<Wrap(c...>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(enabled)) 0b0100 else 0b0010
               }
               if (%dirty and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
-                val content = composableLambda(%composer, <>, true, "C<Displa...>:Test.kt") { %composer: Composer?, %changed: Int ->
+                val content = composableLambda(%composer, <>, true) { %composer: Composer?, %changed: Int ->
+                  sourceInformation(%composer, "C<Displa...>:Test.kt")
                   if (%changed and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                     Display("%enabled", %composer, 0)
                   } else {
@@ -388,7 +407,8 @@
         """
         @Composable
         fun TestLambda(content: Function0<Unit>, %composer: Composer?, %changed: Int) {
-          %composer = %composer.startRestartGroup(<>, "C(TestLambda):Test.kt")
+          %composer = %composer.startRestartGroup(<>)
+          sourceInformation(%composer, "C(TestLambda):Test.kt")
           val %dirty = %changed
           if (%changed and 0b1110 === 0) {
             %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
@@ -404,7 +424,8 @@
         }
         @Composable
         fun Test(%composer: Composer?, %changed: Int) {
-          %composer = %composer.startRestartGroup(<>, "C(Test)<TestLa...>:Test.kt")
+          %composer = %composer.startRestartGroup(<>)
+          sourceInformation(%composer, "C(Test)<TestLa...>:Test.kt")
           if (%changed !== 0 || !%composer.skipping) {
             TestLambda({
               println("Doesn't capture")
@@ -440,7 +461,8 @@
         """
         @Composable
         fun TestLambda(content: Function0<Unit>, %composer: Composer?, %changed: Int) {
-          %composer = %composer.startRestartGroup(<>, "C(TestLambda):Test.kt")
+          %composer = %composer.startRestartGroup(<>)
+          sourceInformation(%composer, "C(TestLambda):Test.kt")
           val %dirty = %changed
           if (%changed and 0b1110 === 0) {
             %dirty = %dirty or if (%composer.changed(content)) 0b0100 else 0b0010
@@ -456,7 +478,8 @@
         }
         @Composable
         fun Test(a: String, %composer: Composer?, %changed: Int) {
-          %composer = %composer.startRestartGroup(<>, "C(Test)<{>,<TestLa...>:Test.kt")
+          %composer = %composer.startRestartGroup(<>)
+          sourceInformation(%composer, "C(Test)<{>,<TestLa...>:Test.kt")
           val %dirty = %changed
           if (%changed and 0b1110 === 0) {
             %dirty = %dirty or if (%composer.changed(a)) 0b0100 else 0b0010
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/RememberIntrinsicTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/RememberIntrinsicTransformTests.kt
index 51532ad..e0863c1 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/RememberIntrinsicTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/RememberIntrinsicTransformTests.kt
@@ -62,7 +62,8 @@
             @Composable
             @NonRestartableComposable
             fun app(x: Boolean, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(app)<rememb...>:Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(app)<rememb...>:Test.kt")
               val a = if (x) {
                 %composer.startReplaceableGroup(<>)
                 val tmp0_group = %composer.cache(false) {
@@ -105,7 +106,8 @@
         """
             @Composable
             fun <T> loadResourceInternal(key: String, pendingResource: T?, failedResource: T?, %composer: Composer?, %changed: Int, %default: Int): Boolean {
-              %composer.startReplaceableGroup(<>, "C(loadResourceInternal)P(1,2):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(loadResourceInternal)P(1,2):Test.kt")
               if (%default and 0b0010 !== 0) {
                 pendingResource = null
               }
@@ -147,7 +149,8 @@
         """
             @Composable
             fun test1(x: KnownStable, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(test1):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(test1):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -166,7 +169,8 @@
             }
             @Composable
             fun test2(x: KnownUnstable, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(test2):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(test2):Test.kt")
               %composer.cache(%composer.changed(x)) {
                 val tmp0_return = 1
                 tmp0_return
@@ -177,7 +181,8 @@
             }
             @Composable
             fun test3(x: Uncertain, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(test3):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(test3):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -227,7 +232,8 @@
             @Composable
             @NonRestartableComposable
             fun test1(x: KnownStable, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(test1):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(test1):Test.kt")
               %composer.cache(%changed and 0b1110 xor 0b0110 > 4 && %composer.changed(x) || %changed and 0b0110 === 0b0100) {
                 val tmp0_return = 1
                 tmp0_return
@@ -237,7 +243,8 @@
             @Composable
             @NonRestartableComposable
             fun test2(x: KnownUnstable, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(test2):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(test2):Test.kt")
               %composer.cache(%composer.changed(x)) {
                 val tmp0_return = 1
                 tmp0_return
@@ -247,7 +254,8 @@
             @Composable
             @NonRestartableComposable
             fun test3(x: Uncertain, %composer: Composer?, %changed: Int) {
-              %composer.startReplaceableGroup(<>, "C(test3):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(test3):Test.kt")
               %composer.cache(%changed and 0b1110 xor 0b0110 > 4 && %composer.changed(x) || %changed and 0b0110 === 0b0100) {
                 val tmp0_return = 1
                 tmp0_return
@@ -269,7 +277,8 @@
         """
             @Composable
             fun rememberFoo(a: Int, b: Int, %composer: Composer?, %changed: Int): Foo {
-              %composer.startReplaceableGroup(<>, "C(rememberFoo):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(rememberFoo):Test.kt")
               val tmp0 = %composer.cache(%changed and 0b1110 xor 0b0110 > 4 && %composer.changed(a) || %changed and 0b0110 === 0b0100 or %changed and 0b01110000 xor 0b00110000 > 32 && %composer.changed(b) || %changed and 0b00110000 === 0b00100000) {
                 val tmp0_return = Foo(a, b)
                 tmp0_return
@@ -298,7 +307,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<A()>,<rememb...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<A()>,<rememb...>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 val foo = %composer.cache(false) {
                   val tmp0_return = Foo()
@@ -340,7 +350,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test):Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 val a = someInt()
                 val b = someInt()
@@ -373,7 +384,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<CInt()...>,<rememb...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<CInt()...>,<rememb...>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 val foo = remember(CInt(%composer, 0), {
                   val tmp0_return = Foo()
@@ -408,7 +420,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<curren...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<curren...>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 val bar = compositionLocalBar.current
                 val foo = %composer.cache(%composer.changed(bar)) {
@@ -443,7 +456,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<curren...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<curren...>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 val foo = %composer.cache(%composer.changed(compositionLocalBar.current)) {
                   val tmp0_return = Foo()
@@ -475,7 +489,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<A()>,<rememb...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<A()>,<rememb...>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 A(%composer, 0)
                 val foo = remember({
@@ -510,7 +525,8 @@
         """
             @Composable
             fun Test(condition: Boolean, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<A()>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<A()>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(condition)) 0b0100 else 0b0010
@@ -556,14 +572,16 @@
         """
             @Composable
             fun Test(condition: Boolean, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(condition)) 0b0100 else 0b0010
               }
               if (%dirty and 0b1011 xor 0b0010 !== 0 || !%composer.skipping) {
                 if (condition) {
-                  %composer.startReplaceableGroup(<>, "<A()>,<rememb...>")
+                  %composer.startReplaceableGroup(<>)
+                  sourceInformation(%composer, "<A()>,<rememb...>")
                   A(%composer, 0)
                   val foo = remember({
                     val tmp0_return = Foo()
@@ -602,7 +620,8 @@
         """
             @Composable
             fun Test(items: List<Int>, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)*<rememb...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)*<rememb...>:Test.kt")
               val tmp0_iterator = items.iterator()
               while (tmp0_iterator.hasNext()) {
                 val item = tmp0_iterator.next()
@@ -640,7 +659,8 @@
         """
             @Composable
             fun Test(items: List<Int>, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)*<rememb...>,<A()>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)*<rememb...>,<A()>:Test.kt")
               val tmp0_iterator = items.iterator()
               while (tmp0_iterator.hasNext()) {
                 val item = tmp0_iterator.next()
@@ -674,7 +694,8 @@
         """
             @Composable
             fun Test(items: List<Int>, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test):Test.kt")
               val foo = %composer.cache(false) {
                 val tmp0_return = Foo()
                 tmp0_return
@@ -702,7 +723,8 @@
         """
             @Composable
             fun Test(a: Int, b: Int, c: Bar, d: Boolean, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(a)) 0b0100 else 0b0010
@@ -746,7 +768,8 @@
         """
             @Composable
             fun Test(items: Array<Bar>, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<rememb...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<rememb...>:Test.kt")
               val foo = remember(*items, {
                 val tmp0_return = Foo()
                 tmp0_return
@@ -774,7 +797,8 @@
         """
             @Composable
             fun Test(inlineInt: InlineInt, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)P(0:InlineInt):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)P(0:InlineInt):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(inlineInt.value)) 0b0100 else 0b0010
@@ -815,7 +839,8 @@
         """
             @Composable
             fun Test(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test):Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 val a = someInt()
                 val b = someInt()
@@ -855,7 +880,8 @@
         """
             @Composable
             fun Test(a: Int, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test):Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test):Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%composer.changed(a)) 0b0100 else 0b0010
@@ -892,7 +918,8 @@
         """
             @Composable
             fun Test(a: Int, %composer: Composer?, %changed: Int): Foo {
-              %composer.startReplaceableGroup(<>, "C(Test):Test.kt")
+              %composer.startReplaceableGroup(<>)
+              sourceInformation(%composer, "C(Test):Test.kt")
               val b = someInt()
               val tmp0 = %composer.cache(%changed and 0b1110 xor 0b0110 > 4 && %composer.changed(a) || %changed and 0b0110 === 0b0100 or %composer.changed(b)) {
                 val tmp0_return = Foo(a, b)
@@ -921,7 +948,8 @@
         """
             @Composable
             fun Test(a: Int, %composer: Composer?, %changed: Int, %default: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<rememb...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<rememb...>:Test.kt")
               val %dirty = %changed
               if (%changed and 0b1110 === 0) {
                 %dirty = %dirty or if (%default and 0b0001 === 0 && %composer.changed(a)) 0b0100 else 0b0010
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/StabilityPropagationTransformTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/StabilityPropagationTransformTests.kt
index b434332..a056dcd 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/StabilityPropagationTransformTests.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/StabilityPropagationTransformTests.kt
@@ -61,7 +61,8 @@
         """
         @Composable
         fun Test(x: Foo, %composer: Composer?, %changed: Int) {
-          %composer = %composer.startRestartGroup(<>, "C(Test)<A(x)>,<A(Foo(...>,<rememb...>,<A(reme...>:Test.kt")
+          %composer = %composer.startRestartGroup(<>)
+          sourceInformation(%composer, "C(Test)<A(x)>,<A(Foo(...>,<rememb...>,<A(reme...>:Test.kt")
           val %dirty = %changed
           if (%changed and 0b1110 === 0) {
             %dirty = %dirty or if (%composer.changed(x)) 0b0100 else 0b0010
@@ -102,7 +103,8 @@
         """
             @Composable
             fun Test(x: Foo, %composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Test)<A(x)>,<A(Foo(...>,<rememb...>,<A(reme...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Test)<A(x)>,<A(Foo(...>,<rememb...>,<A(reme...>:Test.kt")
               A(x, %composer, 0b1000)
               A(Foo(0), %composer, 0b1000)
               A(remember({
@@ -130,7 +132,8 @@
         """
             @Composable
             fun Example(%composer: Composer?, %changed: Int) {
-              %composer = %composer.startRestartGroup(<>, "C(Example)<A(list...>:Test.kt")
+              %composer = %composer.startRestartGroup(<>)
+              sourceInformation(%composer, "C(Example)<A(list...>:Test.kt")
               if (%changed !== 0 || !%composer.skipping) {
                 A(listOf("a"), %composer, 0)
               } else {
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/KtxNameConventions.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/KtxNameConventions.kt
index 4b9c724..4db291b 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/KtxNameConventions.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/KtxNameConventions.kt
@@ -12,4 +12,7 @@
     val STARTRESTARTGROUP = Name.identifier("startRestartGroup")
     val ENDRESTARTGROUP = Name.identifier("endRestartGroup")
     val UPDATE_SCOPE = Name.identifier("updateScope")
+    val SOURCEINFORMATION = "sourceInformation"
+    val SOURCEINFORMATIONMARKERSTART = "sourceInformationMarkerStart"
+    val SOURCEINFORMATIONMARKEREND = "sourceInformationMarkerEnd"
 }
\ No newline at end of file
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 56ec08a..c448eee 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
@@ -515,13 +515,6 @@
             }
     }
 
-    private val startReplaceableSourceFunction by guardedLazy {
-        composerIrClass.functions
-            .first {
-                it.name.identifier == "startReplaceableGroup" && it.valueParameters.size == 2
-            }
-    }
-
     private val endReplaceableFunction by guardedLazy {
         composerIrClass.functions
             .first {
@@ -550,13 +543,6 @@
             }
     }
 
-    private val startMovableSourceFunction by guardedLazy {
-        composerIrClass.functions
-            .first {
-                it.name.identifier == "startMovableGroup" && it.valueParameters.size == 3
-            }
-    }
-
     private val endMovableFunction by guardedLazy {
         composerIrClass.functions
             .first {
@@ -572,13 +558,6 @@
             }
     }
 
-    private val startRestartGroupSourceFunction by guardedLazy {
-        composerIrClass.functions
-            .first {
-                it.name == KtxNameConventions.STARTRESTARTGROUP && it.valueParameters.size == 2
-            }
-    }
-
     private val endRestartGroupFunction by guardedLazy {
         composerIrClass
             .functions
@@ -587,6 +566,24 @@
             }
     }
 
+    private val sourceInformationFunction by guardedLazy {
+        getTopLevelFunctions(
+            ComposeFqNames.fqNameFor(KtxNameConventions.SOURCEINFORMATION)
+        ).map { it.owner }.first()
+    }
+
+    private val sourceInformationMarkerStartFunction by guardedLazy {
+        getTopLevelFunctions(
+            ComposeFqNames.fqNameFor(KtxNameConventions.SOURCEINFORMATIONMARKERSTART)
+        ).map { it.owner }.first()
+    }
+
+    private val sourceInformationMarkerEndFunction by guardedLazy {
+        getTopLevelFunctions(
+            ComposeFqNames.fqNameFor(KtxNameConventions.SOURCEINFORMATIONMARKEREND)
+        ).map { it.owner }.first()
+    }
+
     private val IrType.arguments: List<IrTypeArgument>
         get() = (this as? IrSimpleType)?.arguments.orEmpty()
 
@@ -768,7 +765,7 @@
 
     @OptIn(ObsoleteDescriptorBasedAPI::class)
     private fun IrFunction.shouldElideGroups(): Boolean {
-        return (!collectSourceInformation && descriptor.hasReadonlyComposableAnnotation()) ||
+        return descriptor.hasReadonlyComposableAnnotation() ||
             descriptor.hasExplicitGroupsAnnotation()
     }
 
@@ -822,17 +819,31 @@
             body.startOffset,
             body.endOffset,
             listOfNotNull(
-                if (!elideGroups)
-                    irStartReplaceableGroup(
-                        body,
-                        scope,
-                        declaration.irSourceKey()
-                    )
-                else
-                    null,
+                when {
+                    !elideGroups ->
+                        irStartReplaceableGroup(
+                            body,
+                            scope,
+                            declaration.irSourceKey()
+                        )
+                    collectSourceInformation &&
+                        !declaration.descriptor.hasExplicitGroupsAnnotation() ->
+                        irSourceInformationMarkerStart(
+                            body,
+                            scope,
+                            declaration.irSourceKey()
+                        )
+                    else -> null
+                },
                 *bodyPreamble.statements.toTypedArray(),
                 *transformed.statements.toTypedArray(),
-                if (!elideGroups) irEndReplaceableGroup() else null,
+                when {
+                    !elideGroups -> irEndReplaceableGroup()
+                    collectSourceInformation &&
+                        !declaration.descriptor.hasExplicitGroupsAnnotation() ->
+                        irSourceInformationMarkerEnd(body)
+                    else -> null
+                },
                 returnVar?.let { irReturn(declaration.symbol, irGet(it)) }
             )
         )
@@ -855,9 +866,15 @@
         // no group, since composableLambda should already create one
         // no default logic
         val body = declaration.body!!
+        val sourceInformationPreamble = mutableStatementContainer()
         val skipPreamble = mutableStatementContainer()
         val bodyPreamble = mutableStatementContainer()
 
+        // First generate the source information call
+        if (collectSourceInformation && !scope.isInlinedLambda) {
+            sourceInformationPreamble.statements.add(irSourceInformation(scope))
+        }
+
         // we start off assuming that we *can* skip execution of the function
         var canSkipExecution = declaration.returnType.isUnit() &&
             scope.allTrackedParams.none { stabilityOf(it.type).knownUnstable() }
@@ -927,6 +944,7 @@
                     if (collectSourceInformation && scope.isInlinedLambda)
                         irStartReplaceableGroup(body, scope)
                     else null,
+                    *sourceInformationPreamble.statements.toTypedArray(),
                     *skipPreamble.statements.toTypedArray(),
                     *bodyPreamble.statements.toTypedArray(),
                     transformedBody,
@@ -941,6 +959,7 @@
                 body.startOffset,
                 body.endOffset,
                 listOfNotNull(
+                    *sourceInformationPreamble.statements.toTypedArray(),
                     *skipPreamble.statements.toTypedArray(),
                     *bodyPreamble.statements.toTypedArray(),
                     transformed,
@@ -1740,16 +1759,61 @@
         scope: Scope.BlockScope,
         key: IrExpression = element.irSourceKey()
     ): IrExpression {
-        val startDescriptor = if (scope.hasSourceInformation)
-            startReplaceableSourceFunction else startReplaceableFunction
-        return irMethodCall(
-            irCurrentComposer(),
-            startDescriptor
+        return irWithSourceInformation(
+            irMethodCall(
+                irCurrentComposer(),
+                startReplaceableFunction
+            ).also {
+                it.putValueArgument(0, key)
+            },
+            scope
+        )
+    }
+
+    private fun irWithSourceInformation(
+        startGroup: IrExpression,
+        scope: Scope.BlockScope
+    ): IrExpression {
+        return if (scope.hasSourceInformation) {
+            irBlock(statements = listOf(startGroup, irSourceInformation(scope)))
+        } else startGroup
+    }
+
+    private fun irSourceInformation(scope: Scope.BlockScope): IrExpression {
+        val sourceInformation = irCall(
+            sourceInformationFunction
         ).also {
-            it.putValueArgument(0, key)
-            if (scope.hasSourceInformation) {
-                recordSourceParameter(it, 1, scope)
-            }
+            it.putValueArgument(0, irCurrentComposer())
+        }
+        recordSourceParameter(sourceInformation, 1, scope)
+        return sourceInformation
+    }
+
+    private fun irSourceInformationMarkerStart(
+        element: IrElement,
+        scope: Scope.BlockScope,
+        key: IrExpression = element.irSourceKey(),
+    ): IrExpression {
+        return irCall(
+            sourceInformationMarkerStartFunction,
+            element.startOffset,
+            element.endOffset
+        ).also {
+            it.putValueArgument(0, irCurrentComposer())
+            it.putValueArgument(1, key)
+            recordSourceParameter(it, 2, scope)
+        }
+    }
+
+    private fun irSourceInformationMarkerEnd(
+        element: IrElement,
+    ): IrExpression {
+        return irCall(
+            sourceInformationMarkerEndFunction,
+            element.startOffset,
+            element.endOffset
+        ).also {
+            it.putValueArgument(0, irCurrentComposer())
         }
     }
 
@@ -1767,21 +1831,19 @@
         scope: Scope.BlockScope,
         key: IrExpression = element.irSourceKey()
     ): IrExpression {
-        val startDescriptor = if (scope.hasSourceInformation)
-            startRestartGroupSourceFunction else startRestartGroupFunction
-        return irSet(
-            nearestComposer(),
-            irMethodCall(
-                irCurrentComposer(),
-                startDescriptor,
-                element.startOffset,
-                element.endOffset
-            ).also {
-                it.putValueArgument(0, key)
-                if (scope.hasSourceInformation) {
-                    recordSourceParameter(it, 1, scope)
+        return irWithSourceInformation(
+            irSet(
+                nearestComposer(),
+                irMethodCall(
+                    irCurrentComposer(),
+                    startRestartGroupFunction,
+                    element.startOffset,
+                    element.endOffset
+                ).also {
+                    it.putValueArgument(0, key)
                 }
-            }
+            ),
+            scope
         )
     }
 
@@ -1854,23 +1916,18 @@
         joinedData: IrExpression,
         scope: Scope.BlockScope
     ): IrExpression {
-        val startFunction = if (scope.hasSourceInformation) {
-            startMovableSourceFunction
-        } else {
-            startMovableFunction
-        }
-        return irMethodCall(
-            irCurrentComposer(),
-            startFunction,
-            element.startOffset,
-            element.endOffset
-        ).also {
-            it.putValueArgument(0, element.irSourceKey())
-            it.putValueArgument(1, joinedData)
-            if (scope.hasSourceInformation) {
-                recordSourceParameter(it, 2, scope)
-            }
-        }
+        return irWithSourceInformation(
+            irMethodCall(
+                irCurrentComposer(),
+                startMovableFunction,
+                element.startOffset,
+                element.endOffset
+            ).also {
+                it.putValueArgument(0, element.irSourceKey())
+                it.putValueArgument(1, joinedData)
+            },
+            scope
+        )
     }
 
     private fun irEndMovableGroup(): IrExpression {
@@ -2372,17 +2429,6 @@
                     expression
                 }
             }
-            collectSourceInformation &&
-                expression.symbol.descriptor.fqNameSafe == ComposeFqNames.composableLambda -> {
-                // For calls to `composableLambda` we introduce a scope to collect the source
-                // locations on the top level of the lambda as the startRestartGroup is in the
-                // composable lambda wrapper.
-                val composableLambdaScope = withScope(Scope.ComposableLambdaScope()) {
-                    expression.transformChildrenVoid()
-                }
-                recordSourceParameter(expression, 3, composableLambdaScope)
-                return expression
-            }
             expression.isComposableSingletonGetter() -> {
                 // This looks like `ComposableSingletonClass.lambda-123`, which is a static/saved
                 // call of composableLambdaInstance. We want to transform the property here now
@@ -2393,18 +2439,6 @@
                 property?.transformChildrenVoid()
                 return super.visitCall(expression)
             }
-            collectSourceInformation &&
-                expression.symbol.descriptor.fqNameSafe ==
-                ComposeFqNames.composableLambdaInstance -> {
-                // For calls to `composableLambdaInstance` that are not singletons we introduce a
-                // scope to collect the source locations on the top level of the lambda as the
-                // startRestartGroup is in the composable lambda wrapper.
-                val composableLambdaScope = withScope(Scope.ComposableLambdaScope()) {
-                    expression.transformChildrenVoid()
-                }
-                recordSourceParameter(expression, 2, composableLambdaScope)
-                return expression
-            }
             else -> return super.visitCall(expression)
         }
     }
@@ -3329,13 +3363,9 @@
 
             override fun calculateSourceInfo(sourceInformationEnabled: Boolean): String? =
                 if (sourceInformationEnabled) {
-                    if (function.isLambda() && !isInlinedLambda) {
-                        super.calculateSourceInfo(sourceInformationEnabled)
-                    } else {
-                        "${callInformation()}${parameterInformation()}${
-                        super.calculateSourceInfo(sourceInformationEnabled) ?: ""
-                        }:${sourceFileInformation()}"
-                    }
+                    "${callInformation()}${parameterInformation()}${
+                    super.calculateSourceInfo(sourceInformationEnabled) ?: ""
+                    }:${sourceFileInformation()}"
                 } else {
                     if (function.visibility.isPublicAPI) {
                         "${callInformation()}${parameterInformation()}"
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 0bc3dcc..131e734 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
@@ -48,7 +48,6 @@
 import org.jetbrains.kotlin.ir.builders.irGet
 import org.jetbrains.kotlin.ir.builders.irGetField
 import org.jetbrains.kotlin.ir.builders.irInt
-import org.jetbrains.kotlin.ir.builders.irNull
 import org.jetbrains.kotlin.ir.builders.irReturn
 import org.jetbrains.kotlin.ir.builders.irTemporary
 import org.jetbrains.kotlin.ir.declarations.IrAttributeContainer
@@ -687,9 +686,6 @@
             val shouldBeTracked = collector.captures.isNotEmpty()
             putValueArgument(index++, irBuilder.irBoolean(shouldBeTracked))
 
-            // sourceInformation parameter
-            putValueArgument(index++, irBuilder.irNull())
-
             // ComposableLambdaN requires the arity
             if (useComposableLambdaN) {
                 // arity parameter
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/lazy/Lazy.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/lazy/Lazy.desktop.kt
index fbdcda7..20e25b8 100644
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/lazy/Lazy.desktop.kt
+++ b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/lazy/Lazy.desktop.kt
@@ -16,6 +16,10 @@
 
 package androidx.compose.foundation.lazy
 
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
+import androidx.compose.ui.layout.SubcomposeLayoutState
+
 internal actual fun getDefaultLazyKeyFor(index: Int): Any = DefaultLazyKey(index)
 
 private data class DefaultLazyKey(private val index: Int)
diff --git a/compose/runtime/runtime/api/1.0.0-beta07.txt b/compose/runtime/runtime/api/1.0.0-beta07.txt
index e6427f7..6b7c331 100644
--- a/compose/runtime/runtime/api/1.0.0-beta07.txt
+++ b/compose/runtime/runtime/api/1.0.0-beta07.txt
@@ -108,14 +108,14 @@
     method @androidx.compose.runtime.ComposeCompilerApi public Object? rememberedValue();
     method @androidx.compose.runtime.ComposeCompilerApi public void skipCurrentGroup();
     method @androidx.compose.runtime.ComposeCompilerApi public void skipToGroupEnd();
+    method public void sourceInformation(String sourceInformation);
+    method public void sourceInformationMarkerEnd();
+    method public void sourceInformationMarkerStart(int key, String sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startDefaults();
     method @androidx.compose.runtime.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
-    method @androidx.compose.runtime.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startNode();
     method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key);
-    method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.Composer startRestartGroup(int key);
-    method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.Composer startRestartGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReusableGroup(int key, Object? dataKey);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReusableNode();
     method @androidx.compose.runtime.ComposeCompilerApi public void updateRememberedValue(Object? value);
@@ -139,6 +139,9 @@
 
   public final class ComposerKt {
     method @androidx.compose.runtime.ComposeCompilerApi public static inline <T> T! cache(androidx.compose.runtime.Composer, boolean invalid, kotlin.jvm.functions.Function0<? extends T> block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformation(androidx.compose.runtime.Composer composer, String sourceInformation);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformationMarkerEnd(androidx.compose.runtime.Composer composer);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformationMarkerStart(androidx.compose.runtime.Composer composer, int key, String sourceInformation);
   }
 
   public interface Composition {
@@ -498,16 +501,16 @@
   }
 
   public final class ComposableLambdaKt {
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambda(androidx.compose.runtime.Composer composer, int key, boolean tracked, String? sourceInformation, Object block);
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambdaInstance(int key, boolean tracked, String? sourceInformation, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambda(androidx.compose.runtime.Composer composer, int key, boolean tracked, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambdaInstance(int key, boolean tracked, Object block);
   }
 
   @androidx.compose.runtime.ComposeCompilerApi @androidx.compose.runtime.Stable public interface ComposableLambdaN extends kotlin.jvm.functions.FunctionN<java.lang.Object> {
   }
 
   public final class ComposableLambdaN_jvmKt {
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaN(androidx.compose.runtime.Composer composer, int key, boolean tracked, String? sourceInformation, int arity, Object block);
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaNInstance(int key, boolean tracked, String? sourceInformation, int arity, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaN(androidx.compose.runtime.Composer composer, int key, boolean tracked, int arity, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
   }
 
   public final class DecoyKt {
diff --git a/compose/runtime/runtime/api/current.ignore b/compose/runtime/runtime/api/current.ignore
index 3676e75..87dd33f 100644
--- a/compose/runtime/runtime/api/current.ignore
+++ b/compose/runtime/runtime/api/current.ignore
@@ -5,7 +5,29 @@
     Added method androidx.compose.runtime.Composer.enableReusing()
 AddedAbstractMethod: androidx.compose.runtime.Composer#endReusableGroup():
     Added method androidx.compose.runtime.Composer.endReusableGroup()
+AddedAbstractMethod: androidx.compose.runtime.Composer#sourceInformation(String):
+    Added method androidx.compose.runtime.Composer.sourceInformation(String)
+AddedAbstractMethod: androidx.compose.runtime.Composer#sourceInformationMarkerEnd():
+    Added method androidx.compose.runtime.Composer.sourceInformationMarkerEnd()
+AddedAbstractMethod: androidx.compose.runtime.Composer#sourceInformationMarkerStart(int, String):
+    Added method androidx.compose.runtime.Composer.sourceInformationMarkerStart(int,String)
 AddedAbstractMethod: androidx.compose.runtime.Composer#startReusableGroup(int, Object):
     Added method androidx.compose.runtime.Composer.startReusableGroup(int,Object)
 AddedAbstractMethod: androidx.compose.runtime.Composer#startReusableNode():
     Added method androidx.compose.runtime.Composer.startReusableNode()
+
+
+RemovedMethod: androidx.compose.runtime.Composer#startMovableGroup(int, Object, String):
+    Removed method androidx.compose.runtime.Composer.startMovableGroup(int,Object,String)
+RemovedMethod: androidx.compose.runtime.Composer#startReplaceableGroup(int, String):
+    Removed method androidx.compose.runtime.Composer.startReplaceableGroup(int,String)
+RemovedMethod: androidx.compose.runtime.Composer#startRestartGroup(int, String):
+    Removed method androidx.compose.runtime.Composer.startRestartGroup(int,String)
+RemovedMethod: androidx.compose.runtime.internal.ComposableLambdaKt#composableLambda(androidx.compose.runtime.Composer, int, boolean, String, Object):
+    Removed method androidx.compose.runtime.internal.ComposableLambdaKt.composableLambda(androidx.compose.runtime.Composer,int,boolean,String,Object)
+RemovedMethod: androidx.compose.runtime.internal.ComposableLambdaKt#composableLambdaInstance(int, boolean, String, Object):
+    Removed method androidx.compose.runtime.internal.ComposableLambdaKt.composableLambdaInstance(int,boolean,String,Object)
+RemovedMethod: androidx.compose.runtime.internal.ComposableLambdaN_jvmKt#composableLambdaN(androidx.compose.runtime.Composer, int, boolean, String, int, Object):
+    Removed method androidx.compose.runtime.internal.ComposableLambdaN_jvmKt.composableLambdaN(androidx.compose.runtime.Composer,int,boolean,String,int,Object)
+RemovedMethod: androidx.compose.runtime.internal.ComposableLambdaN_jvmKt#composableLambdaNInstance(int, boolean, String, int, Object):
+    Removed method androidx.compose.runtime.internal.ComposableLambdaN_jvmKt.composableLambdaNInstance(int,boolean,String,int,Object)
diff --git a/compose/runtime/runtime/api/current.txt b/compose/runtime/runtime/api/current.txt
index e6427f7..6b7c331 100644
--- a/compose/runtime/runtime/api/current.txt
+++ b/compose/runtime/runtime/api/current.txt
@@ -108,14 +108,14 @@
     method @androidx.compose.runtime.ComposeCompilerApi public Object? rememberedValue();
     method @androidx.compose.runtime.ComposeCompilerApi public void skipCurrentGroup();
     method @androidx.compose.runtime.ComposeCompilerApi public void skipToGroupEnd();
+    method public void sourceInformation(String sourceInformation);
+    method public void sourceInformationMarkerEnd();
+    method public void sourceInformationMarkerStart(int key, String sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startDefaults();
     method @androidx.compose.runtime.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
-    method @androidx.compose.runtime.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startNode();
     method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key);
-    method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.Composer startRestartGroup(int key);
-    method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.Composer startRestartGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReusableGroup(int key, Object? dataKey);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReusableNode();
     method @androidx.compose.runtime.ComposeCompilerApi public void updateRememberedValue(Object? value);
@@ -139,6 +139,9 @@
 
   public final class ComposerKt {
     method @androidx.compose.runtime.ComposeCompilerApi public static inline <T> T! cache(androidx.compose.runtime.Composer, boolean invalid, kotlin.jvm.functions.Function0<? extends T> block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformation(androidx.compose.runtime.Composer composer, String sourceInformation);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformationMarkerEnd(androidx.compose.runtime.Composer composer);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformationMarkerStart(androidx.compose.runtime.Composer composer, int key, String sourceInformation);
   }
 
   public interface Composition {
@@ -498,16 +501,16 @@
   }
 
   public final class ComposableLambdaKt {
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambda(androidx.compose.runtime.Composer composer, int key, boolean tracked, String? sourceInformation, Object block);
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambdaInstance(int key, boolean tracked, String? sourceInformation, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambda(androidx.compose.runtime.Composer composer, int key, boolean tracked, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambdaInstance(int key, boolean tracked, Object block);
   }
 
   @androidx.compose.runtime.ComposeCompilerApi @androidx.compose.runtime.Stable public interface ComposableLambdaN extends kotlin.jvm.functions.FunctionN<java.lang.Object> {
   }
 
   public final class ComposableLambdaN_jvmKt {
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaN(androidx.compose.runtime.Composer composer, int key, boolean tracked, String? sourceInformation, int arity, Object block);
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaNInstance(int key, boolean tracked, String? sourceInformation, int arity, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaN(androidx.compose.runtime.Composer composer, int key, boolean tracked, int arity, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
   }
 
   public final class DecoyKt {
diff --git a/compose/runtime/runtime/api/public_plus_experimental_1.0.0-beta07.txt b/compose/runtime/runtime/api/public_plus_experimental_1.0.0-beta07.txt
index dc2cc91..3cbeb22 100644
--- a/compose/runtime/runtime/api/public_plus_experimental_1.0.0-beta07.txt
+++ b/compose/runtime/runtime/api/public_plus_experimental_1.0.0-beta07.txt
@@ -114,15 +114,15 @@
     method @androidx.compose.runtime.ComposeCompilerApi public Object? rememberedValue();
     method @androidx.compose.runtime.ComposeCompilerApi public void skipCurrentGroup();
     method @androidx.compose.runtime.ComposeCompilerApi public void skipToGroupEnd();
+    method public void sourceInformation(String sourceInformation);
+    method public void sourceInformationMarkerEnd();
+    method public void sourceInformationMarkerStart(int key, String sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startDefaults();
     method @androidx.compose.runtime.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
-    method @androidx.compose.runtime.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startNode();
     method @androidx.compose.runtime.InternalComposeApi public void startProviders(androidx.compose.runtime.ProvidedValue<?>![] values);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key);
-    method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.Composer startRestartGroup(int key);
-    method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.Composer startRestartGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReusableGroup(int key, Object? dataKey);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReusableNode();
     method @androidx.compose.runtime.ComposeCompilerApi public void updateRememberedValue(Object? value);
@@ -146,6 +146,9 @@
 
   public final class ComposerKt {
     method @androidx.compose.runtime.ComposeCompilerApi public static inline <T> T! cache(androidx.compose.runtime.Composer, boolean invalid, kotlin.jvm.functions.Function0<? extends T> block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformation(androidx.compose.runtime.Composer composer, String sourceInformation);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformationMarkerEnd(androidx.compose.runtime.Composer composer);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformationMarkerStart(androidx.compose.runtime.Composer composer, int key, String sourceInformation);
   }
 
   public interface Composition {
@@ -516,16 +519,16 @@
   }
 
   public final class ComposableLambdaKt {
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambda(androidx.compose.runtime.Composer composer, int key, boolean tracked, String? sourceInformation, Object block);
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambdaInstance(int key, boolean tracked, String? sourceInformation, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambda(androidx.compose.runtime.Composer composer, int key, boolean tracked, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambdaInstance(int key, boolean tracked, Object block);
   }
 
   @androidx.compose.runtime.ComposeCompilerApi @androidx.compose.runtime.Stable public interface ComposableLambdaN extends kotlin.jvm.functions.FunctionN<java.lang.Object> {
   }
 
   public final class ComposableLambdaN_jvmKt {
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaN(androidx.compose.runtime.Composer composer, int key, boolean tracked, String? sourceInformation, int arity, Object block);
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaNInstance(int key, boolean tracked, String? sourceInformation, int arity, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaN(androidx.compose.runtime.Composer composer, int key, boolean tracked, int arity, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
   }
 
   @androidx.compose.runtime.ExperimentalComposeApi @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget}) public @interface Decoy {
diff --git a/compose/runtime/runtime/api/public_plus_experimental_current.txt b/compose/runtime/runtime/api/public_plus_experimental_current.txt
index dc2cc91..3cbeb22 100644
--- a/compose/runtime/runtime/api/public_plus_experimental_current.txt
+++ b/compose/runtime/runtime/api/public_plus_experimental_current.txt
@@ -114,15 +114,15 @@
     method @androidx.compose.runtime.ComposeCompilerApi public Object? rememberedValue();
     method @androidx.compose.runtime.ComposeCompilerApi public void skipCurrentGroup();
     method @androidx.compose.runtime.ComposeCompilerApi public void skipToGroupEnd();
+    method public void sourceInformation(String sourceInformation);
+    method public void sourceInformationMarkerEnd();
+    method public void sourceInformationMarkerStart(int key, String sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startDefaults();
     method @androidx.compose.runtime.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
-    method @androidx.compose.runtime.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startNode();
     method @androidx.compose.runtime.InternalComposeApi public void startProviders(androidx.compose.runtime.ProvidedValue<?>![] values);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key);
-    method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.Composer startRestartGroup(int key);
-    method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.Composer startRestartGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReusableGroup(int key, Object? dataKey);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReusableNode();
     method @androidx.compose.runtime.ComposeCompilerApi public void updateRememberedValue(Object? value);
@@ -146,6 +146,9 @@
 
   public final class ComposerKt {
     method @androidx.compose.runtime.ComposeCompilerApi public static inline <T> T! cache(androidx.compose.runtime.Composer, boolean invalid, kotlin.jvm.functions.Function0<? extends T> block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformation(androidx.compose.runtime.Composer composer, String sourceInformation);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformationMarkerEnd(androidx.compose.runtime.Composer composer);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformationMarkerStart(androidx.compose.runtime.Composer composer, int key, String sourceInformation);
   }
 
   public interface Composition {
@@ -516,16 +519,16 @@
   }
 
   public final class ComposableLambdaKt {
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambda(androidx.compose.runtime.Composer composer, int key, boolean tracked, String? sourceInformation, Object block);
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambdaInstance(int key, boolean tracked, String? sourceInformation, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambda(androidx.compose.runtime.Composer composer, int key, boolean tracked, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambdaInstance(int key, boolean tracked, Object block);
   }
 
   @androidx.compose.runtime.ComposeCompilerApi @androidx.compose.runtime.Stable public interface ComposableLambdaN extends kotlin.jvm.functions.FunctionN<java.lang.Object> {
   }
 
   public final class ComposableLambdaN_jvmKt {
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaN(androidx.compose.runtime.Composer composer, int key, boolean tracked, String? sourceInformation, int arity, Object block);
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaNInstance(int key, boolean tracked, String? sourceInformation, int arity, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaN(androidx.compose.runtime.Composer composer, int key, boolean tracked, int arity, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
   }
 
   @androidx.compose.runtime.ExperimentalComposeApi @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget, kotlin.annotation.AnnotationTarget}) public @interface Decoy {
diff --git a/compose/runtime/runtime/api/restricted_1.0.0-beta07.txt b/compose/runtime/runtime/api/restricted_1.0.0-beta07.txt
index 5dbea01..2cd34c5 100644
--- a/compose/runtime/runtime/api/restricted_1.0.0-beta07.txt
+++ b/compose/runtime/runtime/api/restricted_1.0.0-beta07.txt
@@ -110,14 +110,14 @@
     method @androidx.compose.runtime.ComposeCompilerApi public Object? rememberedValue();
     method @androidx.compose.runtime.ComposeCompilerApi public void skipCurrentGroup();
     method @androidx.compose.runtime.ComposeCompilerApi public void skipToGroupEnd();
+    method public void sourceInformation(String sourceInformation);
+    method public void sourceInformationMarkerEnd();
+    method public void sourceInformationMarkerStart(int key, String sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startDefaults();
     method @androidx.compose.runtime.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
-    method @androidx.compose.runtime.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startNode();
     method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key);
-    method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.Composer startRestartGroup(int key);
-    method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.Composer startRestartGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReusableGroup(int key, Object? dataKey);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReusableNode();
     method @androidx.compose.runtime.ComposeCompilerApi public void updateRememberedValue(Object? value);
@@ -141,6 +141,9 @@
 
   public final class ComposerKt {
     method @androidx.compose.runtime.ComposeCompilerApi public static inline <T> T! cache(androidx.compose.runtime.Composer, boolean invalid, kotlin.jvm.functions.Function0<? extends T> block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformation(androidx.compose.runtime.Composer composer, String sourceInformation);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformationMarkerEnd(androidx.compose.runtime.Composer composer);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformationMarkerStart(androidx.compose.runtime.Composer composer, int key, String sourceInformation);
     field @kotlin.PublishedApi internal static final Object compositionLocalMap;
     field @kotlin.PublishedApi internal static final int compositionLocalMapKey = 202; // 0xca
     field @kotlin.PublishedApi internal static final Object invocation;
@@ -526,16 +529,16 @@
   }
 
   public final class ComposableLambdaKt {
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambda(androidx.compose.runtime.Composer composer, int key, boolean tracked, String? sourceInformation, Object block);
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambdaInstance(int key, boolean tracked, String? sourceInformation, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambda(androidx.compose.runtime.Composer composer, int key, boolean tracked, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambdaInstance(int key, boolean tracked, Object block);
   }
 
   @androidx.compose.runtime.ComposeCompilerApi @androidx.compose.runtime.Stable public interface ComposableLambdaN extends kotlin.jvm.functions.FunctionN<java.lang.Object> {
   }
 
   public final class ComposableLambdaN_jvmKt {
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaN(androidx.compose.runtime.Composer composer, int key, boolean tracked, String? sourceInformation, int arity, Object block);
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaNInstance(int key, boolean tracked, String? sourceInformation, int arity, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaN(androidx.compose.runtime.Composer composer, int key, boolean tracked, int arity, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
   }
 
   public final class DecoyKt {
diff --git a/compose/runtime/runtime/api/restricted_current.ignore b/compose/runtime/runtime/api/restricted_current.ignore
index 3676e75..87dd33f 100644
--- a/compose/runtime/runtime/api/restricted_current.ignore
+++ b/compose/runtime/runtime/api/restricted_current.ignore
@@ -5,7 +5,29 @@
     Added method androidx.compose.runtime.Composer.enableReusing()
 AddedAbstractMethod: androidx.compose.runtime.Composer#endReusableGroup():
     Added method androidx.compose.runtime.Composer.endReusableGroup()
+AddedAbstractMethod: androidx.compose.runtime.Composer#sourceInformation(String):
+    Added method androidx.compose.runtime.Composer.sourceInformation(String)
+AddedAbstractMethod: androidx.compose.runtime.Composer#sourceInformationMarkerEnd():
+    Added method androidx.compose.runtime.Composer.sourceInformationMarkerEnd()
+AddedAbstractMethod: androidx.compose.runtime.Composer#sourceInformationMarkerStart(int, String):
+    Added method androidx.compose.runtime.Composer.sourceInformationMarkerStart(int,String)
 AddedAbstractMethod: androidx.compose.runtime.Composer#startReusableGroup(int, Object):
     Added method androidx.compose.runtime.Composer.startReusableGroup(int,Object)
 AddedAbstractMethod: androidx.compose.runtime.Composer#startReusableNode():
     Added method androidx.compose.runtime.Composer.startReusableNode()
+
+
+RemovedMethod: androidx.compose.runtime.Composer#startMovableGroup(int, Object, String):
+    Removed method androidx.compose.runtime.Composer.startMovableGroup(int,Object,String)
+RemovedMethod: androidx.compose.runtime.Composer#startReplaceableGroup(int, String):
+    Removed method androidx.compose.runtime.Composer.startReplaceableGroup(int,String)
+RemovedMethod: androidx.compose.runtime.Composer#startRestartGroup(int, String):
+    Removed method androidx.compose.runtime.Composer.startRestartGroup(int,String)
+RemovedMethod: androidx.compose.runtime.internal.ComposableLambdaKt#composableLambda(androidx.compose.runtime.Composer, int, boolean, String, Object):
+    Removed method androidx.compose.runtime.internal.ComposableLambdaKt.composableLambda(androidx.compose.runtime.Composer,int,boolean,String,Object)
+RemovedMethod: androidx.compose.runtime.internal.ComposableLambdaKt#composableLambdaInstance(int, boolean, String, Object):
+    Removed method androidx.compose.runtime.internal.ComposableLambdaKt.composableLambdaInstance(int,boolean,String,Object)
+RemovedMethod: androidx.compose.runtime.internal.ComposableLambdaN_jvmKt#composableLambdaN(androidx.compose.runtime.Composer, int, boolean, String, int, Object):
+    Removed method androidx.compose.runtime.internal.ComposableLambdaN_jvmKt.composableLambdaN(androidx.compose.runtime.Composer,int,boolean,String,int,Object)
+RemovedMethod: androidx.compose.runtime.internal.ComposableLambdaN_jvmKt#composableLambdaNInstance(int, boolean, String, int, Object):
+    Removed method androidx.compose.runtime.internal.ComposableLambdaN_jvmKt.composableLambdaNInstance(int,boolean,String,int,Object)
diff --git a/compose/runtime/runtime/api/restricted_current.txt b/compose/runtime/runtime/api/restricted_current.txt
index 5dbea01..2cd34c5 100644
--- a/compose/runtime/runtime/api/restricted_current.txt
+++ b/compose/runtime/runtime/api/restricted_current.txt
@@ -110,14 +110,14 @@
     method @androidx.compose.runtime.ComposeCompilerApi public Object? rememberedValue();
     method @androidx.compose.runtime.ComposeCompilerApi public void skipCurrentGroup();
     method @androidx.compose.runtime.ComposeCompilerApi public void skipToGroupEnd();
+    method public void sourceInformation(String sourceInformation);
+    method public void sourceInformationMarkerEnd();
+    method public void sourceInformationMarkerStart(int key, String sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startDefaults();
     method @androidx.compose.runtime.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey);
-    method @androidx.compose.runtime.ComposeCompilerApi public void startMovableGroup(int key, Object? dataKey, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startNode();
     method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key);
-    method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.Composer startRestartGroup(int key);
-    method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.Composer startRestartGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReusableGroup(int key, Object? dataKey);
     method @androidx.compose.runtime.ComposeCompilerApi public void startReusableNode();
     method @androidx.compose.runtime.ComposeCompilerApi public void updateRememberedValue(Object? value);
@@ -141,6 +141,9 @@
 
   public final class ComposerKt {
     method @androidx.compose.runtime.ComposeCompilerApi public static inline <T> T! cache(androidx.compose.runtime.Composer, boolean invalid, kotlin.jvm.functions.Function0<? extends T> block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformation(androidx.compose.runtime.Composer composer, String sourceInformation);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformationMarkerEnd(androidx.compose.runtime.Composer composer);
+    method @androidx.compose.runtime.ComposeCompilerApi public static void sourceInformationMarkerStart(androidx.compose.runtime.Composer composer, int key, String sourceInformation);
     field @kotlin.PublishedApi internal static final Object compositionLocalMap;
     field @kotlin.PublishedApi internal static final int compositionLocalMapKey = 202; // 0xca
     field @kotlin.PublishedApi internal static final Object invocation;
@@ -526,16 +529,16 @@
   }
 
   public final class ComposableLambdaKt {
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambda(androidx.compose.runtime.Composer composer, int key, boolean tracked, String? sourceInformation, Object block);
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambdaInstance(int key, boolean tracked, String? sourceInformation, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambda(androidx.compose.runtime.Composer composer, int key, boolean tracked, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambda composableLambdaInstance(int key, boolean tracked, Object block);
   }
 
   @androidx.compose.runtime.ComposeCompilerApi @androidx.compose.runtime.Stable public interface ComposableLambdaN extends kotlin.jvm.functions.FunctionN<java.lang.Object> {
   }
 
   public final class ComposableLambdaN_jvmKt {
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaN(androidx.compose.runtime.Composer composer, int key, boolean tracked, String? sourceInformation, int arity, Object block);
-    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaNInstance(int key, boolean tracked, String? sourceInformation, int arity, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaN(androidx.compose.runtime.Composer composer, int key, boolean tracked, int arity, Object block);
+    method @androidx.compose.runtime.ComposeCompilerApi public static androidx.compose.runtime.internal.ComposableLambdaN composableLambdaNInstance(int key, boolean tracked, int arity, Object block);
   }
 
   public final class DecoyKt {
diff --git a/compose/runtime/runtime/build.gradle b/compose/runtime/runtime/build.gradle
index f6127c3..d8bae21 100644
--- a/compose/runtime/runtime/build.gradle
+++ b/compose/runtime/runtime/build.gradle
@@ -106,6 +106,9 @@
 }
 
 android {
+    defaultConfig {
+        consumerProguardFiles 'proguard-rules.pro'
+    }
     buildTypes {
         debug {
             testCoverageEnabled = false
diff --git a/compose/runtime/runtime/proguard-rules.pro b/compose/runtime/runtime/proguard-rules.pro
new file mode 100644
index 0000000..0343d92
--- /dev/null
+++ b/compose/runtime/runtime/proguard-rules.pro
@@ -0,0 +1,5 @@
+-assumenosideeffects public class androidx.compose.runtime.ComposerKt {
+    void sourceInformation(androidx.compose.runtime.Composer,java.lang.String);
+    void sourceInformationMarkerStart(androidx.compose.runtime.Composer,int,java.lang.String);
+    void sourceInformationMarkerEnd(androidx.compose.runtime.Composer);
+}
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
index 2f86602..3f84fc1 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
@@ -378,7 +378,7 @@
      * execution and can only either inserted, removed, or replaced. For example, the group
      * created by most control flow constructs such as an `if` statement are replacable groups.
      *
-     * @param key An compiler generated key based on the source location of the call.
+     * @param key A compiler generated key based on the source location of the call.
      */
     @ComposeCompilerApi
     fun startReplaceableGroup(key: Int)
@@ -386,20 +386,6 @@
     /**
      * A Compose compiler plugin API. DO NOT call directly.
      *
-     * Start a replacable group. A replacable group is a group that cannot be moved during
-     * execution and can only either inserted, removed, or replaced. For example, the group
-     * created by most control flow constructs such as an `if` statement are replacable groups.
-     *
-     * @param key An compiler generated key based on the source location of the call.
-     * @param sourceInformation An optional string value to that provides the compose tools enough
-     * information to calculate the source location calls made in the group.
-     */
-    @ComposeCompilerApi
-    fun startReplaceableGroup(key: Int, sourceInformation: String?)
-
-    /**
-     * A Compose compiler plugin API. DO NOT call directly.
-     *
      * Called at the end of a replacable group.
      *
      * @see startRestartGroup
@@ -418,7 +404,7 @@
      * the state and nodes generated by a loop to move with the composition implied by the key
      * passed to [key][androidx.compose.runtime.key].
 
-     * @param key An compiler generated key based on the source location of the call.
+     * @param key A compiler generated key based on the source location of the call.
      */
     @ComposeCompilerApi
     fun startMovableGroup(key: Int, dataKey: Any?)
@@ -426,24 +412,6 @@
     /**
      * A Compose compiler plugin API. DO NOT call directly.
      *
-     * Start a movable group. A movable group is one that can be moved based on the value of
-     * [dataKey] which is typically supplied by the [key][androidx.compose.runtime.key] pseudo
-     * compiler function.
-     *
-     * A movable group implements the semantics of [key][androidx.compose.runtime.key] which allows
-     * the state and nodes generated by a loop to move with the composition implied by the key
-     * passed to [key][androidx.compose.runtime.key].
-
-     * @param key An compiler generated key based on the source location of the call.
-     * @param sourceInformation An optional string value to that provides the compose tools enough
-     * information to calculate the source location calls made in the group.
-     */
-    @ComposeCompilerApi
-    fun startMovableGroup(key: Int, dataKey: Any?, sourceInformation: String?)
-
-    /**
-     * A Compose compiler plugin API. DO NOT call directly.
-     *
      * Called at the end of a movable group.
      *
      * @see startMovableGroup
@@ -481,7 +449,7 @@
      * recomposed on demand based on the lambda passed to
      * [updateScope][ScopeUpdateScope.updateScope] when [endRestartGroup] is called
      *
-     * @param key An compiler generated key based on the source location of the call.
+     * @param key A compiler generated key based on the source location of the call.
      * @return the instance of the composer to use for the rest of the function.
      */
     @ComposeCompilerApi
@@ -490,21 +458,6 @@
     /**
      * A Compose compiler plugin API. DO NOT call directly.
      *
-     * Called to record a group for a [Composable] function and starts a group that can be
-     * recomposed on demand based on the lambda passed to
-     * [updateScope][ScopeUpdateScope.updateScope] when [endRestartGroup] is called
-     *
-     * @param key An compiler generated key based on the source location of the call.
-     * @param sourceInformation An optional string value to that provides the compose tools enough
-     * information to calculate the source location calls made in the group.
-     * @return the instance of the composer to use for the rest of the function.
-     */
-    @ComposeCompilerApi
-    fun startRestartGroup(key: Int, sourceInformation: String?): Composer
-
-    /**
-     * A Compose compiler plugin API. DO NOT call directly.
-     *
      * Called to end a restart group.
      */
     @ComposeCompilerApi
@@ -513,6 +466,38 @@
     /**
      * A Compose compiler plugin API. DO NOT call directly.
      *
+     * Record the source information string for a group. This must be immediately called after the
+     * start of a group.
+     *
+     * @param sourceInformation An string value to that provides the compose tools enough
+     * information to calculate the source location of calls to composable functions.
+     */
+    fun sourceInformation(sourceInformation: String)
+
+    /**
+     * A compose compiler plugin API. DO NOT call directly.
+     *
+     * Record a source information marker. This marker can be used in place of a group that would
+     * have contained the information but was elided as the compiler plugin determined the group
+     * was not necessary such as when a function is marked with [ReadOnlyComposable].
+     *
+     * @param key A compiler generated key based on the source location of the call.
+     * @param sourceInformation An string value to that provides the compose tools enough
+     * information to calculate the source location of calls to composable functions.
+     *
+     */
+    fun sourceInformationMarkerStart(key: Int, sourceInformation: String)
+
+    /**
+     * A compose compiler plugin API. DO NOT call directly.
+     *
+     * Record the end of the marked source information range.
+     */
+    fun sourceInformationMarkerEnd()
+
+    /**
+     * A Compose compiler plugin API. DO NOT call directly.
+     *
      * Skips the composer to the end of the current group. This generated by the compiler to when
      * the body of a [Composable] function can be skipped typically because the parameters to the
      * function are equal to the values passed to it in the previous composition.
@@ -959,6 +944,52 @@
 }
 
 /**
+ * A Compose internal function. DO NOT call directly.
+ *
+ * Records source information that can be used for tooling to determine the source location of
+ * the corresponding composable function. By default, this function is declared as having no
+ * side-effects. It is safe for code shrinking tools (such as R8 or ProGuard) to remove it.
+ */
+@ComposeCompilerApi
+fun sourceInformation(composer: Composer, sourceInformation: String) {
+    composer.sourceInformation(sourceInformation)
+}
+
+/**
+ * A Compose internal function. DO NOT call directly.
+ *
+ * Records the start of a source information marker that can be used for tooling to determine the
+ * source location of the corresponding composable function that otherwise don't require tracking
+ * information such as [ReadOnlyComposable] functions. By default, this function is declared as
+ * having no side-effects. It is safe for code shrinking tools (such as R8 or ProGuard) to remove
+ * it.
+ *
+ * Important that both [sourceInformationMarkerStart] and [sourceInformationMarkerEnd] are removed
+ * together or both kept. Removing only one will cause incorrect runtime behavior.
+ */
+@ComposeCompilerApi
+fun sourceInformationMarkerStart(composer: Composer, key: Int, sourceInformation: String) {
+    composer.sourceInformationMarkerStart(key, sourceInformation)
+}
+
+/**
+ * A Compose internal function. DO NOT call directly.
+ *
+ * Records the end of a source information marker that can be used for tooling to determine the
+ * source location of the corresponding composable function that otherwise don't require tracking
+ * information such as [ReadOnlyComposable] functions. By default, this function is declared as
+ * having no side-effects. It is safe for code shrinking tools (such as R8 or ProGuard) to remove
+ * it.
+ *
+ * Important that both [sourceInformationMarkerStart] and [sourceInformationMarkerEnd] are removed
+ * together or both kept. Removing only one will cause incorrect runtime behavior.
+ */
+@ComposeCompilerApi
+fun sourceInformationMarkerEnd(composer: Composer) {
+    composer.sourceInformationMarkerEnd()
+}
+
+/**
  * Implementation of a composer for a mutable tree.
  */
 internal class ComposerImpl(
@@ -1053,10 +1084,6 @@
     @ComposeCompilerApi
     override fun startReplaceableGroup(key: Int) = start(key, null, false, null)
 
-    @ComposeCompilerApi
-    override fun startReplaceableGroup(key: Int, sourceInformation: String?) =
-        start(key, null, false, sourceInformation)
-
     /**
      * Indicates the end of a "Replaceable Group" at the current execution position. A
      * Replaceable Group is a group which cannot be moved between its siblings, but
@@ -1136,10 +1163,6 @@
     @ComposeCompilerApi
     override fun startMovableGroup(key: Int, dataKey: Any?) = start(key, dataKey, false, null)
 
-    @ComposeCompilerApi
-    override fun startMovableGroup(key: Int, dataKey: Any?, sourceInformation: String?) =
-        start(key, dataKey, false, sourceInformation)
-
     /**
      * Indicates the end of a "Movable Group" at the current execution position. A Movable Group is
      * a group which can be moved or reordered between its siblings and retain slot table state,
@@ -2414,13 +2437,6 @@
         return this
     }
 
-    @ComposeCompilerApi
-    override fun startRestartGroup(key: Int, sourceInformation: String?): Composer {
-        start(key, null, false, sourceInformation)
-        addRecomposeScope()
-        return this
-    }
-
     private fun addRecomposeScope() {
         if (inserting) {
             val scope = RecomposeScopeImpl(composition as CompositionImpl)
@@ -2469,6 +2485,23 @@
         return result
     }
 
+    @ComposeCompilerApi
+    override fun sourceInformation(sourceInformation: String) {
+        if (inserting) {
+            writer.insertAux(sourceInformation)
+        }
+    }
+
+    @ComposeCompilerApi
+    override fun sourceInformationMarkerStart(key: Int, sourceInformation: String) {
+        start(key, objectKey = null, isNode = false, data = sourceInformation)
+    }
+
+    @ComposeCompilerApi
+    override fun sourceInformationMarkerEnd() {
+        end(isNode = false)
+    }
+
     /**
      * Synchronously compose the initial composition of [content]. This collects all the changes
      * which must be applied by [ControlledComposition.applyChanges] to build the tree implied by
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 8b84b4a..8e8a725 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
@@ -1127,6 +1127,37 @@
     }
 
     /**
+     * Insert aux data into the parent group.
+     *
+     * This must be done only after at most one value has been inserted into the slot table for
+     * the group.
+     */
+    fun insertAux(value: Any?) {
+        check(insertCount >= 0) { "Cannot insert auxiliary data when not inserting" }
+        val parent = parent
+        val parentGroupAddress = groupIndexToAddress(parent)
+        check(!groups.hasAux(parentGroupAddress)) { "Group already has auxiliary data" }
+        insertSlots(1, parent)
+        val auxIndex = groups.auxIndex(parentGroupAddress)
+        val auxAddress = dataIndexToDataAddress(auxIndex)
+        if (currentSlot > auxIndex) {
+            // One or more values were inserted into the slot table before the aux value, we need
+            // to move them. Currently we only will run into one or two slots (the recompose
+            // scope inserted by a restart group and the lambda value in a composableLambda
+            // instance) so this is the only case currently supported.
+            val slotsToMove = currentSlot - auxIndex
+            check(slotsToMove < 3) { "Moving more than two slot not supported" }
+            if (slotsToMove > 1) {
+                slots[auxAddress + 2] = slots[auxAddress + 1]
+            }
+            slots[auxAddress + 1] = slots[auxAddress]
+        }
+        groups.addAux(parentGroupAddress)
+        slots[auxAddress] = value
+        currentSlot++
+    }
+
+    /**
      * Updates the node for the current node group to [value].
      */
     fun updateNode(value: Any?) = updateNodeOfGroup(currentGroup, value)
@@ -2463,7 +2494,7 @@
 // 31 30 29 28_27 26 25 24_23 22 21 20_19 18 17 16__15 14 13 12_11 10 09 08_07 06 05 04_03 02 01 00
 // 0  n  ks ds r |                                node count                                       |
 // where n is set when the group represents a node
-// where ks is whether the group has a data key slot
+// where ks is whether the group has a object key slot
 // where ds is whether the group has a group data slot
 // where r is always 0 (future use)
 
@@ -2508,6 +2539,11 @@
 }
 private fun IntArray.hasAux(address: Int) =
     this[address * Group_Fields_Size + GroupInfo_Offset] and Aux_Mask != 0
+private fun IntArray.addAux(address: Int) {
+    val arrayIndex = address * Group_Fields_Size + GroupInfo_Offset
+    this[arrayIndex] = this[arrayIndex] or Aux_Mask
+}
+
 private fun IntArray.auxIndex(address: Int) = (address * Group_Fields_Size).let { slot ->
     if (slot >= size) size
     else this[slot + DataAnchor_Offset] +
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/internal/ComposableLambda.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/internal/ComposableLambda.kt
index f2cdb63..368da08 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/internal/ComposableLambda.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/internal/ComposableLambda.kt
@@ -47,8 +47,7 @@
 /* ktlint-disable parameter-list-wrapping */ // TODO(https://github.com/pinterest/ktlint/issues/921): reenable
 internal expect class ComposableLambdaImpl(
     key: Int,
-    tracked: Boolean,
-    sourceInformation: String?
+    tracked: Boolean
 ) : ComposableLambda {
     fun update(block: Any)
 }
@@ -327,13 +326,12 @@
     composer: Composer,
     key: Int,
     tracked: Boolean,
-    sourceInformation: String?,
     block: Any
 ): ComposableLambda {
     composer.startReplaceableGroup(key)
     val slot = composer.rememberedValue()
     val result = if (slot === Composer.Empty) {
-        val value = ComposableLambdaImpl(key, tracked, sourceInformation)
+        val value = ComposableLambdaImpl(key, tracked)
         composer.updateRememberedValue(value)
         value
     } else {
@@ -349,7 +347,6 @@
 fun composableLambdaInstance(
     key: Int,
     tracked: Boolean,
-    sourceInformation: String?,
     block: Any
 ): ComposableLambda =
-    ComposableLambdaImpl(key, tracked, sourceInformation).apply { update(block) }
+    ComposableLambdaImpl(key, tracked).apply { update(block) }
diff --git a/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/internal/ComposableLambda.jvm.kt b/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/internal/ComposableLambda.jvm.kt
index 572c146..172a413 100644
--- a/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/internal/ComposableLambda.jvm.kt
+++ b/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/internal/ComposableLambda.jvm.kt
@@ -36,8 +36,7 @@
 /* ktlint-disable parameter-list-wrapping */ // TODO(https://github.com/pinterest/ktlint/issues/921): reenable
 internal actual class ComposableLambdaImpl actual constructor(
     val key: Int,
-    private val tracked: Boolean,
-    private val sourceInformation: String?
+    private val tracked: Boolean
 ) : ComposableLambda {
     private var _block: Any? = null
     private var scope: RecomposeScope? = null
@@ -102,7 +101,7 @@
     }
 
     override operator fun invoke(c: Composer, changed: Int): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed or if (c.changed(this)) differentBits(0) else sameBits(0)
         val result = (_block as (c: Composer, changed: Int) -> Any?)(c, dirty)
@@ -111,7 +110,7 @@
     }
 
     override operator fun invoke(p1: Any?, c: Composer, changed: Int): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed or if (c.changed(this)) differentBits(1) else sameBits(1)
         val result = (
@@ -130,7 +129,7 @@
     }
 
     override operator fun invoke(p1: Any?, p2: Any?, c: Composer, changed: Int): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed or if (c.changed(this)) differentBits(2) else sameBits(2)
         val result = (_block as (p1: Any?, p2: Any?, c: Composer, changed: Int) -> Any?)(
@@ -144,7 +143,7 @@
     }
 
     override operator fun invoke(p1: Any?, p2: Any?, p3: Any?, c: Composer, changed: Int): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed or if (c.changed(this)) differentBits(3) else sameBits(3)
         val result = (
@@ -174,7 +173,7 @@
         c: Composer,
         changed: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed or if (c.changed(this)) differentBits(4) else sameBits(4)
         val result = (
@@ -209,7 +208,7 @@
         c: Composer,
         changed: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed or if (c.changed(this)) differentBits(5) else sameBits(5)
         val result = (
@@ -247,7 +246,7 @@
         c: Composer,
         changed: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed or if (c.changed(this)) differentBits(6) else sameBits(6)
         val result = (
@@ -288,7 +287,7 @@
         c: Composer,
         changed: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed or if (c.changed(this)) differentBits(7) else sameBits(7)
         val result = (
@@ -332,7 +331,7 @@
         c: Composer,
         changed: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed or if (c.changed(this)) differentBits(8) else sameBits(8)
         val result = (
@@ -379,7 +378,7 @@
         c: Composer,
         changed: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed or if (c.changed(this)) differentBits(9) else sameBits(9)
         val result = (
@@ -430,7 +429,7 @@
         changed: Int,
         changed1: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed1 or if (c.changed(this)) differentBits(10) else sameBits(10)
         val result = (
@@ -486,7 +485,7 @@
         changed: Int,
         changed1: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed1 or if (c.changed(this)) differentBits(11) else sameBits(11)
         val result = (
@@ -545,7 +544,7 @@
         changed: Int,
         changed1: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed1 or if (c.changed(this)) differentBits(12) else sameBits(12)
         val result = (
@@ -607,7 +606,7 @@
         changed: Int,
         changed1: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed1 or if (c.changed(this)) differentBits(13) else sameBits(13)
         val result = (
@@ -689,7 +688,7 @@
         changed: Int,
         changed1: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed1 or if (c.changed(this)) differentBits(14) else sameBits(14)
         val result = (
@@ -775,7 +774,7 @@
         changed: Int,
         changed1: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed1 or if (c.changed(this)) differentBits(15) else sameBits(15)
         val result = (
@@ -865,7 +864,7 @@
         changed: Int,
         changed1: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed1 or if (c.changed(this)) differentBits(16) else sameBits(16)
         val result = (
@@ -959,7 +958,7 @@
         changed: Int,
         changed1: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed1 or if (c.changed(this)) differentBits(17) else sameBits(17)
         val result = (
@@ -1057,7 +1056,7 @@
         changed: Int,
         changed1: Int
     ): Any? {
-        val c = c.startRestartGroup(key, sourceInformation)
+        val c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = changed1 or if (c.changed(this)) differentBits(18) else sameBits(18)
         val result = (
diff --git a/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/internal/ComposableLambdaN.jvm.kt b/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/internal/ComposableLambdaN.jvm.kt
index 08e88f1..3193f395 100644
--- a/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/internal/ComposableLambdaN.jvm.kt
+++ b/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/internal/ComposableLambdaN.jvm.kt
@@ -30,7 +30,6 @@
 internal class ComposableLambdaNImpl(
     val key: Int,
     private val tracked: Boolean,
-    private val sourceInformation: String?,
     override val arity: Int
 ) : ComposableLambdaN {
     private var _block: Any? = null
@@ -112,7 +111,7 @@
         var c = args[realParams] as Composer
         val allArgsButLast = args.slice(0 until args.size - 1).toTypedArray()
         val lastChanged = args[args.size - 1] as Int
-        c = c.startRestartGroup(key, sourceInformation)
+        c = c.startRestartGroup(key)
         trackRead(c)
         val dirty = lastChanged or if (c.changed(this))
             differentBits(realParams)
@@ -146,14 +145,13 @@
     composer: Composer,
     key: Int,
     tracked: Boolean,
-    sourceInformation: String?,
     arity: Int,
     block: Any
 ): ComposableLambdaN {
     composer.startReplaceableGroup(key)
     val slot = composer.rememberedValue()
     val result = if (slot === Composer.Empty) {
-        val value = ComposableLambdaNImpl(key, tracked, sourceInformation, arity)
+        val value = ComposableLambdaNImpl(key, tracked, arity)
         composer.updateRememberedValue(value)
         value
     } else {
@@ -170,12 +168,10 @@
 fun composableLambdaNInstance(
     key: Int,
     tracked: Boolean,
-    sourceInformation: String?,
     arity: Int,
     block: Any
 ): ComposableLambdaN = ComposableLambdaNImpl(
     key,
     tracked,
-    sourceInformation,
     arity
 ).apply { update(block) }
diff --git a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/SlotTableTests.kt b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/SlotTableTests.kt
index 90d50e4..f5498d2 100644
--- a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/SlotTableTests.kt
+++ b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/SlotTableTests.kt
@@ -3139,6 +3139,95 @@
         }
         slots.verifyWellFormed()
     }
+
+    @Test
+    fun canInsertAuxData() {
+        val slots = SlotTable().also {
+            it.write { writer ->
+                writer.insert {
+                    // Insert a normal aux data.
+                    writer.startData(10, 10, "10")
+                    writer.endGroup()
+
+                    // Insert using insertAux
+                    writer.startGroup(20)
+                    writer.insertAux("20")
+                    writer.endGroup()
+
+                    // Insert using insertAux after a slot value was added.
+                    writer.startGroup(30)
+                    writer.update(300)
+                    writer.insertAux("30")
+                    writer.endGroup()
+
+                    // Insert using insertAux after a group with an object key
+                    writer.startGroup(40, 40)
+                    writer.insertAux("40")
+                    writer.endGroup()
+
+                    // Insert aux into an object key with a value slot and then add another value.
+                    writer.startGroup(50, 50)
+                    writer.update(500)
+                    writer.insertAux("50")
+                    writer.update(501)
+                    writer.endGroup()
+
+                    // Insert aux after two slot values and then add another value.
+                    writer.startGroup(60)
+                    writer.update(600)
+                    writer.update(601)
+                    writer.insertAux("60")
+                    writer.update(602)
+                    writer.endGroup()
+
+                    // Write a trail group to ensure that the slot table is valid after the
+                    // insertAux
+                    writer.startGroup(1000)
+                    writer.update(10000)
+                    writer.update(10001)
+                    writer.endGroup()
+                }
+            }
+        }
+        slots.verifyWellFormed()
+        slots.read { reader ->
+            assertEquals(10, reader.groupKey)
+            assertEquals(10, reader.groupObjectKey)
+            assertEquals("10", reader.groupAux)
+            reader.skipGroup()
+            assertEquals(20, reader.groupKey)
+            assertEquals("20", reader.groupAux)
+            reader.skipGroup()
+            assertEquals(30, reader.groupKey)
+            assertEquals("30", reader.groupAux)
+            reader.startGroup()
+            assertEquals(300, reader.next())
+            reader.endGroup()
+            assertEquals(40, reader.groupKey)
+            assertEquals(40, reader.groupObjectKey)
+            assertEquals("40", reader.groupAux)
+            reader.skipGroup()
+            assertEquals(50, reader.groupKey)
+            assertEquals(50, reader.groupObjectKey)
+            assertEquals("50", reader.groupAux)
+            reader.startGroup()
+            assertEquals(500, reader.next())
+            assertEquals(501, reader.next())
+            reader.endGroup()
+            assertEquals(60, reader.groupKey)
+            assertEquals("60", reader.groupAux)
+            reader.startGroup()
+            assertEquals(600, reader.next())
+            assertEquals(601, reader.next())
+            assertEquals(602, reader.next())
+            reader.endGroup()
+            assertEquals(1000, reader.groupKey)
+            reader.startGroup()
+            assertEquals(10000, reader.next())
+            assertEquals(10001, reader.next())
+            reader.endGroup()
+        }
+    }
 }
 
 @OptIn(InternalComposeApi::class)
diff --git a/compose/ui/ui-test-junit4/build.gradle b/compose/ui/ui-test-junit4/build.gradle
index 1923226..9a89811 100644
--- a/compose/ui/ui-test-junit4/build.gradle
+++ b/compose/ui/ui-test-junit4/build.gradle
@@ -85,6 +85,7 @@
 
                 implementation("androidx.annotation:annotation:1.1.0")
                 implementation(KOTLIN_COROUTINES_CORE)
+                implementation(KOTLIN_COROUTINES_TEST)
             }
 
             androidMain.dependencies {
@@ -99,7 +100,6 @@
                 implementation(ANDROIDX_TEST_MONITOR)
                 implementation(ESPRESSO_CORE)
                 implementation(ESPRESSO_IDLING_RESOURCE)
-                implementation(KOTLIN_COROUTINES_TEST)
             }
 
             androidAndroidTest.dependencies {
diff --git a/compose/ui/ui-test-junit4/src/androidAndroidTest/kotlin/androidx/compose/ui/test/junit4/UncaughtExceptionsInCoroutinesTest.kt b/compose/ui/ui-test-junit4/src/androidAndroidTest/kotlin/androidx/compose/ui/test/junit4/UncaughtExceptionsInCoroutinesTest.kt
index 0c5823c..01d4151 100644
--- a/compose/ui/ui-test-junit4/src/androidAndroidTest/kotlin/androidx/compose/ui/test/junit4/UncaughtExceptionsInCoroutinesTest.kt
+++ b/compose/ui/ui-test-junit4/src/androidAndroidTest/kotlin/androidx/compose/ui/test/junit4/UncaughtExceptionsInCoroutinesTest.kt
@@ -23,10 +23,7 @@
 import androidx.test.filters.LargeTest
 import org.junit.Rule
 import org.junit.Test
-import org.junit.rules.RuleChain
-import org.junit.rules.TestRule
 import org.junit.runner.RunWith
-import org.junit.runners.model.Statement
 
 @LargeTest
 @RunWith(AndroidJUnit4::class)
@@ -34,23 +31,8 @@
 
     private class TestException : Exception()
 
-    // Need to expect the error in a test rule around the AndroidComposeTestRule, because the
-    // exception can surface after the test is completed, when the AndroidComposeTestRule cleans
-    // up test scoped variables.
-    private val testExceptionRule = TestRule { base, _ ->
-        object : Statement() {
-            override fun evaluate() {
-                expectError<TestException> {
-                    base.evaluate()
-                }
-            }
-        }
-    }
-
-    private val rule = createComposeRule()
-
     @get:Rule
-    val testRule: TestRule = RuleChain.outerRule(testExceptionRule).around(rule)
+    val rule = createComposeRule()
 
     // Run the test twice so we can verify if a failed test took down the test suite:
     // - Results have 1 failed test:
@@ -60,12 +42,16 @@
 
     @Test
     fun test1() {
-        throwInLaunchedEffect()
+        expectError<TestException> {
+            throwInLaunchedEffect()
+        }
     }
 
     @Test
     fun test2() {
-        throwInLaunchedEffect()
+        expectError<TestException> {
+            throwInLaunchedEffect()
+        }
     }
 
     private fun throwInLaunchedEffect() {
diff --git a/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule.android.kt b/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule.android.kt
index 75569f83..b5f158a 100644
--- a/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule.android.kt
+++ b/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule.android.kt
@@ -61,7 +61,6 @@
 import kotlinx.coroutines.cancel
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.test.TestCoroutineDispatcher
-import kotlinx.coroutines.test.TestCoroutineExceptionHandler
 import kotlinx.coroutines.withContext
 import org.junit.rules.RuleChain
 import org.junit.rules.TestRule
@@ -185,8 +184,7 @@
     private val testCoroutineDispatcher: TestCoroutineDispatcher
     private val recomposerApplyCoroutineScope: CoroutineScope
     private val frameCoroutineScope: CoroutineScope
-    @OptIn(ExperimentalCoroutinesApi::class)
-    private val coroutineExceptionHandler: TestCoroutineExceptionHandler
+    private val coroutineExceptionHandler = UncaughtExceptionHandler()
 
     override val mainClock: MainTestClock
         get() = mainClockImpl
@@ -207,8 +205,6 @@
             }
         }
         @OptIn(ExperimentalCoroutinesApi::class)
-        coroutineExceptionHandler = TestCoroutineExceptionHandler()
-        @OptIn(ExperimentalCoroutinesApi::class)
         recomposerApplyCoroutineScope = CoroutineScope(
             testCoroutineDispatcher + frameClock + infiniteAnimationPolicy +
                 coroutineExceptionHandler + Job()
@@ -287,7 +283,7 @@
             // Then await composition(s)
             runEspressoOnIdle()
         }
-        checkUncaughtCoroutineExceptions()
+        coroutineExceptionHandler.throwUncaught()
     }
 
     override fun <T> runOnUiThread(action: () -> T): T {
@@ -326,18 +322,6 @@
         idlingResourceRegistry.unregisterIdlingResource(idlingResource)
     }
 
-    /**
-     * Checks if the [coroutineExceptionHandler] has caught uncaught exceptions. If so, will
-     * rethrow the first to fail the test. Rather than only calling this only at the end of the
-     * test, as recommended by [cleanupTestCoroutines][kotlinx.coroutines.test
-     * .UncaughtExceptionCaptor.cleanupTestCoroutines], try calling this at a few strategic
-     * points to fail the test asap after the exception was caught.
-     */
-    private fun checkUncaughtCoroutineExceptions() {
-        @OptIn(ExperimentalCoroutinesApi::class)
-        coroutineExceptionHandler.cleanupTestCoroutines()
-    }
-
     inner class AndroidComposeStatement(
         private val base: Statement
     ) : Statement() {
@@ -363,7 +347,7 @@
                 // throwing errors on active coroutines
                 recomposerApplyCoroutineScope.cancel()
                 frameCoroutineScope.cancel()
-                checkUncaughtCoroutineExceptions()
+                coroutineExceptionHandler.throwUncaught()
                 @OptIn(ExperimentalCoroutinesApi::class)
                 testCoroutineDispatcher.cleanupTestCoroutines()
                 textInputServiceFactory = oldTextInputFactory
@@ -456,7 +440,7 @@
             //  between now and when the new Activity has created its compose root, even though
             //  waitForComposeRoots() suggests that we are now guaranteed one.
 
-            checkUncaughtCoroutineExceptions()
+            coroutineExceptionHandler.throwUncaught()
         }
 
         override fun getRoots(atLeastOneRootExpected: Boolean): Set<RootForTest> {
diff --git a/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.desktop.kt b/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.desktop.kt
index 7038f13..e055101 100644
--- a/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.desktop.kt
+++ b/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.desktop.kt
@@ -49,10 +49,6 @@
 @OptIn(InternalTestApi::class)
 class DesktopComposeTestRule : ComposeContentTestRule {
 
-    companion object {
-        var current: DesktopComposeTestRule? = null
-    }
-
     override val density: Density
         get() = Density(1f, 1f)
 
@@ -61,13 +57,13 @@
 
     internal val testDisplaySize: IntSize get() = IntSize(1024, 768)
 
+    private var uncaughtExceptionHandler = UncaughtExceptionHandler()
     lateinit var window: TestComposeWindow
 
     private val testOwner = DesktopTestOwner(this)
     private val testContext = createTestContext(testOwner)
 
     override fun apply(base: Statement, description: Description?): Statement {
-        current = this
         return object : Statement() {
             override fun evaluate() {
                 window = runOnUiThread(::createWindow)
@@ -77,6 +73,8 @@
                 } finally {
                     runOnUiThread(window::dispose)
                 }
+
+                uncaughtExceptionHandler.throwUncaught()
             }
         }
     }
@@ -86,7 +84,7 @@
         height = testDisplaySize.height,
         density = density,
         nanoTime = System::nanoTime, // TODO(demin): use mainClock?
-        coroutineContext = Dispatchers.Swing
+        coroutineContext = Dispatchers.Swing + uncaughtExceptionHandler
     )
 
     private fun isIdle() =
@@ -96,6 +94,7 @@
     override fun waitForIdle() {
         while (!isIdle()) {
             Thread.sleep(10)
+            uncaughtExceptionHandler.throwUncaught()
         }
     }
 
@@ -103,6 +102,7 @@
     override suspend fun awaitIdle() {
         while (!isIdle()) {
             delay(10)
+            uncaughtExceptionHandler.throwUncaught()
         }
     }
 
diff --git a/compose/ui/ui-test-junit4/src/jvmMain/kotlin/androidx/compose/ui/test/junit4/UncaughtExceptionHandler.jvm.kt b/compose/ui/ui-test-junit4/src/jvmMain/kotlin/androidx/compose/ui/test/junit4/UncaughtExceptionHandler.jvm.kt
new file mode 100644
index 0000000..b25d2ba
--- /dev/null
+++ b/compose/ui/ui-test-junit4/src/jvmMain/kotlin/androidx/compose/ui/test/junit4/UncaughtExceptionHandler.jvm.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.test.junit4
+
+import kotlinx.coroutines.CoroutineExceptionHandler
+import kotlin.coroutines.AbstractCoroutineContextElement
+import kotlin.coroutines.CoroutineContext
+
+/**
+ * Similar to [TestCoroutineExceptionHandler], but with clearing all thrown exceptions
+ *
+ * If we don't clear exceptions they will be thrown twice in this example
+ * (the exception will be thrown inside awaitIdle and after the test):
+ * ```
+ * @Test
+ * fun test() {
+ *    runBlocking(Dispatchers.Main) {
+ *        try {
+ *            rule.awaitIdle()
+ *        } catch (e: SomeException) {
+ *            // ignore
+ *        }
+ *    }
+ * }
+ * ```
+ */
+internal class UncaughtExceptionHandler :
+    AbstractCoroutineContextElement(CoroutineExceptionHandler),
+    CoroutineExceptionHandler {
+    private var exception: Throwable? = null
+
+    override fun handleException(context: CoroutineContext, exception: Throwable) {
+        synchronized(this) {
+            if (this.exception == null) {
+                this.exception = exception
+            } else {
+                this.exception!!.addSuppressed(exception)
+            }
+        }
+    }
+
+    /**
+     * Checks if the [UncaughtExceptionHandler] has caught uncaught exceptions. If so, will
+     * rethrow the first to fail the test. The rest exceptions will be added to the first and
+     * marked as `suppressed`.
+     *
+     * The next call of this method will not throw already thrown exception.
+     *
+     * Rather than only calling this only at the end of the test, as recommended by
+     * [UncaughtExceptionCaptor.cleanupTestCoroutines],
+     * try calling this at a few strategic
+     * points to fail the test asap after the exception was caught.
+     */
+    fun throwUncaught() {
+        synchronized(this) {
+            val exception = exception
+            if (exception != null) {
+                this.exception = null
+                throw exception
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwners.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwners.desktop.kt
index 6586019..7a27e67 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwners.desktop.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/DesktopOwners.desktop.kt
@@ -73,7 +73,7 @@
 
     private val dispatcher = FlushCoroutineDispatcher(coroutineScope)
     private val frameClock = BroadcastFrameClock(onNewAwaiters = ::invalidateIfNeeded)
-    private val coroutineContext = dispatcher + frameClock
+    private val coroutineContext = coroutineScope.coroutineContext + dispatcher + frameClock
 
     internal val recomposer = Recomposer(coroutineContext)
     internal val platformInputService: DesktopPlatformInput = DesktopPlatformInput(component)
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/TestComposeWindow.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/TestComposeWindow.desktop.kt
index 15d19ba..cddba9b 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/TestComposeWindow.desktop.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/TestComposeWindow.desktop.kt
@@ -25,6 +25,7 @@
 import androidx.compose.ui.unit.Density
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.Runnable
 import kotlinx.coroutines.cancel
 import org.jetbrains.skija.Surface
@@ -59,7 +60,7 @@
     private val canvas = surface.canvas
     private var owner: DesktopOwner? = null
 
-    private val coroutineScope = CoroutineScope(coroutineContext)
+    private val coroutineScope = CoroutineScope(coroutineContext + Job())
     private val frameDispatcher: FrameDispatcher = FrameDispatcher(
         onFrame = { onFrame() },
         context = coroutineScope.coroutineContext
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt
index d3345e2..b6073f5 100644
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt
+++ b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/DesktopOwnerTest.kt
@@ -46,8 +46,11 @@
 import androidx.compose.ui.input.mouse.MouseScrollUnit
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.test.junit4.DesktopScreenshotTestRule
+import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.unit.dp
 import com.google.common.truth.Truth
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
 import org.junit.Assert.assertFalse
 import org.junit.Rule
 import org.junit.Test
@@ -55,6 +58,8 @@
 class DesktopOwnerTest {
     @get:Rule
     val screenshotRule = DesktopScreenshotTestRule("ui/ui-desktop/ui")
+    @get:Rule
+    val composeRule = createComposeRule()
 
     @Test(timeout = 5000)
     fun `rendering of Box state change`() = renderingTest(width = 40, height = 40) {
@@ -349,4 +354,18 @@
         awaitNextRender()
         Truth.assertThat(effectIsLaunched).isTrue()
     }
+
+    @Test(expected = TestException::class)
+    fun `catch exception in LaunchedEffect`() {
+        runBlocking(Dispatchers.Main) {
+            composeRule.setContent {
+                LaunchedEffect(Unit) {
+                    throw TestException()
+                }
+            }
+            composeRule.awaitIdle()
+        }
+    }
+
+    private class TestException : RuntimeException()
 }
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/TestComposeWindowTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/TestComposeWindowTest.kt
index a85f9da..7fd119a 100644
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/TestComposeWindowTest.kt
+++ b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/TestComposeWindowTest.kt
@@ -23,6 +23,9 @@
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.AccountBox
 import androidx.compose.ui.Modifier
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.swing.Swing
 import org.junit.Test
 
 class TestComposeWindowTest {
@@ -41,4 +44,12 @@
             }
         }
     }
+
+    @Test(timeout = 5000)
+    fun `disposing TestComposeWindow should not cancel coroutineContext's Job`() {
+        runBlocking(Dispatchers.Swing) {
+            val window = TestComposeWindow(100, 100, coroutineContext = coroutineContext)
+            window.dispose()
+        }
+    }
 }
\ No newline at end of file
diff --git a/concurrent/futures-ktx/lint-baseline.xml b/concurrent/futures-ktx/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/concurrent/futures-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/core/core-animation-integration-tests/testapp/lint-baseline.xml b/core/core-animation-integration-tests/testapp/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/core/core-animation-integration-tests/testapp/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/core/core-animation-testing/lint-baseline.xml b/core/core-animation-testing/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/core/core-animation-testing/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/core/core-appdigest/lint-baseline.xml b/core/core-appdigest/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/core/core-appdigest/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/core/core-google-shortcuts/api/1.0.0-beta01.txt b/core/core-google-shortcuts/api/1.0.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/core/core-google-shortcuts/api/1.0.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/core/core-google-shortcuts/api/public_plus_experimental_1.0.0-beta01.txt b/core/core-google-shortcuts/api/public_plus_experimental_1.0.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/core/core-google-shortcuts/api/public_plus_experimental_1.0.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/core/core-google-shortcuts/api/res-1.0.0-beta01.txt b/core/core-google-shortcuts/api/res-1.0.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/core/core-google-shortcuts/api/res-1.0.0-beta01.txt
diff --git a/core/core-google-shortcuts/api/restricted_1.0.0-beta01.txt b/core/core-google-shortcuts/api/restricted_1.0.0-beta01.txt
new file mode 100644
index 0000000..bdb2746
--- /dev/null
+++ b/core/core-google-shortcuts/api/restricted_1.0.0-beta01.txt
@@ -0,0 +1,9 @@
+// Signature format: 4.0
+package @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) androidx.core.google.shortcuts {
+
+  @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public class ShortcutInfoChangeListenerImpl extends androidx.core.content.pm.ShortcutInfoChangeListener {
+    method public static androidx.core.google.shortcuts.ShortcutInfoChangeListenerImpl getInstance(android.content.Context);
+  }
+
+}
+
diff --git a/core/core-google-shortcuts/build.gradle b/core/core-google-shortcuts/build.gradle
index e89eb00..31d0cfe 100644
--- a/core/core-google-shortcuts/build.gradle
+++ b/core/core-google-shortcuts/build.gradle
@@ -33,7 +33,7 @@
 
 dependencies {
     api(KOTLIN_STDLIB)
-    api("androidx.core:core:1.6.0-alpha02")
+    api(project(":core:core"))
 
     implementation("com.google.firebase:firebase-appindexing:19.2.0")
     implementation("com.google.crypto.tink:tink-android:1.5.0")
diff --git a/core/core-role/lint-baseline.xml b/core/core-role/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/core/core-role/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/datastore/datastore-core/lint-baseline.xml b/datastore/datastore-core/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/datastore/datastore-core/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/datastore/datastore-preferences-core/datastore-preferences-proto/lint-baseline.xml b/datastore/datastore-preferences-core/datastore-preferences-proto/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/datastore/datastore-preferences-core/datastore-preferences-proto/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/datastore/datastore-preferences-core/lint-baseline.xml b/datastore/datastore-preferences-core/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/datastore/datastore-preferences-core/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/datastore/datastore-preferences-rxjava2/lint-baseline.xml b/datastore/datastore-preferences-rxjava2/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/datastore/datastore-preferences-rxjava2/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/datastore/datastore-preferences-rxjava3/lint-baseline.xml b/datastore/datastore-preferences-rxjava3/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/datastore/datastore-preferences-rxjava3/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/datastore/datastore-preferences/lint-baseline.xml b/datastore/datastore-preferences/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/datastore/datastore-preferences/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/datastore/datastore-proto/lint-baseline.xml b/datastore/datastore-proto/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/datastore/datastore-proto/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/datastore/datastore-rxjava2/lint-baseline.xml b/datastore/datastore-rxjava2/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/datastore/datastore-rxjava2/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/datastore/datastore-rxjava3/lint-baseline.xml b/datastore/datastore-rxjava3/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/datastore/datastore-rxjava3/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/docs/api_guidelines.md b/docs/api_guidelines.md
index f04be61..e2662a5 100644
--- a/docs/api_guidelines.md
+++ b/docs/api_guidelines.md
@@ -41,9 +41,8 @@
 *   `-core` for a low-level artifact that *may* contain public APIs but is
     primarily intended for use by other libraries in the group
 *   `-ktx` for an Kotlin artifact that exposes idiomatic Kotlin APIs as an
-    extension to a Java-only library
-*   `-java8` for a Java 8 artifact that exposes idiomatic Java 8 APIs as an
-    extension to a Java 7 library
+    extension to a Java-only library (see
+    [additional -ktx guidance](#module-ktx))
 *   `-<third-party>` for an artifact that integrates an optional third-party API
     surface, e.g. `-proto` or `-rxjava2`. Note that a major version is included
     in the sub-feature name for third-party API surfaces where the major version
@@ -177,6 +176,25 @@
 external developers and should be considered a last-resort when backporting
 behavior is not feasible.
 
+### Kotlin extension `-ktx` libraries {#module-ktx}
+
+New libraries should prefer Kotlin sources with built-in Java compatibility via
+`@JvmName` and other affordances of the Kotlin language; however, existing Java
+sourced libraries may benefit from extending their API surface with
+Kotlin-friendly APIs in a `-ktx` library.
+
+A Kotlin extension library **may only** provide extensions for a single base
+library's API surface and its name **must** match the base library exactly. For
+example, `work:work-ktx` may only provide extensions for APIs exposed by
+`work:work`.
+
+Additionally, an extension library **must** specify an `api`-type dependency on
+the base library and **must** be versioned and released identically to the base
+library.
+
+Kotlin extension libraries _should not_ expose new functionality; they should
+only provide Kotlin-friendly versions of existing Java-facing functionality.
+
 ## Platform compatibility API patterns {#platform-compatibility-apis}
 
 NOTE For all library APIs that wrap or provide parity with platform APIs,
@@ -1767,7 +1785,7 @@
 
 For library groups with strongly related samples that want to share code.
 
-Gradle project name: `:foo-library:samples`
+Gradle project name: `:foo-library:foo-library-samples`
 
 ```
 foo-library/
@@ -1780,10 +1798,18 @@
 
 For library groups with complex, relatively independent sub-libraries
 
-Gradle project name: `:foo-library:foo-module:samples`
+Gradle project name: `:foo-library:foo-module:foo-module-samples`
 
 ```
 foo-library/
   foo-module/
     samples/
 ```
+
+**Samples module configuration**
+
+Samples modules are published to GMaven so that they are available to Android
+Studio, which displays code in @Sample annotations as hover-over pop-ups.
+
+To achieve this, samples modules must declare the same MavenGroup and `publish`
+as the library(s) they are samples for.
diff --git a/docs/benchmarking.md b/docs/benchmarking.md
index 5fc0276..a4fabb1 100644
--- a/docs/benchmarking.md
+++ b/docs/benchmarking.md
@@ -133,11 +133,11 @@
 
 #### Device
 
-Get an API 28+ device (Or a rooted API 27 device). The rest of this section is
-about *why* those constraints exist, skip if not interested.
+Get an API 29+ device. The rest of this section is about *why* those constraints
+exist, skip if not interested.
 
 Simpleperf has restrictions about where it can be used - Jetpack Benchmark will
-only support API 28+ for now, due to
+only support API 29+ for now, due to
 [platform/simpleperf constraints](https://android.googlesource.com/platform/system/extras/+/master/simpleperf/doc/android_application_profiling.md#prepare-an-android-application)
 (see last subsection titled "If you want to profile Java code"). Summary is:
 
@@ -148,9 +148,13 @@
 -   26 (O): Requires compiled Java code, and wrapper script. We haven't
     investigated support.
 
--   27 (P): Can profile all Java code, but requires `userdebug`/rooted device
+-   27 (O.1): Can profile all Java code, but requires `userdebug`/rooted device
 
--   \>=28 (Q): Can profile all Java code, requires profileable (or
+-   28 (P): Can profile all Java code, requires debuggable (or
+    `userdebug`/rooted device, but this appears to not be supported by scripts
+    currently)
+
+-   \>=29 (Q): Can profile all Java code, requires profileable or debuggable (or
     `userdebug`/rooted device)
 
 We aren't planning to support profiling debuggable APK builds, since they're
diff --git a/docs/branching.md b/docs/branching.md
index 074a54c..dd23ec5 100644
--- a/docs/branching.md
+++ b/docs/branching.md
@@ -1,15 +1,20 @@
-# AndroidX Branch Workflow
+# Branch workflow
 
 [TOC]
 
-## Single Development Branch [androidx-main]
+## Single Development Branch [`aosp/androidx-main`]
 
-All feature development occurs in the public AndroidX master dev branch of the
+All feature development occurs in the public main development branch of the
 Android Open Source Project: `androidx-main`. This branch serves as the central
-location and source of truth for all AndroidX library source code. All alpha and
-beta version development, builds, and releases will be done ONLY in this branch.
+location and source of truth for all AndroidX library source code. All `alpha`
+and `beta` version work -- development, builds, and releases -- will be done
+ONLY in this branch.
 
-## Release Branches [androidx-\<feature\>-release]
+## Release Branches [`aosp/androidx-\<feature\>-release`]
+
+Release branches are used for stabilitization of a library and support of a
+previous stable release. With one development branch, this is how AndroidX
+provides support for the previous `rc` or stable version.
 
 When a library updates to rc (release-candidate) or stable, that library version
 will be snapped over to that library’s release branch. If that release branch
@@ -19,21 +24,13 @@
 
 Release branches have the following properties:
 
-*   A release branch will contain rc or stable versions of libraries.
-*   Release branches are internal branches.
-*   Release branches can **ONLY** be changed through
-    cherry-picks
-*   Bug-fixes and updates to that rc or stable version will need to be
-    individually cherry-picked
-*   No alpha or beta versions will exist in a release branch.
-*   Toolchain and other library wide changes to androidx-main will be synced to
-    each release branch.
+*   A release branch will contain `rc` or `stable` versions of libraries
+*   Release branches can **ONLY** be changed through cherry-picks
+*   Bug fixes and updates to `rc` or stable versions must be cherry-picked
+*   No `alpha` or `beta` versions will exist in a release branch.
+*   Toolchain and other library wide changes to `androidx-main` will be synced
+    to each release branch.
 *   Release branches will have the naming format
     `androidx-<feature-name>-release`
 *   Release branches will be re-snapped from `androidx-main` for each new minor
-    version release (for example, releasing 2.2.0-rc01 after 2.1.0)
-
-## Platform Developement and AndroidX [androidx-platform-dev]
-
-Platform specific development is done using our INTERNAL platform development
-branch `androidx-platform-dev`.
+    version release (for example, releasing `2.2.0-rc01` after `2.1.0`)
diff --git a/docs/kdoc_guidelines.md b/docs/kdoc_guidelines.md
index ef33b04..72f91eb 100644
--- a/docs/kdoc_guidelines.md
+++ b/docs/kdoc_guidelines.md
@@ -179,6 +179,27 @@
  */
 ```
 
+### Don't use angle brackets for `@param`
+
+Instead of:
+
+```kotlin {.bad}
+/**
+ * @param <T> my cool param
+ */
+```
+
+Do this:
+
+```kotlin {.good}
+/**
+ * * @param T my cool param
+ */
+```
+
+This syntax is correct is Javadoc, but angle brackets aren't used in KDoc
+([@param reference guide](https://kotlinlang.org/docs/kotlin-doc.html#param-name)).
+
 ## Javadoc - KDoc differences
 
 Some tags are shared between Javadoc and KDoc, such as `@param`, but there are
diff --git a/docs/onboarding.md b/docs/onboarding.md
index 5715972..f8dcafa 100644
--- a/docs/onboarding.md
+++ b/docs/onboarding.md
@@ -13,9 +13,10 @@
 
 ## Workstation setup {#setup}
 
-You will need to install the `repo` tool, which is used for Git branch and
-commit management. If you want to learn more about `repo`, see the
-[Repo Command Reference](https://source.android.com/setup/develop/repo).
+You will need to install the
+[`repo`](https://source.android.com/setup/develop#repo) tool, which is used for
+Git branch and commit management. If you want to learn more about `repo`, see
+the [Repo Command Reference](https://source.android.com/setup/develop/repo).
 
 ### Linux and MacOS {#setup-linux-mac}
 
@@ -210,7 +211,10 @@
 ```
 
 The `--cbr` switch automatically picks the current repo branch for upload. The
-`-t` switch sets the Gerrit topic to the branch name, e.g. `my-branch-name`.
+`-t` switch sets the Gerrit topic to the branch name, e.g. `my-branch-name`. You
+can refer to the
+[Android documentation](https://source.android.com/setup/create/coding-tasks#workflow)
+for a high level overview of this basic workflow.
 
 NOTE If you encounter issues with `repo upload`, consider running upload with
 trace enabled, e.g. `GIT_DAPPER_TRACE=1 repo --trace upload . --cbr -y`. These
diff --git a/docs/policies.md b/docs/policies.md
index 35b7aaa..ffe656f 100644
--- a/docs/policies.md
+++ b/docs/policies.md
@@ -15,7 +15,7 @@
 Libraries developed in AndroidX follow a consistent project naming and directory
 structure.
 
-Library groups should organize their modules into directories and module names
+Library groups should organize their projects into directories and project names
 (in brackets) as:
 
 ```
@@ -39,6 +39,27 @@
     testapp/ [navigation:integration-tests:testapp]
 ```
 
+### Project creator script {#project-creator}
+
+Note: The terms _project_, _module_, and _library_ are often used
+interchangeably within AndroidX, with project being the technical term used by
+Gradle to describe a build target, e.g. a library that maps to a single AAR.
+
+New projects can be created using our
+[project creation script](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:development/project-creator/?q=project-creator&ss=androidx%2Fplatform%2Fframeworks%2Fsupport)
+available in our repo.
+
+It will create a new project with the proper structure and configuration based
+on your project needs!
+
+To use it:
+
+```sh
+cd ~/androidx-main/framework/support && \
+cd development/project-creator && \
+./create_project.py androidx.foo foo-bar
+```
+
 ## Terminology {#terminology}
 
 **Artifact**
@@ -91,24 +112,6 @@
 }
 ```
 
-#### Finalizing for release {#finalizing-for-release}
-
-When the artifact is ready for release, its versioned API file should be
-finalized to ensure that the subsequent versioned release conforms to the
-versioning policies.
-
-```
-./gradlew <module>:finalizeApi
-```
-
-This will prevent any subsequent changes to the API surface until the artifact
-version is updated. To update the artifact version and allow changes within the
-semantic versioning contract, simply update the version string in the artifact's
-`build.gradle` (see [Workflow](#workflow) introduction).
-
-To avoid breaking the development workflow, we recommend that API finalization
-and version string updates be submitted as a single CL.
-
 ## Dependencies {#dependencies}
 
 Artifacts may depend on other artifacts within AndroidX as well as sanctioned
@@ -130,6 +133,9 @@
 only have implementation-type dependencies, your artifact may carry either the
 `alpha` or `beta` suffix.
 
+Note: This does not apply to test dependencies: suffixes of test dependencies do
+_not_ carry over to your artifact.
+
 #### Pinned versions {#pinned-versions}
 
 To avoid issues with dependency versioning, consider pinning your artifact's
diff --git a/docs/versioning.md b/docs/versioning.md
index 27efde7..3c1424a 100644
--- a/docs/versioning.md
+++ b/docs/versioning.md
@@ -239,13 +239,16 @@
 granted for new features, non-trivial API changes, significant refactorings, or
 any changes likely to introduce additional functional instability. Requests for
 exceptions **must** be accompanied by a justification explaining why the change
-cannot be made in a future minor version.
+cannot be made in a future minor version. This policy does not apply to
+additions of `@Experimental` APIs or changes to `@Experimental` APIs.
 
 #### Checklist for moving to `beta01` {#beta-checklist}
 
 *   API surface
     *   Entire API surface has been reviewed by API Council
     *   All APIs from alpha undergoing deprecate/remove cycle must be removed
+        *   The final removal of a `@Deprecated` API must occur in alpha, not in
+            Beta.
 *   Testing
     *   All public APIs are tested
     *   All pre-submit and post-submit tests are enabled (e.g. all suppressions
@@ -264,10 +267,13 @@
 *   API surface
     *   May not add, remove, or change APIs unless granted an exception by API
         Council following the beta API change exception request process
-    *   Must go through the full `@Deprecate` and hard-removal cycle in separate
-        `beta` releases for any exception-approved API removals or changes
-    *   May not remove `@Experimental` from experimental APIs, see previous item
-        regarding new APIs
+        *   Must go through the full `@Deprecate` and hard-removal cycle in
+            separate `beta` releases for any exception-approved API removals or
+            changes
+    *   May not remove `@Experimental` from experimental APIs, as this would
+        amount to an API addition
+    *   **May** add new `@Experimental` APIs and change existing `@Experimental`
+        APIs
 
 ### RC {#rc}
 
diff --git a/dynamic-animation/dynamic-animation-ktx/lint-baseline.xml b/dynamic-animation/dynamic-animation-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/dynamic-animation/dynamic-animation-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/emoji/bundled/lint-baseline.xml b/emoji/bundled/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/emoji/bundled/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/emoji2/emoji2-benchmark/lint-baseline.xml b/emoji2/emoji2-benchmark/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/emoji2/emoji2-benchmark/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/enterprise/feedback/lint-baseline.xml b/enterprise/feedback/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/enterprise/feedback/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/enterprise/feedback/testing/lint-baseline.xml b/enterprise/feedback/testing/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/enterprise/feedback/testing/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/fragment/fragment-ktx/lint-baseline.xml b/fragment/fragment-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/fragment/fragment-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/fragment/fragment-lint/lint-baseline.xml b/fragment/fragment-lint/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/fragment/fragment-lint/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/fragment/fragment-testing-lint/lint-baseline.xml b/fragment/fragment-testing-lint/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/fragment/fragment-testing-lint/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/fragment/fragment-testing/lint-baseline.xml b/fragment/fragment-testing/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/fragment/fragment-testing/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/fragment/fragment-truth/lint-baseline.xml b/fragment/fragment-truth/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/fragment/fragment-truth/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/hilt/hilt-common/lint-baseline.xml b/hilt/hilt-common/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/hilt/hilt-common/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/hilt/hilt-compiler/lint-baseline.xml b/hilt/hilt-compiler/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/hilt/hilt-compiler/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/hilt/hilt-navigation-fragment/lint-baseline.xml b/hilt/hilt-navigation-fragment/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/hilt/hilt-navigation-fragment/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/hilt/hilt-work/lint-baseline.xml b/hilt/hilt-work/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/hilt/hilt-work/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/hilt/integration-tests/viewmodelapp/lint-baseline.xml b/hilt/integration-tests/viewmodelapp/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/hilt/integration-tests/viewmodelapp/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/hilt/integration-tests/workerapp/lint-baseline.xml b/hilt/integration-tests/workerapp/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/hilt/integration-tests/workerapp/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/inspection/inspection-gradle-plugin/lint-baseline.xml b/inspection/inspection-gradle-plugin/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/inspection/inspection-gradle-plugin/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/interpolator/interpolator/lint-baseline.xml b/interpolator/interpolator/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/interpolator/interpolator/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/jetifier/jetifier/core/lint-baseline.xml b/jetifier/jetifier/core/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/jetifier/jetifier/core/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/jetifier/jetifier/preprocessor/lint-baseline.xml b/jetifier/jetifier/preprocessor/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/jetifier/jetifier/preprocessor/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/jetifier/jetifier/processor/lint-baseline.xml b/jetifier/jetifier/processor/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/jetifier/jetifier/processor/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/jetifier/jetifier/standalone/lint-baseline.xml b/jetifier/jetifier/standalone/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/jetifier/jetifier/standalone/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/leanback/leanback-paging/lint-baseline.xml b/leanback/leanback-paging/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/leanback/leanback-paging/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/leanback/leanback-tab/lint-baseline.xml b/leanback/leanback-tab/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/leanback/leanback-tab/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/integration-tests/incrementality/lint-baseline.xml b/lifecycle/integration-tests/incrementality/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/lifecycle/integration-tests/incrementality/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/integration-tests/kotlintestapp/lint-baseline.xml b/lifecycle/integration-tests/kotlintestapp/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/lifecycle/integration-tests/kotlintestapp/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/lifecycle-common-java8/lint-baseline.xml b/lifecycle/lifecycle-common-java8/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/lifecycle/lifecycle-common-java8/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/lifecycle-compiler/lint-baseline.xml b/lifecycle/lifecycle-compiler/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/lifecycle/lifecycle-compiler/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/lifecycle-livedata-core-ktx-lint/lint-baseline.xml b/lifecycle/lifecycle-livedata-core-ktx-lint/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/lifecycle/lifecycle-livedata-core-ktx-lint/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/lifecycle-livedata-core-ktx/lint-baseline.xml b/lifecycle/lifecycle-livedata-core-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/lifecycle/lifecycle-livedata-core-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/lifecycle-livedata-core-truth/lint-baseline.xml b/lifecycle/lifecycle-livedata-core-truth/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/lifecycle/lifecycle-livedata-core-truth/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/lifecycle-reactivestreams-ktx/lint-baseline.xml b/lifecycle/lifecycle-reactivestreams-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/lifecycle/lifecycle-reactivestreams-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/lifecycle-runtime-ktx-lint/lint-baseline.xml b/lifecycle/lifecycle-runtime-ktx-lint/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/lifecycle/lifecycle-runtime-ktx-lint/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/lifecycle-runtime-ktx/lint-baseline.xml b/lifecycle/lifecycle-runtime-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/lifecycle/lifecycle-runtime-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/lifecycle-runtime-testing/lint-baseline.xml b/lifecycle/lifecycle-runtime-testing/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/lifecycle/lifecycle-runtime-testing/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/lifecycle-service/lint-baseline.xml b/lifecycle/lifecycle-service/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/lifecycle/lifecycle-service/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/lifecycle-viewmodel-ktx/lint-baseline.xml b/lifecycle/lifecycle-viewmodel-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/lifecycle/lifecycle-viewmodel-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/lifecycle/lifecycle-viewmodel/lint-baseline.xml b/lifecycle/lifecycle-viewmodel/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/lifecycle/lifecycle-viewmodel/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/lint-checks/integration-tests/build.gradle b/lint-checks/integration-tests/build.gradle
index a738ab8..c7f4c61 100644
--- a/lint-checks/integration-tests/build.gradle
+++ b/lint-checks/integration-tests/build.gradle
@@ -14,11 +14,6 @@
  * limitations under the License.
  */
 
-import androidx.build.AndroidXGradlePropertiesKt
-import androidx.build.BuildOnServerKt
-import androidx.build.StudioType
-import androidx.build.dependencyTracker.AffectedModuleDetector
-import androidx.build.uptodatedness.EnableCachingKt
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
 import static androidx.build.dependencies.DependenciesKt.KOTLIN_STDLIB
@@ -84,36 +79,3 @@
         }
     }
 }
-
-def lintOutputFile = project.file("${buildDir}/reports/lint-results-debug.xml")
-def lintOutputFileNormalized = project.file("${buildDir}/lint-results-normalized/lint-results-debug.xml.normalized")
-
-def normalizeLintOutput = tasks.register("normalizeLintOutput", Copy) {
-    def supportRootFolder = project.rootProject.ext.supportRootFolder
-    from(lintOutputFile) {
-        filter { line ->
-            return line.replace(supportRootFolder.getAbsolutePath(), "\$SUPPORT")
-        }
-    }
-    into(lintOutputFileNormalized.parentFile)
-    rename(".*", lintOutputFileNormalized.name)
-    dependsOn("lintDebug")
-}
-
-def validateLint = tasks.register("validateLint", CompareFilesTask) { task ->
-    task.actualFile = lintOutputFileNormalized
-    // Make validateLint a no-op, but still build and run lint itself on playground builds.
-    // Due to b/186918949, expected-lint-results.xml provides the incorrect output for playground
-    // builds, causing lint-checks:integration-tests:validateLint to fail.
-    def studioType = AndroidXGradlePropertiesKt.studioType(project.rootProject)
-    if (studioType == StudioType.PLAYGROUND) {
-        task.expectedFile = lintOutputFileNormalized
-    } else {
-        task.expectedFile = project.file("expected-lint-results.xml")
-    }
-    EnableCachingKt.cacheEvenIfNoOutputs(task)
-    dependsOn(normalizeLintOutput)
-    AffectedModuleDetector.configureTaskGuard(task)
-}
-
-BuildOnServerKt.addToBuildOnServer(project, validateLint)
diff --git a/lint-checks/integration-tests/expected-lint-results.xml b/lint-checks/integration-tests/expected-lint-results.xml
index 79b7190..698b8cd 100644
--- a/lint-checks/integration-tests/expected-lint-results.xml
+++ b/lint-checks/integration-tests/expected-lint-results.xml
@@ -20,6 +20,22 @@
     <issue
         id="ClassVerificationFailure"
         severity="Error"
+        message="This call references a method added in API level 30; however, the containing class androidx.AutofixUnsafeConstructorReferenceJava is reachable from earlier API levels and will fail run-time class verification."
+        category="Correctness"
+        priority="5"
+        summary="Even in cases where references to new APIs are gated on SDK_INT checks, run-time class verification will still fail on references to APIs that may not be available at run time, including platform APIs introduced after a library&apos;s minSdkVersion."
+        explanation="The Java language requires a virtual machine to verify the class files it&#xA;loads and executes. A class may fail verification for a wide variety of&#xA;reasons, but in practice it‘s usually because the class’s code refers to&#xA;unknown classes or methods.&#xA;&#xA;References to APIs added after a library&apos;s minSdkVersion -- regardless of&#xA;any surrounding version checks -- will fail run-time class verification if&#xA;the API does not exist on the device, leading to reduced run-time&#xA;performance.&#xA;&#xA;Gating references on SDK checks alone DOES NOT address class verification&#xA;failures.&#xA;&#xA;To prevent class verification failures, references to new APIs must be&#xA;moved to inner classes that are only initialized inside of an appropriate&#xA;SDK check.&#xA;&#xA;For example, if our minimum SDK is 14 and platform method a.x(params...)&#xA;was added in SDK 16, the method call must be moved to an inner class like:&#xA;&#xA;@RequiresApi(16)&#xA;private static class Api16Impl{&#xA;  @DoNotInline&#xA;  static void callX(params...) {&#xA;    a.x(params...);&#xA;  }&#xA;}&#xA;&#xA;The call site is changed from a.x(params...) to Api16Impl.callX(params).&#xA;&#xA;Since ART will only try to optimize Api16Impl when it&apos;s on the execution&#xA;path, we are guaranteed to have a.x(...) available.&#xA;&#xA;In addition, optimizers like R8 or Proguard may inline the method in the&#xA;separate class and replace the wrapper call with the actual call, so you&#xA;must disable inlining using the @DoNotInline annotation.&#xA;&#xA;Failure to do the above may result in overall performance degradation."
+        errorLine1="            AccessibilityNodeInfo node = new AccessibilityNodeInfo(new View(context), 1);"
+        errorLine2="                                         ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="$SUPPORT/lint-checks/integration-tests/src/main/java/androidx/AutofixUnsafeConstructorReferenceJava.java"
+            line="35"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="ClassVerificationFailure"
+        severity="Error"
         message="This call references a method added in API level 23; however, the containing class androidx.AutofixUnsafeGenericMethodReferenceJava is reachable from earlier API levels and will fail run-time class verification."
         category="Correctness"
         priority="5"
diff --git a/lint-checks/tests/lint-baseline.xml b/lint-checks/tests/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/lint-checks/tests/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/loader/loader-ktx/lint-baseline.xml b/loader/loader-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/loader/loader-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/loader/loader/lint-baseline.xml b/loader/loader/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/loader/loader/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/localbroadcastmanager/localbroadcastmanager/lint-baseline.xml b/localbroadcastmanager/localbroadcastmanager/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/localbroadcastmanager/localbroadcastmanager/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/media/version-compat-tests/current/client/lint-baseline.xml b/media/version-compat-tests/current/client/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/media/version-compat-tests/current/client/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/media/version-compat-tests/current/service/lint-baseline.xml b/media/version-compat-tests/current/service/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/media/version-compat-tests/current/service/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/media/version-compat-tests/previous/client/lint-baseline.xml b/media/version-compat-tests/previous/client/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/media/version-compat-tests/previous/client/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/media/version-compat-tests/previous/service/lint-baseline.xml b/media/version-compat-tests/previous/service/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/media/version-compat-tests/previous/service/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/media2/media2-exoplayer/lint-baseline.xml b/media2/media2-exoplayer/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/media2/media2-exoplayer/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/media2/media2-session/version-compat-tests/current/client/lint-baseline.xml b/media2/media2-session/version-compat-tests/current/client/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/media2/media2-session/version-compat-tests/current/client/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/media2/media2-session/version-compat-tests/current/service/lint-baseline.xml b/media2/media2-session/version-compat-tests/current/service/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/media2/media2-session/version-compat-tests/current/service/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/media2/media2-session/version-compat-tests/previous/client/lint-baseline.xml b/media2/media2-session/version-compat-tests/previous/client/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/media2/media2-session/version-compat-tests/previous/client/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/media2/media2-session/version-compat-tests/previous/service/lint-baseline.xml b/media2/media2-session/version-compat-tests/previous/service/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/media2/media2-session/version-compat-tests/previous/service/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/benchmark/lint-baseline.xml b/navigation/benchmark/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/navigation/benchmark/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-common-ktx/lint-baseline.xml b/navigation/navigation-common-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/navigation/navigation-common-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-common/api/current.txt b/navigation/navigation-common/api/current.txt
index 3b56519..5f8904b 100644
--- a/navigation/navigation-common/api/current.txt
+++ b/navigation/navigation-common/api/current.txt
@@ -302,7 +302,6 @@
   @androidx.navigation.Navigator.Name("navigation") public class NavGraphNavigator extends androidx.navigation.Navigator<androidx.navigation.NavGraph> {
     ctor public NavGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider);
     method public androidx.navigation.NavGraph createDestination();
-    method public androidx.navigation.NavDestination? navigate(androidx.navigation.NavGraph destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
   }
 
   public final class NavOptions {
diff --git a/navigation/navigation-common/api/public_plus_experimental_current.txt b/navigation/navigation-common/api/public_plus_experimental_current.txt
index 4d3a4dc..5159fc4 100644
--- a/navigation/navigation-common/api/public_plus_experimental_current.txt
+++ b/navigation/navigation-common/api/public_plus_experimental_current.txt
@@ -343,7 +343,6 @@
   @androidx.navigation.Navigator.Name("navigation") public class NavGraphNavigator extends androidx.navigation.Navigator<androidx.navigation.NavGraph> {
     ctor public NavGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider);
     method public androidx.navigation.NavGraph createDestination();
-    method public androidx.navigation.NavDestination? navigate(androidx.navigation.NavGraph destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
   }
 
   public final class NavOptions {
diff --git a/navigation/navigation-common/api/restricted_current.txt b/navigation/navigation-common/api/restricted_current.txt
index 3b56519..5f8904b 100644
--- a/navigation/navigation-common/api/restricted_current.txt
+++ b/navigation/navigation-common/api/restricted_current.txt
@@ -302,7 +302,6 @@
   @androidx.navigation.Navigator.Name("navigation") public class NavGraphNavigator extends androidx.navigation.Navigator<androidx.navigation.NavGraph> {
     ctor public NavGraphNavigator(androidx.navigation.NavigatorProvider navigatorProvider);
     method public androidx.navigation.NavGraph createDestination();
-    method public androidx.navigation.NavDestination? navigate(androidx.navigation.NavGraph destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
   }
 
   public final class NavOptions {
diff --git a/navigation/navigation-common/build.gradle b/navigation/navigation-common/build.gradle
index 5ecb6d0..fe1af8a2 100644
--- a/navigation/navigation-common/build.gradle
+++ b/navigation/navigation-common/build.gradle
@@ -36,6 +36,8 @@
     implementation("androidx.collection:collection-ktx:1.1.0")
 
     api(KOTLIN_STDLIB)
+    testImplementation(project(":navigation:navigation-testing"))
+    testImplementation("androidx.arch.core:core-testing:2.1.0")
     testImplementation(JUNIT)
     testImplementation(MOCKITO_CORE)
     testImplementation(TRUTH)
diff --git a/navigation/navigation-common/lint-baseline.xml b/navigation/navigation-common/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/navigation/navigation-common/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-common/src/main/java/androidx/navigation/NavGraphNavigator.kt b/navigation/navigation-common/src/main/java/androidx/navigation/NavGraphNavigator.kt
index 0527a9b..4b58555 100644
--- a/navigation/navigation-common/src/main/java/androidx/navigation/NavGraphNavigator.kt
+++ b/navigation/navigation-common/src/main/java/androidx/navigation/NavGraphNavigator.kt
@@ -15,9 +15,6 @@
  */
 package androidx.navigation
 
-import android.os.Bundle
-import java.lang.IllegalArgumentException
-
 /**
  * A Navigator built specifically for [NavGraph] elements. Handles navigating to the
  * correct destination when the NavGraph is the target of navigation actions.
@@ -44,11 +41,22 @@
      * @throws IllegalArgumentException if given destination is not a child of the current navgraph
      */
     override fun navigate(
-        destination: NavGraph,
-        args: Bundle?,
+        entries: List<NavBackStackEntry>,
         navOptions: NavOptions?,
         navigatorExtras: Extras?
-    ): NavDestination? {
+    ) {
+        for (entry in entries) {
+            navigate(entry, navOptions, navigatorExtras)
+        }
+    }
+
+    private fun navigate(
+        entry: NavBackStackEntry,
+        navOptions: NavOptions?,
+        navigatorExtras: Extras?
+    ) {
+        val destination = entry.destination as NavGraph
+        val args = entry.arguments
         val startId = destination.startDestinationId
         val startRoute = destination.startDestinationRoute
         check(startId != 0 || startRoute != null) {
@@ -68,15 +76,10 @@
         val navigator = navigatorProvider.getNavigator<Navigator<NavDestination>>(
             startDestination.navigatorName
         )
-        return navigator.navigate(
+        val startDestinationEntry = state.createBackStackEntry(
             startDestination,
-            startDestination.addInDefaultArgs(args),
-            navOptions,
-            navigatorExtras
+            startDestination.addInDefaultArgs(args)
         )
-    }
-
-    override fun popBackStack(): Boolean {
-        return true
+        navigator.navigate(listOf(startDestinationEntry), navOptions, navigatorExtras)
     }
 }
\ No newline at end of file
diff --git a/navigation/navigation-common/src/test/java/androidx/navigation/NavGraphNavigatorTest.kt b/navigation/navigation-common/src/test/java/androidx/navigation/NavGraphNavigatorTest.kt
index be1b914..5cd574a 100644
--- a/navigation/navigation-common/src/test/java/androidx/navigation/NavGraphNavigatorTest.kt
+++ b/navigation/navigation-common/src/test/java/androidx/navigation/NavGraphNavigatorTest.kt
@@ -17,9 +17,11 @@
 package androidx.navigation
 
 import androidx.annotation.IdRes
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule
+import androidx.navigation.testing.TestNavigatorState
 import com.google.common.truth.Truth.assertThat
-import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Before
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -34,8 +36,13 @@
         private const val SECOND_DESTINATION_ID = 2
     }
 
+    @get:Rule
+    val instantTaskExecutorRule = InstantTaskExecutorRule()
+
     private lateinit var provider: NavigatorProvider
+    private lateinit var noOpState: TestNavigatorState
     private lateinit var noOpNavigator: NoOpNavigator
+    private lateinit var navGraphState: TestNavigatorState
     private lateinit var navGraphNavigator: NavGraphNavigator
 
     @Before
@@ -48,6 +55,10 @@
                 }
             )
         }
+        noOpState = TestNavigatorState()
+        noOpNavigator.onAttach(noOpState)
+        navGraphState = TestNavigatorState()
+        navGraphNavigator.onAttach(navGraphState)
     }
 
     private fun createFirstDestination() = noOpNavigator.createDestination().apply {
@@ -74,92 +85,17 @@
             id = 2 // can't match id of first destination or the start destination
             setStartDestination(0)
         }
-        navGraphNavigator.navigate(graph, null, null, null)
+        val entry = navGraphState.createBackStackEntry(graph, null)
+        navGraphNavigator.navigate(listOf(entry), null, null)
     }
 
     @Test
     fun navigate() {
         val destination = createFirstDestination()
         val graph = createGraphWithDestination(destination)
-        assertThat(navGraphNavigator.navigate(graph, null, null, null))
-            .isEqualTo(destination)
-    }
-
-    @Test
-    fun navigateThenPop() {
-        val destination = createFirstDestination()
-        val graph = createGraphWithDestination(destination)
-        assertThat(navGraphNavigator.navigate(graph, null, null, null))
-            .isEqualTo(destination)
-        val success = navGraphNavigator.popBackStack()
-        assertWithMessage("popBackStack should return true")
-            .that(success)
-            .isTrue()
-    }
-
-    @Test
-    fun navigateSingleTopOnEmptyStack() {
-        val destination = createFirstDestination()
-        val graph = createGraphWithDestination(destination)
-        // singleTop should still show as added on an empty stack
-        assertThat(
-            navGraphNavigator.navigate(
-                graph, null,
-                NavOptions.Builder().setLaunchSingleTop(true).build(), null
-            )
-        )
-            .isEqualTo(destination)
-    }
-
-    @Test
-    fun navigateSingleTop() {
-        val destination = createFirstDestination()
-        val graph = createGraphWithDestination(destination)
-        assertThat(navGraphNavigator.navigate(graph, null, null, null))
-            .isEqualTo(destination)
-        assertThat(
-            navGraphNavigator.navigate(
-                graph, null,
-                NavOptions.Builder().setLaunchSingleTop(true).build(), null
-            )
-        )
-            .isEqualTo(destination)
-    }
-
-    @Test
-    fun navigateSingleTopNotTop() {
-        val destination = createFirstDestination()
-        val graph = createGraphWithDestination(destination)
-        val secondDestination = createSecondDestination()
-        val secondGraph = createGraphWithDestination(secondDestination).apply {
-            id = SECOND_DESTINATION_ID
-        }
-        assertThat(navGraphNavigator.navigate(graph, null, null, null))
-            .isEqualTo(destination)
-        assertThat(
-            navGraphNavigator.navigate(
-                secondGraph, null,
-                NavOptions.Builder().setLaunchSingleTop(true).build(), null
-            )
-        )
-            .isEqualTo(secondDestination)
-    }
-
-    @Test
-    fun navigateSingleTopNested() {
-        val destination = createFirstDestination()
-        val nestedGraph = createGraphWithDestination(destination).apply {
-            id = FIRST_DESTINATION_ID
-        }
-        val graph = createGraphWithDestination(nestedGraph)
-        assertThat(navGraphNavigator.navigate(graph, null, null, null))
-            .isEqualTo(destination)
-        assertThat(
-            navGraphNavigator.navigate(
-                graph, null,
-                NavOptions.Builder().setLaunchSingleTop(true).build(), null
-            )
-        )
-            .isEqualTo(destination)
+        val entry = navGraphState.createBackStackEntry(graph, null)
+        navGraphNavigator.navigate(listOf(entry), null, null)
+        assertThat(noOpState.backStack.value.map { it.destination })
+            .containsExactly(destination)
     }
 }
diff --git a/navigation/navigation-dynamic-features-fragment/lint-baseline.xml b/navigation/navigation-dynamic-features-fragment/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/navigation/navigation-dynamic-features-fragment/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigator.kt b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigator.kt
index 574c877..a3ac6d7 100644
--- a/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigator.kt
+++ b/navigation/navigation-dynamic-features-fragment/src/main/java/androidx/navigation/dynamicfeatures/fragment/DynamicFragmentNavigator.kt
@@ -17,11 +17,10 @@
 package androidx.navigation.dynamicfeatures.fragment
 
 import android.content.Context
-import android.os.Bundle
 import android.util.AttributeSet
 import androidx.core.content.withStyledAttributes
 import androidx.fragment.app.FragmentManager
-import androidx.navigation.NavDestination
+import androidx.navigation.NavBackStackEntry
 import androidx.navigation.NavOptions
 import androidx.navigation.Navigator
 import androidx.navigation.NavigatorProvider
@@ -43,21 +42,32 @@
     override fun createDestination(): Destination = Destination(this)
 
     override fun navigate(
-        destination: FragmentNavigator.Destination,
-        args: Bundle?,
+        entries: List<NavBackStackEntry>,
         navOptions: NavOptions?,
         navigatorExtras: Navigator.Extras?
-    ): NavDestination? {
+    ) {
+        for (entry in entries) {
+            navigate(entry, navOptions, navigatorExtras)
+        }
+    }
+
+    private fun navigate(
+        entry: NavBackStackEntry,
+        navOptions: NavOptions?,
+        navigatorExtras: Navigator.Extras?
+    ) {
+        val destination = entry.destination
+        val args = entry.arguments
         val extras = navigatorExtras as? DynamicExtras
         if (destination is Destination) {
             val moduleName = destination.moduleName
             if (moduleName != null && installManager.needsInstall(moduleName)) {
-                return installManager.performInstall(destination, args, extras, moduleName)
+                installManager.performInstall(destination, args, extras, moduleName)
+                return
             }
         }
-        return super.navigate(
-            destination,
-            args,
+        super.navigate(
+            listOf(entry),
             navOptions,
             if (extras != null) extras.destinationExtras else navigatorExtras
         )
diff --git a/navigation/navigation-dynamic-features-runtime/build.gradle b/navigation/navigation-dynamic-features-runtime/build.gradle
index 2b45ff2..09812400 100644
--- a/navigation/navigation-dynamic-features-runtime/build.gradle
+++ b/navigation/navigation-dynamic-features-runtime/build.gradle
@@ -37,6 +37,8 @@
     api(PLAY_CORE)
     api(KOTLIN_STDLIB)
 
+    testImplementation(project(":navigation:navigation-testing"))
+    testImplementation("androidx.arch.core:core-testing:2.1.0")
     testImplementation(ANDROIDX_TEST_CORE)
     testImplementation(ANDROIDX_TEST_EXT_JUNIT)
     testImplementation(ANDROIDX_TEST_RUNNER)
diff --git a/navigation/navigation-dynamic-features-runtime/lint-baseline.xml b/navigation/navigation-dynamic-features-runtime/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/navigation/navigation-dynamic-features-runtime/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicGraphNavigator.kt b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicGraphNavigator.kt
index 04ec5fa..1aa62d6 100644
--- a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicGraphNavigator.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicGraphNavigator.kt
@@ -21,6 +21,7 @@
 import android.util.AttributeSet
 import androidx.annotation.RestrictTo
 import androidx.core.content.withStyledAttributes
+import androidx.navigation.NavBackStackEntry
 import androidx.navigation.NavDestination
 import androidx.navigation.NavGraph
 import androidx.navigation.NavGraphNavigator
@@ -58,20 +59,32 @@
      * module has successfully been installed.
      */
     override fun navigate(
-        destination: NavGraph,
-        args: Bundle?,
+        entries: List<NavBackStackEntry>,
         navOptions: NavOptions?,
         navigatorExtras: Extras?
-    ): NavDestination? {
+    ) {
+        for (entry in entries) {
+            navigate(entry, navOptions, navigatorExtras)
+        }
+    }
+
+    private fun navigate(
+        entry: NavBackStackEntry,
+        navOptions: NavOptions?,
+        navigatorExtras: Extras?
+    ) {
+        val destination = entry.destination
+        val args = entry.arguments
         val extras = if (navigatorExtras is DynamicExtras) navigatorExtras else null
         if (destination is DynamicNavGraph) {
             val moduleName = destination.moduleName
             if (moduleName != null && installManager.needsInstall(moduleName)) {
-                return installManager.performInstall(destination, args, extras, moduleName)
+                installManager.performInstall(destination, args, extras, moduleName)
+                return
             }
         }
-        return super.navigate(
-            destination, args, navOptions,
+        super.navigate(
+            listOf(entry), navOptions,
             if (extras != null) extras.destinationExtras else navigatorExtras
         )
     }
@@ -110,7 +123,7 @@
     internal fun navigateToProgressDestination(
         dynamicNavGraph: DynamicNavGraph,
         progressArgs: Bundle?
-    ): NavDestination? {
+    ) {
         var progressDestinationId = dynamicNavGraph.progressDestination
         if (progressDestinationId == 0) {
             progressDestinationId = installDefaultProgressDestination(dynamicNavGraph)
@@ -124,7 +137,8 @@
         val navigator = navigatorProvider.getNavigator<Navigator<NavDestination>>(
             progressDestination.navigatorName
         )
-        return navigator.navigate(progressDestination, progressArgs, null, null)
+        val entry = state.createBackStackEntry(progressDestination, progressArgs)
+        navigator.navigate(listOf(entry), null, null)
     }
 
     /**
diff --git a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicInstallManager.kt b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicInstallManager.kt
index 0d14629e..eab3688 100644
--- a/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicInstallManager.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/main/java/androidx/navigation/dynamicfeatures/DynamicInstallManager.kt
@@ -79,8 +79,9 @@
             val dynamicNavGraph = DynamicNavGraph.getOrThrow(destination)
             val navigator: Navigator<*> =
                 dynamicNavGraph.navigatorProvider[dynamicNavGraph.navigatorName]
-            return if (navigator is DynamicGraphNavigator) {
+            if (navigator is DynamicGraphNavigator) {
                 navigator.navigateToProgressDestination(dynamicNavGraph, progressArgs)
+                return null
             } else {
                 throw IllegalStateException(
                     "You must use a DynamicNavGraph to perform a module installation."
diff --git a/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicNavGraphTest.kt b/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicNavGraphTest.kt
index 73897f5..f48fdbb 100644
--- a/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicNavGraphTest.kt
+++ b/navigation/navigation-dynamic-features-runtime/src/test/java/androidx/navigation/dynamicfeatures/DynamicNavGraphTest.kt
@@ -16,14 +16,17 @@
 
 package androidx.navigation.dynamicfeatures
 
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule
 import androidx.navigation.NavDestination
 import androidx.navigation.NavigatorProvider
 import androidx.navigation.NoOpNavigator
 import androidx.navigation.dynamicfeatures.DynamicGraphNavigator.DynamicNavGraph
 import androidx.navigation.dynamicfeatures.shared.TestDynamicInstallManager
+import androidx.navigation.testing.TestNavigatorState
 import org.junit.Assert.assertNotNull
 import org.junit.Assert.assertTrue
 import org.junit.Before
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -31,10 +34,15 @@
 @RunWith(JUnit4::class)
 class DynamicNavGraphTest {
 
+    @get:Rule
+    val instantTaskExecutorRule = InstantTaskExecutorRule()
+
     private val progressId = 1
     private lateinit var provider: NavigatorProvider
+    private lateinit var navigatorState: TestNavigatorState
     private lateinit var navigator: DynamicGraphNavigator
     private lateinit var dynamicNavGraph: DynamicNavGraph
+    private lateinit var noOpState: TestNavigatorState
     private lateinit var noOpNavigator: NoOpNavigator
 
     @Before
@@ -46,6 +54,8 @@
             TestDynamicInstallManager()
         )
         provider.addNavigator(noOpNavigator)
+        noOpState = TestNavigatorState()
+        noOpNavigator.onAttach(noOpState)
         dynamicNavGraph = navigator.createDestination()
     }
 
@@ -61,7 +71,8 @@
                 id = progressId
             }
         )
-        val progressDestination = navigator.navigateToProgressDestination(dynamicNavGraph, null)
+        navigator.navigateToProgressDestination(dynamicNavGraph, null)
+        val progressDestination = noOpState.backStack.value.lastOrNull()?.destination
         assertNotNull(progressDestination)
         progressDestination?.let {
             DynamicNavGraph.getOrThrow(progressDestination)
@@ -82,7 +93,8 @@
                 id = progressId
             }
         )
-        val destination = navigator.navigateToProgressDestination(dynamicNavGraph, null)
+        navigator.navigateToProgressDestination(dynamicNavGraph, null)
+        val destination = noOpState.backStack.value.lastOrNull()?.destination
         assertTrue(destination?.parent is DynamicNavGraph)
     }
 
@@ -91,6 +103,8 @@
             navigator.installDefaultProgressDestination { it }
         }
         provider.addNavigator(navigator)
+        navigatorState = TestNavigatorState()
+        navigator.onAttach(navigatorState)
         dynamicNavGraph = navigator.createDestination()
     }
 }
diff --git a/navigation/navigation-fragment-ktx/lint-baseline.xml b/navigation/navigation-fragment-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/navigation/navigation-fragment-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-fragment/api/current.ignore b/navigation/navigation-fragment/api/current.ignore
index e92246d..bed10fd 100644
--- a/navigation/navigation-fragment/api/current.ignore
+++ b/navigation/navigation-fragment/api/current.ignore
@@ -5,5 +5,7 @@
 
 RemovedMethod: androidx.navigation.fragment.DialogFragmentNavigator#popBackStack():
     Removed method androidx.navigation.fragment.DialogFragmentNavigator.popBackStack()
+RemovedMethod: androidx.navigation.fragment.FragmentNavigator#navigate(androidx.navigation.fragment.FragmentNavigator.Destination, android.os.Bundle, androidx.navigation.NavOptions, androidx.navigation.Navigator.Extras):
+    Removed method androidx.navigation.fragment.FragmentNavigator.navigate(androidx.navigation.fragment.FragmentNavigator.Destination,android.os.Bundle,androidx.navigation.NavOptions,androidx.navigation.Navigator.Extras)
 RemovedMethod: androidx.navigation.fragment.FragmentNavigator#popBackStack():
     Removed method androidx.navigation.fragment.FragmentNavigator.popBackStack()
diff --git a/navigation/navigation-fragment/api/current.txt b/navigation/navigation-fragment/api/current.txt
index ac16ffe..5f8b262 100644
--- a/navigation/navigation-fragment/api/current.txt
+++ b/navigation/navigation-fragment/api/current.txt
@@ -45,7 +45,6 @@
     ctor public FragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager, int containerId);
     method public androidx.navigation.fragment.FragmentNavigator.Destination createDestination();
     method @Deprecated public androidx.fragment.app.Fragment instantiateFragment(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager, String className, android.os.Bundle? args);
-    method public androidx.navigation.NavDestination? navigate(androidx.navigation.fragment.FragmentNavigator.Destination destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
   }
 
   @androidx.navigation.NavDestination.ClassType(Fragment::class) public static class FragmentNavigator.Destination extends androidx.navigation.NavDestination {
diff --git a/navigation/navigation-fragment/api/public_plus_experimental_current.txt b/navigation/navigation-fragment/api/public_plus_experimental_current.txt
index ac16ffe..5f8b262 100644
--- a/navigation/navigation-fragment/api/public_plus_experimental_current.txt
+++ b/navigation/navigation-fragment/api/public_plus_experimental_current.txt
@@ -45,7 +45,6 @@
     ctor public FragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager, int containerId);
     method public androidx.navigation.fragment.FragmentNavigator.Destination createDestination();
     method @Deprecated public androidx.fragment.app.Fragment instantiateFragment(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager, String className, android.os.Bundle? args);
-    method public androidx.navigation.NavDestination? navigate(androidx.navigation.fragment.FragmentNavigator.Destination destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
   }
 
   @androidx.navigation.NavDestination.ClassType(Fragment::class) public static class FragmentNavigator.Destination extends androidx.navigation.NavDestination {
diff --git a/navigation/navigation-fragment/api/restricted_current.ignore b/navigation/navigation-fragment/api/restricted_current.ignore
index e92246d..bed10fd 100644
--- a/navigation/navigation-fragment/api/restricted_current.ignore
+++ b/navigation/navigation-fragment/api/restricted_current.ignore
@@ -5,5 +5,7 @@
 
 RemovedMethod: androidx.navigation.fragment.DialogFragmentNavigator#popBackStack():
     Removed method androidx.navigation.fragment.DialogFragmentNavigator.popBackStack()
+RemovedMethod: androidx.navigation.fragment.FragmentNavigator#navigate(androidx.navigation.fragment.FragmentNavigator.Destination, android.os.Bundle, androidx.navigation.NavOptions, androidx.navigation.Navigator.Extras):
+    Removed method androidx.navigation.fragment.FragmentNavigator.navigate(androidx.navigation.fragment.FragmentNavigator.Destination,android.os.Bundle,androidx.navigation.NavOptions,androidx.navigation.Navigator.Extras)
 RemovedMethod: androidx.navigation.fragment.FragmentNavigator#popBackStack():
     Removed method androidx.navigation.fragment.FragmentNavigator.popBackStack()
diff --git a/navigation/navigation-fragment/api/restricted_current.txt b/navigation/navigation-fragment/api/restricted_current.txt
index ac16ffe..5f8b262 100644
--- a/navigation/navigation-fragment/api/restricted_current.txt
+++ b/navigation/navigation-fragment/api/restricted_current.txt
@@ -45,7 +45,6 @@
     ctor public FragmentNavigator(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager, int containerId);
     method public androidx.navigation.fragment.FragmentNavigator.Destination createDestination();
     method @Deprecated public androidx.fragment.app.Fragment instantiateFragment(android.content.Context context, androidx.fragment.app.FragmentManager fragmentManager, String className, android.os.Bundle? args);
-    method public androidx.navigation.NavDestination? navigate(androidx.navigation.fragment.FragmentNavigator.Destination destination, android.os.Bundle? args, androidx.navigation.NavOptions? navOptions, androidx.navigation.Navigator.Extras? navigatorExtras);
   }
 
   @androidx.navigation.NavDestination.ClassType(Fragment::class) public static class FragmentNavigator.Destination extends androidx.navigation.NavDestination {
diff --git a/navigation/navigation-fragment/build.gradle b/navigation/navigation-fragment/build.gradle
index fa1132c..5837d97 100644
--- a/navigation/navigation-fragment/build.gradle
+++ b/navigation/navigation-fragment/build.gradle
@@ -31,6 +31,7 @@
     api(project(":navigation:navigation-runtime"))
 
     api(KOTLIN_STDLIB)
+    androidTestImplementation(project(":navigation:navigation-testing"))
     androidTestImplementation(projectOrArtifact(":fragment:fragment-testing"))
     androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
     androidTestImplementation(ANDROIDX_TEST_CORE)
diff --git a/navigation/navigation-fragment/lint-baseline.xml b/navigation/navigation-fragment/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/navigation/navigation-fragment/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
index 8b7571e..2498514 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/FragmentNavigatorTest.kt
@@ -22,9 +22,11 @@
 import androidx.fragment.app.FragmentFactory
 import androidx.fragment.app.FragmentManager
 import androidx.lifecycle.Lifecycle
+import androidx.navigation.NavBackStackEntry
 import androidx.navigation.NavOptions
 import androidx.navigation.fragment.test.EmptyFragment
 import androidx.navigation.fragment.test.R
+import androidx.navigation.testing.TestNavigatorState
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
@@ -38,6 +40,7 @@
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import kotlin.reflect.KClass
 
 @LargeTest
 @RunWith(AndroidJUnit4::class)
@@ -57,24 +60,26 @@
 
     private lateinit var emptyActivity: EmptyActivity
     private lateinit var fragmentManager: FragmentManager
+    private lateinit var navigatorState: TestNavigatorState
+    private lateinit var fragmentNavigator: FragmentNavigator
 
     @Before
     fun setup() {
         emptyActivity = activityRule.activity
         fragmentManager = emptyActivity.supportFragmentManager
+        navigatorState = TestNavigatorState()
+        fragmentNavigator = FragmentNavigator(emptyActivity, fragmentManager, R.id.container)
+        fragmentNavigator.onAttach(navigatorState)
     }
 
     @UiThreadTest
     @Test
     fun testNavigate() {
-        val fragmentNavigator = FragmentNavigator(emptyActivity, fragmentManager, R.id.container)
-        val destination = fragmentNavigator.createDestination().apply {
-            id = INITIAL_FRAGMENT
-            setClassName(EmptyFragment::class.java.name)
-        }
+        val entry = createBackStackEntry()
 
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        fragmentNavigator.navigate(listOf(entry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
         fragmentManager.executePendingTransactions()
         val fragment = fragmentManager.findFragmentById(R.id.container)
         assertNotNull("Fragment should be added", fragment)
@@ -92,14 +97,11 @@
     @Test
     fun testNavigateWithFragmentFactory() {
         fragmentManager.fragmentFactory = NonEmptyFragmentFactory()
-        val fragmentNavigator = FragmentNavigator(emptyActivity, fragmentManager, R.id.container)
-        val destination = fragmentNavigator.createDestination().apply {
-            id = INITIAL_FRAGMENT
-            setClassName(NonEmptyConstructorFragment::class.java.name)
-        }
+        val entry = createBackStackEntry(clazz = NonEmptyConstructorFragment::class)
 
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        fragmentNavigator.navigate(listOf(entry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
         fragmentManager.executePendingTransactions()
         val fragment = fragmentManager.findFragmentById(R.id.container)
         assertWithMessage("Fragment should be added")
@@ -116,14 +118,11 @@
     @UiThreadTest
     @Test
     fun testNavigateTwice() {
-        val fragmentNavigator = FragmentNavigator(emptyActivity, fragmentManager, R.id.container)
-        val destination = fragmentNavigator.createDestination().apply {
-            id = INITIAL_FRAGMENT
-            setClassName(EmptyFragment::class.java.name)
-        }
+        val entry = createBackStackEntry()
 
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        fragmentNavigator.navigate(listOf(entry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
         fragmentManager.executePendingTransactions()
         val fragment = fragmentManager.findFragmentById(R.id.container)
         assertNotNull("Fragment should be added", fragment)
@@ -137,9 +136,10 @@
         )
 
         // Now push a second fragment
-        destination.id = SECOND_FRAGMENT
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        val replacementEntry = createBackStackEntry(SECOND_FRAGMENT)
+        fragmentNavigator.navigate(listOf(replacementEntry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, replacementEntry).inOrder()
         fragmentManager.executePendingTransactions()
         val replacementFragment = fragmentManager.findFragmentById(R.id.container)
         assertNotNull("Replacement Fragment should be added", replacementFragment)
@@ -156,60 +156,55 @@
     @UiThreadTest
     @Test
     fun testNavigateWithPopUpToThenPop() {
-        val fragmentNavigator = FragmentNavigator(emptyActivity, fragmentManager, R.id.container)
-        val destination = fragmentNavigator.createDestination()
-        destination.id = INITIAL_FRAGMENT
-        destination.setClassName(EmptyFragment::class.java.name)
+        val entry = createBackStackEntry()
 
         // Push initial fragment
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        fragmentNavigator.navigate(listOf(entry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
         fragmentManager.executePendingTransactions()
 
         // Push a second fragment
-        destination.id = SECOND_FRAGMENT
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        val secondEntry = createBackStackEntry(SECOND_FRAGMENT)
+        fragmentNavigator.navigate(listOf(secondEntry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, secondEntry).inOrder()
         fragmentManager.executePendingTransactions()
 
         // Pop and then push third fragment, simulating popUpTo to initial.
-        val success = fragmentNavigator.popBackStack()
-        assertTrue("FragmentNavigator should return true when popping the third fragment", success)
-        destination.id = THIRD_FRAGMENT
-        assertThat(
-            fragmentNavigator.navigate(
-                destination, null,
-                NavOptions.Builder().setPopUpTo(INITIAL_FRAGMENT, false).build(), null
-            )
-        )
-            .isEqualTo(destination)
+        fragmentNavigator.popBackStack(secondEntry, false)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
+        val thirdEntry = createBackStackEntry(THIRD_FRAGMENT)
+        fragmentNavigator.navigate(listOf(thirdEntry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, thirdEntry).inOrder()
         fragmentManager.executePendingTransactions()
 
         // Now pop the Fragment
-        val popped = fragmentNavigator.popBackStack()
-        assertTrue("FragmentNavigator should return true when popping the third fragment", popped)
+        fragmentNavigator.popBackStack(thirdEntry, false)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
     }
 
     @UiThreadTest
     @Test
     fun testSingleTopInitial() {
-        val fragmentNavigator = FragmentNavigator(emptyActivity, fragmentManager, R.id.container)
-        val destination = fragmentNavigator.createDestination()
-        destination.setClassName(EmptyFragment::class.java.name)
+        val entry = createBackStackEntry()
 
-        fragmentNavigator.navigate(destination, null, null, null)
+        fragmentNavigator.navigate(listOf(entry), null, null)
         fragmentManager.executePendingTransactions()
         val fragment = fragmentManager.findFragmentById(R.id.container)
         assertNotNull("Fragment should be added", fragment)
         val lifecycle = fragment!!.lifecycle
 
-        assertThat(
-            fragmentNavigator.navigate(
-                destination, null,
-                NavOptions.Builder().setLaunchSingleTop(true).build(), null
-            )
+        fragmentNavigator.navigate(
+            listOf(entry),
+            NavOptions.Builder().setLaunchSingleTop(true).build(),
+            null
         )
-            .isNull()
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
         fragmentManager.executePendingTransactions()
         val replacementFragment = fragmentManager.findFragmentById(R.id.container)
         assertNotNull("Replacement Fragment should be added", replacementFragment)
@@ -234,13 +229,12 @@
     @UiThreadTest
     @Test
     fun testSingleTop() {
-        val fragmentNavigator = FragmentNavigator(emptyActivity, fragmentManager, R.id.container)
-        val destination = fragmentNavigator.createDestination()
-        destination.setClassName(EmptyFragment::class.java.name)
+        val entry = createBackStackEntry()
 
         // First push an initial Fragment
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        fragmentNavigator.navigate(listOf(entry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
         fragmentManager.executePendingTransactions()
         val initialFragment = fragmentManager.findFragmentById(R.id.container)
         assertWithMessage("Initial Fragment should be added")
@@ -248,9 +242,10 @@
             .isNotNull()
 
         // Now push the Fragment that we want to replace with a singleTop operation
-        destination.id = 1
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        val replacementEntry = createBackStackEntry(SECOND_FRAGMENT)
+        fragmentNavigator.navigate(listOf(replacementEntry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, replacementEntry).inOrder()
         fragmentManager.executePendingTransactions()
         val fragment = fragmentManager.findFragmentById(R.id.container)
         assertWithMessage("Fragment should be added")
@@ -258,13 +253,13 @@
             .isNotNull()
         val lifecycle = fragment!!.lifecycle
 
-        assertThat(
-            fragmentNavigator.navigate(
-                destination, null,
-                NavOptions.Builder().setLaunchSingleTop(true).build(), null
-            )
+        fragmentNavigator.navigate(
+            listOf(replacementEntry),
+            NavOptions.Builder().setLaunchSingleTop(true).build(),
+            null
         )
-            .isNull()
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, replacementEntry).inOrder()
         fragmentManager.executePendingTransactions()
         val replacementFragment = fragmentManager.findFragmentById(R.id.container)
         assertWithMessage("Replacement Fragment should be added")
@@ -283,8 +278,10 @@
             .that(lifecycle.currentState)
             .isEqualTo(Lifecycle.State.DESTROYED)
 
-        assertThat(fragmentNavigator.popBackStack())
-            .isTrue()
+        fragmentNavigator.popBackStack(replacementEntry, false)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
+
         fragmentManager.executePendingTransactions()
         assertWithMessage("Initial Fragment should be on top of back stack after pop")
             .that(fragmentManager.findFragmentById(R.id.container))
@@ -297,47 +294,37 @@
     @UiThreadTest
     @Test
     fun testPopInitial() {
-        val fragmentNavigator = FragmentNavigator(
-            emptyActivity,
-            fragmentManager, R.id.container
-        )
-        val destination = fragmentNavigator.createDestination()
-        destination.id = INITIAL_FRAGMENT
-        destination.setClassName(EmptyFragment::class.java.name)
+        val entry = createBackStackEntry()
 
         // First push an initial Fragment
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        fragmentNavigator.navigate(listOf(entry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
 
         // Now pop the initial Fragment
-        val popped = fragmentNavigator.popBackStack()
-        assertWithMessage(
-            "FragmentNavigator should return false when popping " +
-                "the initial Fragment"
-        )
-            .that(popped)
-            .isTrue()
+        fragmentNavigator.popBackStack(entry, false)
+        assertThat(navigatorState.backStack.value)
+            .isEmpty()
     }
 
     @UiThreadTest
     @Test
     fun testPop() {
-        val fragmentNavigator = FragmentNavigator(emptyActivity, fragmentManager, R.id.container)
-        val destination = fragmentNavigator.createDestination()
-        destination.id = INITIAL_FRAGMENT
-        destination.setClassName(EmptyFragment::class.java.name)
+        val entry = createBackStackEntry()
 
         // First push an initial Fragment
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        fragmentNavigator.navigate(listOf(entry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
         fragmentManager.executePendingTransactions()
         val fragment = fragmentManager.findFragmentById(R.id.container)
         assertNotNull("Fragment should be added", fragment)
 
         // Now push the Fragment that we want to pop
-        destination.id = SECOND_FRAGMENT
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        val replacementEntry = createBackStackEntry(SECOND_FRAGMENT)
+        fragmentNavigator.navigate(listOf(replacementEntry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, replacementEntry).inOrder()
         fragmentManager.executePendingTransactions()
         val replacementFragment = fragmentManager.findFragmentById(R.id.container)
         assertNotNull("Replacement Fragment should be added", replacementFragment)
@@ -351,9 +338,10 @@
         )
 
         // Now pop the Fragment
-        val popped = fragmentNavigator.popBackStack()
+        fragmentNavigator.popBackStack(replacementEntry, false)
         fragmentManager.executePendingTransactions()
-        assertTrue("FragmentNavigator should return true when popping a Fragment", popped)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
         assertEquals(
             "Fragment should be the primary navigation Fragment after pop",
             fragment, fragmentManager.primaryNavigationFragment
@@ -363,14 +351,12 @@
     @UiThreadTest
     @Test
     fun testPopWithSameDestinationTwice() {
-        val fragmentNavigator = FragmentNavigator(emptyActivity, fragmentManager, R.id.container)
-        val destination = fragmentNavigator.createDestination()
-        destination.id = INITIAL_FRAGMENT
-        destination.setClassName(EmptyFragment::class.java.name)
+        val entry = createBackStackEntry()
 
         // First push an initial Fragment
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        fragmentNavigator.navigate(listOf(entry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
         fragmentManager.executePendingTransactions()
         val fragment = fragmentManager.findFragmentById(R.id.container)
         assertWithMessage("Fragment should be added")
@@ -378,9 +364,10 @@
             .isNotNull()
 
         // Now push a second Fragment
-        destination.id = SECOND_FRAGMENT
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        val secondEntry = createBackStackEntry(SECOND_FRAGMENT)
+        fragmentNavigator.navigate(listOf(secondEntry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, secondEntry).inOrder()
         fragmentManager.executePendingTransactions()
         val replacementFragment = fragmentManager.findFragmentById(R.id.container)
         assertWithMessage("Replacement Fragment should be added")
@@ -392,8 +379,10 @@
 
         // Push the same Fragment a second time, creating a stack of two
         // identical Fragments
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        val replacementEntry = createBackStackEntry(SECOND_FRAGMENT)
+        fragmentNavigator.navigate(listOf(replacementEntry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, secondEntry, replacementEntry).inOrder()
         fragmentManager.executePendingTransactions()
         val fragmentToPop = fragmentManager.findFragmentById(R.id.container)
         assertWithMessage("Fragment to pop should be added")
@@ -404,11 +393,10 @@
             .isSameInstanceAs(fragmentToPop)
 
         // Now pop the Fragment
-        val popped = fragmentNavigator.popBackStack()
+        fragmentNavigator.popBackStack(replacementEntry, false)
         fragmentManager.executePendingTransactions()
-        assertWithMessage("FragmentNavigator should return true when popping a Fragment")
-            .that(popped)
-            .isTrue()
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, secondEntry).inOrder()
         assertWithMessage(
             "Replacement Fragment should be the primary navigation Fragment " +
                 "after pop"
@@ -420,22 +408,21 @@
     @UiThreadTest
     @Test
     fun testPopWithChildFragmentBackStack() {
-        val fragmentNavigator = FragmentNavigator(emptyActivity, fragmentManager, R.id.container)
-        val destination = fragmentNavigator.createDestination()
-        destination.id = INITIAL_FRAGMENT
-        destination.setClassName(EmptyFragment::class.java.name)
+        val entry = createBackStackEntry()
 
         // First push an initial Fragment
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        fragmentNavigator.navigate(listOf(entry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
         fragmentManager.executePendingTransactions()
         val fragment = fragmentManager.findFragmentById(R.id.container)
         assertNotNull("Fragment should be added", fragment)
 
         // Now push the Fragment that we want to pop
-        destination.id = SECOND_FRAGMENT
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        val replacementEntry = createBackStackEntry(SECOND_FRAGMENT)
+        fragmentNavigator.navigate(listOf(replacementEntry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, replacementEntry).inOrder()
         fragmentManager.executePendingTransactions()
         val replacementFragment = fragmentManager.findFragmentById(R.id.container)
         assertNotNull("Replacement Fragment should be added", replacementFragment)
@@ -458,9 +445,10 @@
         }
 
         // Now pop the Fragment
-        val popped = fragmentNavigator.popBackStack()
+        fragmentNavigator.popBackStack(replacementEntry, false)
         fragmentManager.executePendingTransactions()
-        assertTrue("FragmentNavigator should return true when popping a Fragment", popped)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
         assertEquals(
             "Fragment should be the primary navigation Fragment after pop",
             fragment, fragmentManager.primaryNavigationFragment
@@ -470,22 +458,19 @@
     @UiThreadTest
     @Test
     fun testDeepLinkPop() {
-        val fragmentNavigator = FragmentNavigator(emptyActivity, fragmentManager, R.id.container)
-        val destination = fragmentNavigator.createDestination()
-        destination.id = INITIAL_FRAGMENT
-        destination.setClassName(EmptyFragment::class.java.name)
+        val entry = createBackStackEntry()
+        val secondEntry = createBackStackEntry(SECOND_FRAGMENT)
 
         // First push two Fragments as our 'deep link'
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
-        destination.id = SECOND_FRAGMENT
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        fragmentNavigator.navigate(listOf(entry, secondEntry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, secondEntry)
 
         // Now push the Fragment that we want to pop
-        destination.id = THIRD_FRAGMENT
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
+        val thirdEntry = createBackStackEntry(THIRD_FRAGMENT)
+        fragmentNavigator.navigate(listOf(thirdEntry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, secondEntry, thirdEntry)
         fragmentManager.executePendingTransactions()
         val replacementFragment = fragmentManager.findFragmentById(R.id.container)
         assertNotNull("Replacement Fragment should be added", replacementFragment)
@@ -499,7 +484,7 @@
         )
 
         // Now pop the Fragment
-        fragmentNavigator.popBackStack()
+        fragmentNavigator.popBackStack(thirdEntry, false)
         fragmentManager.executePendingTransactions()
         val fragment = fragmentManager.findFragmentById(R.id.container)
         assertEquals(
@@ -510,156 +495,19 @@
 
     @UiThreadTest
     @Test
-    fun testDeepLinkPopWithSaveState() {
-        var fragmentNavigator = FragmentNavigator(
-            emptyActivity,
-            fragmentManager, R.id.container
-        )
-        val destination = fragmentNavigator.createDestination()
-        destination.id = INITIAL_FRAGMENT
-        destination.setClassName(EmptyFragment::class.java.name)
-
-        // First push two Fragments as our 'deep link'
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
-        destination.id = SECOND_FRAGMENT
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
-
-        // Now push the Fragment that we want to pop
-        destination.id = THIRD_FRAGMENT
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
-        fragmentManager.executePendingTransactions()
-        val replacementFragment = fragmentManager.findFragmentById(R.id.container)
-        assertNotNull("Replacement Fragment should be added", replacementFragment)
-        assertTrue(
-            "Replacement Fragment should be the correct type",
-            replacementFragment is EmptyFragment
-        )
-        assertEquals(
-            "Replacement Fragment should be the primary navigation Fragment",
-            replacementFragment, fragmentManager.primaryNavigationFragment
-        )
-
-        // Create a new FragmentNavigator, replacing the previous one
-        val savedState = fragmentNavigator.onSaveState() as Bundle
-        fragmentNavigator = FragmentNavigator(
-            emptyActivity,
-            fragmentManager, R.id.container
-        )
-        fragmentNavigator.onRestoreState(savedState)
-
-        // Now pop the Fragment
-        fragmentNavigator.popBackStack()
-        fragmentManager.executePendingTransactions()
-        val fragment = fragmentManager.findFragmentById(R.id.container)
-        assertEquals(
-            "Fragment should be the primary navigation Fragment after pop",
-            fragment, fragmentManager.primaryNavigationFragment
-        )
-    }
-
-    @UiThreadTest
-    @Test
-    fun testNavigateThenPopAfterSaveState() {
-        var fragmentNavigator = FragmentNavigator(
-            emptyActivity,
-            fragmentManager, R.id.container
-        )
-        val destination = fragmentNavigator.createDestination()
-        destination.id = INITIAL_FRAGMENT
-        destination.setClassName(EmptyFragment::class.java.name)
-
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
-        fragmentManager.executePendingTransactions()
-        var fragment = fragmentManager.findFragmentById(R.id.container)
-        assertNotNull("Fragment should be added", fragment)
-        assertEquals(
-            "Fragment should be the correct type",
-            EmptyFragment::class.java, fragment!!::class.java
-        )
-        assertEquals(
-            "Fragment should be the primary navigation Fragment",
-            fragment, fragmentManager.primaryNavigationFragment
-        )
-
-        // Now push a second fragment
-        destination.id = SECOND_FRAGMENT
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
-        fragmentManager.executePendingTransactions()
-        var replacementFragment = fragmentManager.findFragmentById(R.id.container)
-        assertNotNull("Replacement Fragment should be added", replacementFragment)
-        assertEquals(
-            "Replacement Fragment should be the correct type",
-            EmptyFragment::class.java, replacementFragment!!::class.java
-        )
-        assertEquals(
-            "Replacement Fragment should be the primary navigation Fragment",
-            replacementFragment, fragmentManager.primaryNavigationFragment
-        )
-
-        // Create a new FragmentNavigator, replacing the previous one
-        val savedState = fragmentNavigator.onSaveState() as Bundle
-        fragmentNavigator = FragmentNavigator(
-            emptyActivity,
-            fragmentManager, R.id.container
-        )
-        fragmentNavigator.onRestoreState(savedState)
-
-        // Now push a third fragment after the state save
-        destination.id = THIRD_FRAGMENT
-        assertThat(fragmentNavigator.navigate(destination, null, null, null))
-            .isEqualTo(destination)
-        fragmentManager.executePendingTransactions()
-        replacementFragment = fragmentManager.findFragmentById(R.id.container)
-        assertNotNull("Replacement Fragment should be added", replacementFragment)
-        assertTrue(
-            "Replacement Fragment should be the correct type",
-            replacementFragment is EmptyFragment
-        )
-        assertEquals(
-            "Replacement Fragment should be the primary navigation Fragment",
-            replacementFragment, fragmentManager.primaryNavigationFragment
-        )
-
-        // Now pop the Fragment
-        fragmentNavigator.popBackStack()
-        fragmentManager.executePendingTransactions()
-        fragment = fragmentManager.findFragmentById(R.id.container)
-        assertEquals(
-            "Fragment should be the primary navigation Fragment after pop",
-            fragment, fragmentManager.primaryNavigationFragment
-        )
-    }
-
-    @UiThreadTest
-    @Test
     fun testMultipleNavigateFragmentTransactionsThenPop() {
-        val fragmentNavigator = FragmentNavigator(
-            emptyActivity,
-            fragmentManager, R.id.container
-        )
-        val destination = fragmentNavigator.createDestination()
-        destination.setClassName(EmptyFragment::class.java.name)
-        val destination2 = fragmentNavigator.createDestination()
-        destination2.setClassName(Fragment::class.java.name)
+        val entry = createBackStackEntry()
+        val secondEntry = createBackStackEntry(SECOND_FRAGMENT, clazz = Fragment::class)
+        val thirdEntry = createBackStackEntry(THIRD_FRAGMENT)
 
         // Push 3 fragments without executing pending transactions.
-        destination.id = INITIAL_FRAGMENT
-        fragmentNavigator.navigate(destination, null, null, null)
-        destination2.id = SECOND_FRAGMENT
-        fragmentNavigator.navigate(destination2, null, null, null)
-        destination.id = THIRD_FRAGMENT
-        fragmentNavigator.navigate(destination, null, null, null)
+        fragmentNavigator.navigate(listOf(entry, secondEntry, thirdEntry), null, null)
 
         // Now pop the Fragment
-        val popped = fragmentNavigator.popBackStack()
+        fragmentNavigator.popBackStack(thirdEntry, false)
         fragmentManager.executePendingTransactions()
-        assertWithMessage("FragmentNavigator should return true when popping the third fragment")
-            .that(popped).isTrue()
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, secondEntry)
         // We should ensure the fragment manager is on the proper fragment at the end
         assertWithMessage("FragmentManager back stack should have only SECOND_FRAGMENT")
             .that(fragmentManager.backStackEntryCount)
@@ -672,36 +520,176 @@
     @UiThreadTest
     @Test
     fun testMultiplePopFragmentTransactionsThenPop() {
-        val fragmentNavigator = FragmentNavigator(
-            emptyActivity,
-            fragmentManager, R.id.container
-        )
-        val destination = fragmentNavigator.createDestination()
-        destination.setClassName(EmptyFragment::class.java.name)
+        val entry = createBackStackEntry()
+        val secondEntry = createBackStackEntry(SECOND_FRAGMENT)
+        val thirdEntry = createBackStackEntry(THIRD_FRAGMENT)
+        val fourthEntry = createBackStackEntry(FOURTH_FRAGMENT)
 
         // Push 4 fragments
-        destination.id = INITIAL_FRAGMENT
-        fragmentNavigator.navigate(destination, null, null, null)
-        destination.id = SECOND_FRAGMENT
-        fragmentNavigator.navigate(destination, null, null, null)
-        destination.id = THIRD_FRAGMENT
-        fragmentNavigator.navigate(destination, null, null, null)
-        destination.id = FOURTH_FRAGMENT
-        fragmentNavigator.navigate(destination, null, null, null)
+        fragmentNavigator.navigate(
+            listOf(entry, secondEntry, thirdEntry, fourthEntry),
+            null, null
+        )
         fragmentManager.executePendingTransactions()
 
         // Pop 2 fragments without executing pending transactions.
-        fragmentNavigator.popBackStack()
-        fragmentNavigator.popBackStack()
+        fragmentNavigator.popBackStack(thirdEntry, false)
 
-        val popped = fragmentNavigator.popBackStack()
+        fragmentNavigator.popBackStack(secondEntry, false)
         fragmentManager.executePendingTransactions()
-        assertTrue("FragmentNavigator should return true when popping the third fragment", popped)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
+    }
+
+    @UiThreadTest
+    @Test
+    fun testSaveRestoreState() {
+        val entry = createBackStackEntry()
+
+        // First push an initial Fragment
+        fragmentNavigator.navigate(listOf(entry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
+        fragmentManager.executePendingTransactions()
+        val fragment = fragmentManager.findFragmentById(R.id.container)
+        assertWithMessage("Fragment should be added")
+            .that(fragment)
+            .isNotNull()
+
+        // Now push the Fragment that we want to save
+        val replacementEntry = createBackStackEntry(SECOND_FRAGMENT, SavedStateFragment::class)
+        fragmentNavigator.navigate(listOf(replacementEntry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, replacementEntry).inOrder()
+        fragmentManager.executePendingTransactions()
+        val replacementFragment = fragmentManager.findFragmentById(R.id.container)
+        assertWithMessage("Replacement Fragment should be added")
+            .that(replacementFragment)
+            .isNotNull()
+        assertWithMessage("Replacement Fragment should be the correct type")
+            .that(replacementFragment)
+            .isInstanceOf(SavedStateFragment::class.java)
+        assertWithMessage("Replacement Fragment should be the primary navigation Fragment")
+            .that(fragmentManager.primaryNavigationFragment)
+            .isSameInstanceAs(replacementFragment)
+
+        // Save some state into the replacement fragment
+        (replacementFragment as SavedStateFragment).savedState = "test"
+
+        // Now save the Fragment
+        fragmentNavigator.popBackStack(replacementEntry, true)
+        fragmentManager.executePendingTransactions()
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
+        assertWithMessage("Fragment should be the primary navigation Fragment after pop")
+            .that(fragmentManager.primaryNavigationFragment)
+            .isSameInstanceAs(fragment)
+
+        // And now restore the fragment
+        val restoredEntry = navigatorState.restoreBackStackEntry(replacementEntry)
+        fragmentNavigator.navigate(
+            listOf(restoredEntry),
+            NavOptions.Builder().setRestoreState(true).build(), null
+        )
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, restoredEntry).inOrder()
+        fragmentManager.executePendingTransactions()
+        val restoredFragment = fragmentManager.findFragmentById(R.id.container)
+        assertWithMessage("Restored Fragment should be added")
+            .that(restoredFragment)
+            .isNotNull()
+        assertWithMessage("Restored Fragment should be the correct type")
+            .that(restoredFragment)
+            .isInstanceOf(SavedStateFragment::class.java)
+        assertWithMessage("Restored Fragment should be the primary navigation Fragment")
+            .that(fragmentManager.primaryNavigationFragment)
+            .isSameInstanceAs(restoredFragment)
+
+        assertWithMessage("Restored Fragment should have its state restored")
+            .that((restoredFragment as SavedStateFragment).savedState)
+            .isEqualTo("test")
+    }
+
+    @UiThreadTest
+    @Test
+    fun testSaveRestoreStateAfterSaveState() {
+        val entry = createBackStackEntry()
+
+        // First push an initial Fragment
+        fragmentNavigator.navigate(listOf(entry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
+        fragmentManager.executePendingTransactions()
+        val fragment = fragmentManager.findFragmentById(R.id.container)
+        assertWithMessage("Fragment should be added")
+            .that(fragment)
+            .isNotNull()
+
+        // Now push the Fragment that we want to save
+        val replacementEntry = createBackStackEntry(SECOND_FRAGMENT, SavedStateFragment::class)
+        fragmentNavigator.navigate(listOf(replacementEntry), null, null)
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, replacementEntry).inOrder()
+        fragmentManager.executePendingTransactions()
+        val replacementFragment = fragmentManager.findFragmentById(R.id.container)
+        assertWithMessage("Replacement Fragment should be added")
+            .that(replacementFragment)
+            .isNotNull()
+        assertWithMessage("Replacement Fragment should be the correct type")
+            .that(replacementFragment)
+            .isInstanceOf(SavedStateFragment::class.java)
+        assertWithMessage("Replacement Fragment should be the primary navigation Fragment")
+            .that(fragmentManager.primaryNavigationFragment)
+            .isSameInstanceAs(replacementFragment)
+
+        // Save some state into the replacement fragment
+        (replacementFragment as SavedStateFragment).savedState = "test"
+
+        // Now save the Fragment
+        fragmentNavigator.popBackStack(replacementEntry, true)
+        fragmentManager.executePendingTransactions()
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry)
+        assertWithMessage("Fragment should be the primary navigation Fragment after pop")
+            .that(fragmentManager.primaryNavigationFragment)
+            .isSameInstanceAs(fragment)
+
+        // Create a new FragmentNavigator, replacing the previous one
+        val savedState = fragmentNavigator.onSaveState() as Bundle
+        fragmentNavigator = FragmentNavigator(
+            emptyActivity,
+            fragmentManager, R.id.container
+        )
+        fragmentNavigator.onAttach(navigatorState)
+        fragmentNavigator.onRestoreState(savedState)
+
+        // And now restore the fragment
+        val restoredEntry = navigatorState.restoreBackStackEntry(replacementEntry)
+        fragmentNavigator.navigate(
+            listOf(restoredEntry),
+            NavOptions.Builder().setRestoreState(true).build(), null
+        )
+        assertThat(navigatorState.backStack.value)
+            .containsExactly(entry, restoredEntry).inOrder()
+        fragmentManager.executePendingTransactions()
+        val restoredFragment = fragmentManager.findFragmentById(R.id.container)
+        assertWithMessage("Restored Fragment should be added")
+            .that(restoredFragment)
+            .isNotNull()
+        assertWithMessage("Restored Fragment should be the correct type")
+            .that(restoredFragment)
+            .isInstanceOf(SavedStateFragment::class.java)
+        assertWithMessage("Restored Fragment should be the primary navigation Fragment")
+            .that(fragmentManager.primaryNavigationFragment)
+            .isSameInstanceAs(restoredFragment)
+
+        assertWithMessage("Restored Fragment should have its state restored")
+            .that((restoredFragment as SavedStateFragment).savedState)
+            .isEqualTo("test")
     }
 
     @Test
     fun testToString() {
-        val fragmentNavigator = FragmentNavigator(emptyActivity, fragmentManager, R.id.container)
         val destination = fragmentNavigator.createDestination().apply {
             id = INITIAL_FRAGMENT
             setClassName(EmptyFragment::class.java.name)
@@ -714,7 +702,6 @@
 
     @Test
     fun testToStringNoClassName() {
-        val fragmentNavigator = FragmentNavigator(emptyActivity, fragmentManager, R.id.container)
         val destination = fragmentNavigator.createDestination().apply {
             id = INITIAL_FRAGMENT
             label = TEST_LABEL
@@ -723,6 +710,17 @@
             "class=null"
         assertThat(destination.toString()).isEqualTo(expected)
     }
+
+    private fun createBackStackEntry(
+        destId: Int = INITIAL_FRAGMENT,
+        clazz: KClass<out Fragment> = EmptyFragment::class
+    ): NavBackStackEntry {
+        val destination = fragmentNavigator.createDestination().apply {
+            id = destId
+            setClassName(clazz.java.name)
+        }
+        return navigatorState.createBackStackEntry(destination, null)
+    }
 }
 
 class EmptyActivity : FragmentActivity() {
@@ -732,6 +730,20 @@
     }
 }
 
+class SavedStateFragment : Fragment() {
+    var savedState: String? = null
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        savedState = savedInstanceState?.getString("savedState")
+    }
+
+    override fun onSaveInstanceState(outState: Bundle) {
+        super.onSaveInstanceState(outState)
+        outState.putString("savedState", savedState)
+    }
+}
+
 class NonEmptyConstructorFragment(val test: String) : Fragment()
 
 class NonEmptyFragmentFactory : FragmentFactory() {
diff --git a/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/FragmentNavigator.kt b/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/FragmentNavigator.kt
index 4dd7e37..7e575fc 100644
--- a/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/FragmentNavigator.kt
+++ b/navigation/navigation-fragment/src/main/java/androidx/navigation/fragment/FragmentNavigator.kt
@@ -23,8 +23,10 @@
 import androidx.annotation.CallSuper
 import androidx.annotation.IdRes
 import androidx.core.content.res.use
+import androidx.core.os.bundleOf
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentManager
+import androidx.navigation.NavBackStackEntry
 import androidx.navigation.NavDestination
 import androidx.navigation.NavOptions
 import androidx.navigation.Navigator
@@ -50,7 +52,7 @@
     private val fragmentManager: FragmentManager,
     private val containerId: Int
 ) : Navigator<Destination>() {
-    private val backStack = ArrayDeque<Int>()
+    private val savedIds = mutableSetOf<String>()
 
     /**
      * {@inheritDoc}
@@ -64,22 +66,41 @@
      * asynchronously, so the newly visible Fragment from the back stack
      * is not instantly available after this call completes.
      */
-    public override fun popBackStack(): Boolean {
-        if (backStack.isEmpty()) {
-            return false
-        }
+    override fun popBackStack(popUpTo: NavBackStackEntry, savedState: Boolean) {
         if (fragmentManager.isStateSaved) {
             Log.i(
                 TAG, "Ignoring popBackStack() call: FragmentManager has already saved its state"
             )
-            return false
+            return
         }
-        fragmentManager.popBackStack(
-            generateBackStackName(backStack.size, backStack.last()),
-            FragmentManager.POP_BACK_STACK_INCLUSIVE
-        )
-        backStack.removeLast()
-        return true
+        if (savedState) {
+            val beforePopList = state.backStack.value
+            val initialEntry = beforePopList.first()
+            // Get the set of entries that are going to be popped
+            val poppedList = beforePopList.subList(
+                beforePopList.indexOf(popUpTo),
+                beforePopList.size
+            )
+            // Now go through the list in reversed order (i.e., started from the most added)
+            // and save the back stack state of each.
+            for (entry in poppedList.reversed()) {
+                if (entry == initialEntry) {
+                    Log.i(
+                        TAG,
+                        "FragmentManager cannot save the state of the initial destination $entry"
+                    )
+                } else {
+                    fragmentManager.saveBackStack(entry.id)
+                    savedIds += entry.id
+                }
+            }
+        } else {
+            fragmentManager.popBackStack(
+                popUpTo.id,
+                FragmentManager.POP_BACK_STACK_INCLUSIVE
+            )
+        }
+        state.pop(popUpTo, savedState)
     }
 
     public override fun createDestination(): Destination {
@@ -126,18 +147,42 @@
      * asynchronously, so the new Fragment is not instantly available
      * after this call completes.
      */
-    public override fun navigate(
-        destination: Destination,
-        args: Bundle?,
+    override fun navigate(
+        entries: List<NavBackStackEntry>,
         navOptions: NavOptions?,
         navigatorExtras: Navigator.Extras?
-    ): NavDestination? {
+    ) {
         if (fragmentManager.isStateSaved) {
             Log.i(
                 TAG, "Ignoring navigate() call: FragmentManager has already saved its state"
             )
-            return null
+            return
         }
+        for (entry in entries) {
+            navigate(entry, navOptions, navigatorExtras)
+        }
+    }
+
+    private fun navigate(
+        entry: NavBackStackEntry,
+        navOptions: NavOptions?,
+        navigatorExtras: Navigator.Extras?
+    ) {
+        val backStack = state.backStack.value
+        val initialNavigation = backStack.isEmpty()
+        val restoreState = (
+            navOptions != null && !initialNavigation &&
+                navOptions.shouldRestoreState() &&
+                savedIds.remove(entry.id)
+            )
+        if (restoreState) {
+            // Restore back stack does all the work to restore the entry
+            fragmentManager.restoreBackStack(entry.id)
+            state.add(entry)
+            return
+        }
+        val destination = entry.destination as Destination
+        val args = entry.arguments
         var className = destination.className
         if (className[0] == '.') {
             className = context.packageName + className
@@ -159,15 +204,13 @@
         ft.replace(containerId, frag)
         ft.setPrimaryNavigationFragment(frag)
         @IdRes val destId = destination.id
-        val initialNavigation = backStack.isEmpty()
         // TODO Build first class singleTop behavior for fragments
         val isSingleTopReplacement = (
             navOptions != null && !initialNavigation &&
                 navOptions.shouldLaunchSingleTop() &&
-                backStack.last() == destId
+                backStack.last().destination.id == destId
             )
-        val isAdded: Boolean
-        isAdded = when {
+        val isAdded = when {
             initialNavigation -> {
                 true
             }
@@ -179,15 +222,15 @@
                     // remove it from the back stack and put our replacement
                     // on the back stack in its place
                     fragmentManager.popBackStack(
-                        generateBackStackName(backStack.size, backStack.last()),
+                        entry.id,
                         FragmentManager.POP_BACK_STACK_INCLUSIVE
                     )
-                    ft.addToBackStack(generateBackStackName(backStack.size, destId))
+                    ft.addToBackStack(entry.id)
                 }
                 false
             }
             else -> {
-                ft.addToBackStack(generateBackStackName(backStack.size + 1, destId))
+                ft.addToBackStack(entry.id)
                 true
             }
         }
@@ -199,35 +242,26 @@
         ft.setReorderingAllowed(true)
         ft.commit()
         // The commit succeeded, update our view of the world
-        return if (isAdded) {
-            backStack.add(destId)
-            destination
-        } else {
-            null
+        if (isAdded) {
+            state.add(entry)
         }
     }
 
     public override fun onSaveState(): Bundle? {
-        val b = Bundle()
-        val backStack = backStack.toIntArray()
-        b.putIntArray(KEY_BACK_STACK_IDS, backStack)
-        return b
+        if (savedIds.isEmpty()) {
+            return null
+        }
+        return bundleOf(KEY_SAVED_IDS to ArrayList(savedIds))
     }
 
     public override fun onRestoreState(savedState: Bundle) {
-        val backStack = savedState.getIntArray(KEY_BACK_STACK_IDS)
-        if (backStack != null) {
-            this.backStack.clear()
-            for (destId in backStack) {
-                this.backStack.add(destId)
-            }
+        val savedIds = savedState.getStringArrayList(KEY_SAVED_IDS)
+        if (savedIds != null) {
+            this.savedIds.clear()
+            this.savedIds += savedIds
         }
     }
 
-    private fun generateBackStackName(backStackIndex: Int, destId: Int): String {
-        return "$backStackIndex-$destId"
-    }
-
     /**
      * NavDestination specific to [FragmentNavigator]
      */
@@ -368,6 +402,6 @@
 
     private companion object {
         private const val TAG = "FragmentNavigator"
-        private const val KEY_BACK_STACK_IDS = "androidx-nav-fragment:navigator:backStackIds"
+        private const val KEY_SAVED_IDS = "androidx-nav-fragment:navigator:savedIds"
     }
 }
diff --git a/navigation/navigation-runtime-ktx/lint-baseline.xml b/navigation/navigation-runtime-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/navigation/navigation-runtime-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-runtime-truth/lint-baseline.xml b/navigation/navigation-runtime-truth/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/navigation/navigation-runtime-truth/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-runtime/lint-baseline.xml b/navigation/navigation-runtime/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/navigation/navigation-runtime/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-safe-args-generator/lint-baseline.xml b/navigation/navigation-safe-args-generator/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/navigation/navigation-safe-args-generator/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-safe-args-gradle-plugin/lint-baseline.xml b/navigation/navigation-safe-args-gradle-plugin/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/navigation/navigation-safe-args-gradle-plugin/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-testing/api/current.txt b/navigation/navigation-testing/api/current.txt
index b862bb3..8fc24e8 100644
--- a/navigation/navigation-testing/api/current.txt
+++ b/navigation/navigation-testing/api/current.txt
@@ -15,6 +15,7 @@
     ctor public TestNavigatorState(optional android.content.Context? context, optional kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
     ctor public TestNavigatorState(optional android.content.Context? context);
     method public androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+    method public androidx.navigation.NavBackStackEntry restoreBackStackEntry(androidx.navigation.NavBackStackEntry previouslySavedEntry);
   }
 
 }
diff --git a/navigation/navigation-testing/api/public_plus_experimental_current.txt b/navigation/navigation-testing/api/public_plus_experimental_current.txt
index b862bb3..8fc24e8 100644
--- a/navigation/navigation-testing/api/public_plus_experimental_current.txt
+++ b/navigation/navigation-testing/api/public_plus_experimental_current.txt
@@ -15,6 +15,7 @@
     ctor public TestNavigatorState(optional android.content.Context? context, optional kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
     ctor public TestNavigatorState(optional android.content.Context? context);
     method public androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+    method public androidx.navigation.NavBackStackEntry restoreBackStackEntry(androidx.navigation.NavBackStackEntry previouslySavedEntry);
   }
 
 }
diff --git a/navigation/navigation-testing/api/restricted_current.txt b/navigation/navigation-testing/api/restricted_current.txt
index b862bb3..8fc24e8 100644
--- a/navigation/navigation-testing/api/restricted_current.txt
+++ b/navigation/navigation-testing/api/restricted_current.txt
@@ -15,6 +15,7 @@
     ctor public TestNavigatorState(optional android.content.Context? context, optional kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
     ctor public TestNavigatorState(optional android.content.Context? context);
     method public androidx.navigation.NavBackStackEntry createBackStackEntry(androidx.navigation.NavDestination destination, android.os.Bundle? arguments);
+    method public androidx.navigation.NavBackStackEntry restoreBackStackEntry(androidx.navigation.NavBackStackEntry previouslySavedEntry);
   }
 
 }
diff --git a/navigation/navigation-testing/lint-baseline.xml b/navigation/navigation-testing/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/navigation/navigation-testing/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-testing/src/main/java/androidx/navigation/testing/TestNavigatorState.kt b/navigation/navigation-testing/src/main/java/androidx/navigation/testing/TestNavigatorState.kt
index a3de911..9140e76 100644
--- a/navigation/navigation-testing/src/main/java/androidx/navigation/testing/TestNavigatorState.kt
+++ b/navigation/navigation-testing/src/main/java/androidx/navigation/testing/TestNavigatorState.kt
@@ -64,6 +64,8 @@
         }
     }
 
+    private val savedStates = mutableMapOf<String, Bundle>()
+
     override fun createBackStackEntry(
         destination: NavDestination,
         arguments: Bundle?
@@ -71,6 +73,23 @@
         context, destination, arguments, lifecycleOwner, viewModelStoreProvider
     )
 
+    /**
+     * Restore a previously saved [NavBackStackEntry]. You must have previously called
+     * [pop] with [previouslySavedEntry] and `true`.
+     */
+    public fun restoreBackStackEntry(previouslySavedEntry: NavBackStackEntry): NavBackStackEntry {
+        val savedState = checkNotNull(savedStates[previouslySavedEntry.id]) {
+            "restoreBackStackEntry(previouslySavedEntry) must be passed a NavBackStackEntry " +
+                "that was previously popped with popBackStack(previouslySavedEntry, true)"
+        }
+        return NavBackStackEntry.create(
+            context,
+            previouslySavedEntry.destination, previouslySavedEntry.arguments,
+            lifecycleOwner, viewModelStoreProvider,
+            previouslySavedEntry.id, savedState
+        )
+    }
+
     override fun add(backStackEntry: NavBackStackEntry) {
         super.add(backStackEntry)
         updateMaxLifecycle()
@@ -80,10 +99,13 @@
         val beforePopList = backStack.value
         val poppedList = beforePopList.subList(beforePopList.indexOf(popUpTo), beforePopList.size)
         super.pop(popUpTo, saveState)
-        updateMaxLifecycle(poppedList)
+        updateMaxLifecycle(poppedList, saveState)
     }
 
-    private fun updateMaxLifecycle(poppedList: List<NavBackStackEntry> = emptyList()) {
+    private fun updateMaxLifecycle(
+        poppedList: List<NavBackStackEntry> = emptyList(),
+        saveState: Boolean = false
+    ) {
         runBlocking(coroutineDispatcher) {
             // NavBackStackEntry Lifecycles must be updated on the main thread
             // as per the contract within Lifecycle, so we explicitly swap to the main thread
@@ -91,6 +113,13 @@
             withContext(Dispatchers.Main.immediate) {
                 // Mark all removed NavBackStackEntries as DESTROYED
                 for (entry in poppedList.reversed()) {
+                    if (saveState) {
+                        // Move the NavBackStackEntry to the stopped state, then save its state
+                        entry.maxLifecycle = Lifecycle.State.CREATED
+                        val savedState = Bundle()
+                        entry.saveState(savedState)
+                        savedStates[entry.id] = savedState
+                    }
                     entry.maxLifecycle = Lifecycle.State.DESTROYED
                 }
                 // Now go through the current list of destinations, updating their Lifecycle state
diff --git a/navigation/navigation-ui-ktx/lint-baseline.xml b/navigation/navigation-ui-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/navigation/navigation-ui-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-ui/build.gradle b/navigation/navigation-ui/build.gradle
index 446191d..ab64177 100644
--- a/navigation/navigation-ui/build.gradle
+++ b/navigation/navigation-ui/build.gradle
@@ -30,6 +30,9 @@
     buildTypes.all {
         consumerProguardFiles "proguard-rules.pro"
     }
+    defaultConfig {
+        multiDexEnabled true
+    }
 }
 
 dependencies {
@@ -47,6 +50,7 @@
     androidTestImplementation(ANDROIDX_TEST_CORE)
     androidTestImplementation(ANDROIDX_TEST_RUNNER)
     androidTestImplementation(TRUTH)
+    androidTestImplementation(MULTIDEX)
 }
 
 androidx {
diff --git a/navigation/navigation-ui/lint-baseline.xml b/navigation/navigation-ui/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/navigation/navigation-ui/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/navigation/navigation-ui/src/androidTest/AndroidManifest.xml b/navigation/navigation-ui/src/androidTest/AndroidManifest.xml
index 40d9eb7..ed9f9a9 100644
--- a/navigation/navigation-ui/src/androidTest/AndroidManifest.xml
+++ b/navigation/navigation-ui/src/androidTest/AndroidManifest.xml
@@ -15,6 +15,7 @@
   ~ limitations under the License.
   -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="androidx.navigation.ui">
+          package="androidx.navigation.ui"
+          android:name="androidx.multidex.MultiDexApplication">
 
 </manifest>
diff --git a/paging/common/ktx/lint-baseline.xml b/paging/common/ktx/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/paging/common/ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/paging/guava/lint-baseline.xml b/paging/guava/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/paging/guava/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/paging/paging-compose/build.gradle b/paging/paging-compose/build.gradle
index a481bd4..669f393d3 100644
--- a/paging/paging-compose/build.gradle
+++ b/paging/paging-compose/build.gradle
@@ -32,7 +32,7 @@
 
     implementation(libs.kotlinStdlib)
     api(projectOrArtifact(":compose:foundation:foundation"))
-    api(projectOrArtifact(":paging:paging-common"))
+    api("androidx.paging:paging-common:3.0.0")
 
     androidTestImplementation(projectOrArtifact(":compose:ui:ui-test-junit4"))
     androidTestImplementation(project(":compose:test-utils"))
diff --git a/paging/paging-compose/src/main/java/androidx/paging/compose/LazyPagingItems.kt b/paging/paging-compose/src/main/java/androidx/paging/compose/LazyPagingItems.kt
index 0df5445..7a4302d 100644
--- a/paging/paging-compose/src/main/java/androidx/paging/compose/LazyPagingItems.kt
+++ b/paging/paging-compose/src/main/java/androidx/paging/compose/LazyPagingItems.kt
@@ -48,10 +48,12 @@
  * This instance can be used by the [items] and [itemsIndexed] methods inside [LazyListScope] to
  * display data received from the [Flow] of [PagingData].
  *
- * @param flow the [Flow] object which contains a stream of [PagingData] elements.
  * @param T the type of value used by [PagingData].
  */
 public class LazyPagingItems<T : Any> internal constructor(
+    /**
+     * the [Flow] object which contains a stream of [PagingData] elements.
+     */
     private val flow: Flow<PagingData<T>>
 ) {
     private val mainDispatcher = Dispatchers.Main
diff --git a/paging/runtime/ktx/lint-baseline.xml b/paging/runtime/ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/paging/runtime/ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/paging/rxjava2/ktx/lint-baseline.xml b/paging/rxjava2/ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/paging/rxjava2/ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/paging/rxjava2/lint-baseline.xml b/paging/rxjava2/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/paging/rxjava2/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/paging/rxjava3/lint-baseline.xml b/paging/rxjava3/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/paging/rxjava3/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/paging/samples/lint-baseline.xml b/paging/samples/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/paging/samples/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/palette/palette-ktx/lint-baseline.xml b/palette/palette-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/palette/palette-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/palette/palette/lint-baseline.xml b/palette/palette/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/palette/palette/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/preference/preference-ktx/lint-baseline.xml b/preference/preference-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/preference/preference-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/recyclerview/recyclerview-benchmark/lint-baseline.xml b/recyclerview/recyclerview-benchmark/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/recyclerview/recyclerview-benchmark/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/recyclerview/recyclerview-lint/lint-baseline.xml b/recyclerview/recyclerview-lint/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/recyclerview/recyclerview-lint/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/resourceinspection/resourceinspection-processor/lint-baseline.xml b/resourceinspection/resourceinspection-processor/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/resourceinspection/resourceinspection-processor/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/room/benchmark/lint-baseline.xml b/room/benchmark/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/room/benchmark/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/room/compiler-processing-testing/lint-baseline.xml b/room/compiler-processing-testing/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/room/compiler-processing-testing/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/room/compiler-processing/lint-baseline.xml b/room/compiler-processing/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/room/compiler-processing/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/room/compiler/lint-baseline.xml b/room/compiler/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/room/compiler/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/room/integration-tests/autovaluetestapp/lint-baseline.xml b/room/integration-tests/autovaluetestapp/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/room/integration-tests/autovaluetestapp/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/room/integration-tests/incremental-annotation-processing/lint-baseline.xml b/room/integration-tests/incremental-annotation-processing/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/room/integration-tests/incremental-annotation-processing/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/room/integration-tests/kotlintestapp/lint-baseline.xml b/room/integration-tests/kotlintestapp/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/room/integration-tests/kotlintestapp/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/room/integration-tests/noappcompattestapp/lint-baseline.xml b/room/integration-tests/noappcompattestapp/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/room/integration-tests/noappcompattestapp/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/room/rxjava3/lint-baseline.xml b/room/rxjava3/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/room/rxjava3/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/savedstate/savedstate-ktx/lint-baseline.xml b/savedstate/savedstate-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/savedstate/savedstate-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/savedstate/savedstate/lint-baseline.xml b/savedstate/savedstate/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/savedstate/savedstate/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/security/identity-credential/lint-baseline.xml b/security/identity-credential/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/security/identity-credential/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/security/security-app-authenticator/lint-baseline.xml b/security/security-app-authenticator/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/security/security-app-authenticator/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/security/security-biometric/lint-baseline.xml b/security/security-biometric/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/security/security-biometric/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/security/security-crypto-ktx/lint-baseline.xml b/security/security-crypto-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/security/security-crypto-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/slices/benchmark/lint-baseline.xml b/slices/benchmark/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/slices/benchmark/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/slices/builders/ktx/lint-baseline.xml b/slices/builders/ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/slices/builders/ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/slices/remotecallback/lint-baseline.xml b/slices/remotecallback/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/slices/remotecallback/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/sqlite/sqlite-ktx/lint-baseline.xml b/sqlite/sqlite-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/sqlite/sqlite-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/startup/integration-tests/first-library/lint-baseline.xml b/startup/integration-tests/first-library/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/startup/integration-tests/first-library/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/startup/integration-tests/second-library/lint-baseline.xml b/startup/integration-tests/second-library/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/startup/integration-tests/second-library/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/startup/integration-tests/test-app/lint-baseline.xml b/startup/integration-tests/test-app/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/startup/integration-tests/test-app/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/startup/startup-runtime-lint/lint-baseline.xml b/startup/startup-runtime-lint/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/startup/startup-runtime-lint/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/startup/startup-runtime/lint-baseline.xml b/startup/startup-runtime/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/startup/startup-runtime/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/testutils/testutils-appcompat/lint-baseline.xml b/testutils/testutils-appcompat/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/testutils/testutils-appcompat/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/testutils/testutils-gradle-plugin/lint-baseline.xml b/testutils/testutils-gradle-plugin/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/testutils/testutils-gradle-plugin/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/testutils/testutils-mockito/lint-baseline.xml b/testutils/testutils-mockito/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/testutils/testutils-mockito/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/testutils/testutils-truth/lint-baseline.xml b/testutils/testutils-truth/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/testutils/testutils-truth/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/transition/transition-ktx/lint-baseline.xml b/transition/transition-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/transition/transition-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/vectordrawable/vectordrawable-seekable/lint-baseline.xml b/vectordrawable/vectordrawable-seekable/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/vectordrawable/vectordrawable-seekable/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/tiles/tiles/lint-baseline.xml b/wear/tiles/tiles/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/tiles/tiles/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-complications-provider/lint-baseline.xml b/wear/wear-complications-provider/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/wear-complications-provider/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-complications-provider/samples/lint-baseline.xml b/wear/wear-complications-provider/samples/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/wear-complications-provider/samples/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-input-testing/lint-baseline.xml b/wear/wear-input-testing/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/wear-input-testing/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-input/lint-baseline.xml b/wear/wear-input/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/wear-input/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-ongoing/lint-baseline.xml b/wear/wear-ongoing/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/wear-ongoing/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-phone-interactions/lint-baseline.xml b/wear/wear-phone-interactions/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/wear-phone-interactions/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-remote-interactions/lint-baseline.xml b/wear/wear-remote-interactions/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/wear-remote-interactions/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-watchface-client/lint-baseline.xml b/wear/wear-watchface-client/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/wear-watchface-client/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/SerializationTest.kt b/wear/wear-watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/SerializationTest.kt
index 0ce3355..d9f8180 100644
--- a/wear/wear-watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/SerializationTest.kt
+++ b/wear/wear-watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/SerializationTest.kt
@@ -56,7 +56,7 @@
 
     private fun <T> loadGoldenResource(resourceId: Int, readFromParcel: (p: Parcel) -> T): T {
         val resource = context.resources.openRawResource(resourceId)
-        val bytes = Base64.getDecoder().decode(resource.readBytes())
+        val bytes = Base64.getDecoder().decode(String(resource.readBytes()))
         val p = Parcel.obtain()
         p.unmarshall(bytes, 0, bytes.size)
         p.setDataPosition(0)
@@ -236,4 +236,11 @@
         assertThat(complicationB.text.getTextAt(context.resources, 0)).isEqualTo("Example")
         assertThat(complicationB.title!!.getTextAt(context.resources, 0)).isEqualTo("complication")
     }
-}
\ No newline at end of file
+
+    @Test
+    public fun userStyleSchema() {
+        // TODO(b/187498135): Implement a golden test. This is harder than it sounds because the raw
+        // bytes of  a serialized Parcel is not portable and can differ between architectures even
+        // on the same API level.  The tests above possibly only pass on current bots by luck.
+    }
+}
diff --git a/wear/wear-watchface-complications-rendering/api/current.txt b/wear/wear-watchface-complications-rendering/api/current.txt
index 085dab4..2093fe8 100644
--- a/wear/wear-watchface-complications-rendering/api/current.txt
+++ b/wear/wear-watchface-complications-rendering/api/current.txt
@@ -20,15 +20,15 @@
 
   public final class ComplicationDrawable extends android.graphics.drawable.Drawable {
     ctor public ComplicationDrawable();
-    ctor public ComplicationDrawable(android.content.Context);
-    ctor public ComplicationDrawable(androidx.wear.watchface.complications.rendering.ComplicationDrawable);
-    method public void draw(android.graphics.Canvas);
+    ctor public ComplicationDrawable(android.content.Context context);
+    ctor public ComplicationDrawable(androidx.wear.watchface.complications.rendering.ComplicationDrawable drawable);
+    method public void draw(android.graphics.Canvas canvas);
     method public androidx.wear.watchface.complications.rendering.ComplicationStyle getActiveStyle();
     method public androidx.wear.watchface.complications.rendering.ComplicationStyle getAmbientStyle();
     method public androidx.wear.complications.data.ComplicationData? getComplicationData();
     method public android.content.Context? getContext();
     method public long getCurrentTimeMillis();
-    method public static androidx.wear.watchface.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context, int);
+    method public static androidx.wear.watchface.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context context, int id);
     method public long getHighlightDuration();
     method public CharSequence? getNoDataText();
     method @Deprecated public int getOpacity();
@@ -37,19 +37,36 @@
     method public boolean isInAmbientMode();
     method public boolean isLowBitAmbient();
     method public boolean isRangedValueProgressHidden();
-    method public boolean onTap(@Px int, @Px int);
-    method public void setAlpha(int);
-    method public void setBurnInProtection(boolean);
-    method public void setColorFilter(android.graphics.ColorFilter?);
-    method public void setComplicationData(androidx.wear.complications.data.ComplicationData?, boolean);
-    method public void setContext(android.content.Context);
-    method public void setCurrentTimeMillis(long);
-    method public void setHighlightDuration(@IntRange(from=0) long);
-    method public void setHighlighted(boolean);
-    method public void setInAmbientMode(boolean);
-    method public void setLowBitAmbient(boolean);
-    method public void setNoDataText(CharSequence?);
-    method public void setRangedValueProgressHidden(boolean);
+    method public boolean onTap(@Px int x, @Px int y);
+    method public void setAlpha(@IntRange(from=0, to=255) int alpha);
+    method public void setBurnInProtectionOn(boolean p);
+    method public void setColorFilter(android.graphics.ColorFilter? colorFilter);
+    method public void setComplicationData(androidx.wear.complications.data.ComplicationData? complicationData, boolean loadDrawablesAsync);
+    method public void setContext(android.content.Context context);
+    method public void setCurrentTimeMillis(long p);
+    method public void setHighlightDuration(@IntRange(from=0) long highlightDurationMillis);
+    method public void setHighlighted(boolean p);
+    method public void setInAmbientMode(boolean p);
+    method public void setLowBitAmbient(boolean p);
+    method public void setNoDataText(CharSequence? noDataText);
+    method public void setRangedValueProgressHidden(boolean rangedValueProgressHidden);
+    property public final androidx.wear.watchface.complications.rendering.ComplicationStyle activeStyle;
+    property public final androidx.wear.watchface.complications.rendering.ComplicationStyle ambientStyle;
+    property public final androidx.wear.complications.data.ComplicationData? complicationData;
+    property public final android.content.Context? context;
+    property public final long currentTimeMillis;
+    property public final long highlightDuration;
+    property public final boolean isBurnInProtectionOn;
+    property public final boolean isHighlighted;
+    property public final boolean isInAmbientMode;
+    property public final boolean isLowBitAmbient;
+    property public final boolean isRangedValueProgressHidden;
+    property public final CharSequence? noDataText;
+    field public static final androidx.wear.watchface.complications.rendering.ComplicationDrawable.Companion Companion;
+  }
+
+  public static final class ComplicationDrawable.Companion {
+    method public androidx.wear.watchface.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context context, int id);
   }
 
   public final class ComplicationHighlightRenderer {
diff --git a/wear/wear-watchface-complications-rendering/api/public_plus_experimental_current.txt b/wear/wear-watchface-complications-rendering/api/public_plus_experimental_current.txt
index 085dab4..2093fe8 100644
--- a/wear/wear-watchface-complications-rendering/api/public_plus_experimental_current.txt
+++ b/wear/wear-watchface-complications-rendering/api/public_plus_experimental_current.txt
@@ -20,15 +20,15 @@
 
   public final class ComplicationDrawable extends android.graphics.drawable.Drawable {
     ctor public ComplicationDrawable();
-    ctor public ComplicationDrawable(android.content.Context);
-    ctor public ComplicationDrawable(androidx.wear.watchface.complications.rendering.ComplicationDrawable);
-    method public void draw(android.graphics.Canvas);
+    ctor public ComplicationDrawable(android.content.Context context);
+    ctor public ComplicationDrawable(androidx.wear.watchface.complications.rendering.ComplicationDrawable drawable);
+    method public void draw(android.graphics.Canvas canvas);
     method public androidx.wear.watchface.complications.rendering.ComplicationStyle getActiveStyle();
     method public androidx.wear.watchface.complications.rendering.ComplicationStyle getAmbientStyle();
     method public androidx.wear.complications.data.ComplicationData? getComplicationData();
     method public android.content.Context? getContext();
     method public long getCurrentTimeMillis();
-    method public static androidx.wear.watchface.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context, int);
+    method public static androidx.wear.watchface.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context context, int id);
     method public long getHighlightDuration();
     method public CharSequence? getNoDataText();
     method @Deprecated public int getOpacity();
@@ -37,19 +37,36 @@
     method public boolean isInAmbientMode();
     method public boolean isLowBitAmbient();
     method public boolean isRangedValueProgressHidden();
-    method public boolean onTap(@Px int, @Px int);
-    method public void setAlpha(int);
-    method public void setBurnInProtection(boolean);
-    method public void setColorFilter(android.graphics.ColorFilter?);
-    method public void setComplicationData(androidx.wear.complications.data.ComplicationData?, boolean);
-    method public void setContext(android.content.Context);
-    method public void setCurrentTimeMillis(long);
-    method public void setHighlightDuration(@IntRange(from=0) long);
-    method public void setHighlighted(boolean);
-    method public void setInAmbientMode(boolean);
-    method public void setLowBitAmbient(boolean);
-    method public void setNoDataText(CharSequence?);
-    method public void setRangedValueProgressHidden(boolean);
+    method public boolean onTap(@Px int x, @Px int y);
+    method public void setAlpha(@IntRange(from=0, to=255) int alpha);
+    method public void setBurnInProtectionOn(boolean p);
+    method public void setColorFilter(android.graphics.ColorFilter? colorFilter);
+    method public void setComplicationData(androidx.wear.complications.data.ComplicationData? complicationData, boolean loadDrawablesAsync);
+    method public void setContext(android.content.Context context);
+    method public void setCurrentTimeMillis(long p);
+    method public void setHighlightDuration(@IntRange(from=0) long highlightDurationMillis);
+    method public void setHighlighted(boolean p);
+    method public void setInAmbientMode(boolean p);
+    method public void setLowBitAmbient(boolean p);
+    method public void setNoDataText(CharSequence? noDataText);
+    method public void setRangedValueProgressHidden(boolean rangedValueProgressHidden);
+    property public final androidx.wear.watchface.complications.rendering.ComplicationStyle activeStyle;
+    property public final androidx.wear.watchface.complications.rendering.ComplicationStyle ambientStyle;
+    property public final androidx.wear.complications.data.ComplicationData? complicationData;
+    property public final android.content.Context? context;
+    property public final long currentTimeMillis;
+    property public final long highlightDuration;
+    property public final boolean isBurnInProtectionOn;
+    property public final boolean isHighlighted;
+    property public final boolean isInAmbientMode;
+    property public final boolean isLowBitAmbient;
+    property public final boolean isRangedValueProgressHidden;
+    property public final CharSequence? noDataText;
+    field public static final androidx.wear.watchface.complications.rendering.ComplicationDrawable.Companion Companion;
+  }
+
+  public static final class ComplicationDrawable.Companion {
+    method public androidx.wear.watchface.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context context, int id);
   }
 
   public final class ComplicationHighlightRenderer {
diff --git a/wear/wear-watchface-complications-rendering/api/restricted_current.txt b/wear/wear-watchface-complications-rendering/api/restricted_current.txt
index 110cc54..8b9e974 100644
--- a/wear/wear-watchface-complications-rendering/api/restricted_current.txt
+++ b/wear/wear-watchface-complications-rendering/api/restricted_current.txt
@@ -20,15 +20,15 @@
 
   public final class ComplicationDrawable extends android.graphics.drawable.Drawable {
     ctor public ComplicationDrawable();
-    ctor public ComplicationDrawable(android.content.Context);
-    ctor public ComplicationDrawable(androidx.wear.watchface.complications.rendering.ComplicationDrawable);
-    method public void draw(android.graphics.Canvas);
+    ctor public ComplicationDrawable(android.content.Context context);
+    ctor public ComplicationDrawable(androidx.wear.watchface.complications.rendering.ComplicationDrawable drawable);
+    method public void draw(android.graphics.Canvas canvas);
     method public androidx.wear.watchface.complications.rendering.ComplicationStyle getActiveStyle();
     method public androidx.wear.watchface.complications.rendering.ComplicationStyle getAmbientStyle();
     method public androidx.wear.complications.data.ComplicationData? getComplicationData();
     method public android.content.Context? getContext();
     method public long getCurrentTimeMillis();
-    method public static androidx.wear.watchface.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context, int);
+    method public static androidx.wear.watchface.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context context, int id);
     method public long getHighlightDuration();
     method public CharSequence? getNoDataText();
     method @Deprecated public int getOpacity();
@@ -37,19 +37,36 @@
     method public boolean isInAmbientMode();
     method public boolean isLowBitAmbient();
     method public boolean isRangedValueProgressHidden();
-    method public boolean onTap(@Px int, @Px int);
-    method public void setAlpha(int);
-    method public void setBurnInProtection(boolean);
-    method public void setColorFilter(android.graphics.ColorFilter?);
-    method public void setComplicationData(androidx.wear.complications.data.ComplicationData?, boolean);
-    method public void setContext(android.content.Context);
-    method public void setCurrentTimeMillis(long);
-    method public void setHighlightDuration(@IntRange(from=0) long);
-    method public void setHighlighted(boolean);
-    method public void setInAmbientMode(boolean);
-    method public void setLowBitAmbient(boolean);
-    method public void setNoDataText(CharSequence?);
-    method public void setRangedValueProgressHidden(boolean);
+    method public boolean onTap(@Px int x, @Px int y);
+    method public void setAlpha(@IntRange(from=0, to=255) int alpha);
+    method public void setBurnInProtectionOn(boolean p);
+    method public void setColorFilter(android.graphics.ColorFilter? colorFilter);
+    method public void setComplicationData(androidx.wear.complications.data.ComplicationData? complicationData, boolean loadDrawablesAsync);
+    method public void setContext(android.content.Context context);
+    method public void setCurrentTimeMillis(long p);
+    method public void setHighlightDuration(@IntRange(from=0) long highlightDurationMillis);
+    method public void setHighlighted(boolean p);
+    method public void setInAmbientMode(boolean p);
+    method public void setLowBitAmbient(boolean p);
+    method public void setNoDataText(CharSequence? noDataText);
+    method public void setRangedValueProgressHidden(boolean rangedValueProgressHidden);
+    property public final androidx.wear.watchface.complications.rendering.ComplicationStyle activeStyle;
+    property public final androidx.wear.watchface.complications.rendering.ComplicationStyle ambientStyle;
+    property public final androidx.wear.complications.data.ComplicationData? complicationData;
+    property public final android.content.Context? context;
+    property public final long currentTimeMillis;
+    property public final long highlightDuration;
+    property public final boolean isBurnInProtectionOn;
+    property public final boolean isHighlighted;
+    property public final boolean isInAmbientMode;
+    property public final boolean isLowBitAmbient;
+    property public final boolean isRangedValueProgressHidden;
+    property public final CharSequence? noDataText;
+    field public static final androidx.wear.watchface.complications.rendering.ComplicationDrawable.Companion Companion;
+  }
+
+  public static final class ComplicationDrawable.Companion {
+    method public androidx.wear.watchface.complications.rendering.ComplicationDrawable? getDrawable(android.content.Context context, int id);
   }
 
   public final class ComplicationHighlightRenderer {
diff --git a/wear/wear-watchface-complications-rendering/lint-baseline.xml b/wear/wear-watchface-complications-rendering/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/wear-watchface-complications-rendering/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/CanvasComplicationDrawable.kt b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/CanvasComplicationDrawable.kt
index 05df52f..9222881 100644
--- a/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/CanvasComplicationDrawable.kt
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/CanvasComplicationDrawable.kt
@@ -92,7 +92,7 @@
             field = value
             value.isInAmbientMode = watchState.isAmbient.value
             value.isLowBitAmbient = watchState.hasLowBitAmbient
-            value.setBurnInProtection(watchState.hasBurnInProtection)
+            value.isBurnInProtectionOn = watchState.hasBurnInProtection
 
             attachedComplication?.scheduleUpdateComplications()
         }
diff --git a/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationDrawable.java b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationDrawable.java
deleted file mode 100644
index 55c1e16..0000000
--- a/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationDrawable.java
+++ /dev/null
@@ -1,870 +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.wear.watchface.complications.rendering;
-
-import android.app.PendingIntent.CanceledException;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.content.res.Resources.Theme;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.Looper;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Xml;
-
-import androidx.annotation.IntRange;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.Px;
-import androidx.annotation.VisibleForTesting;
-import androidx.wear.complications.ComplicationHelperActivity;
-import androidx.wear.complications.data.ComplicationData;
-import androidx.wear.complications.data.ComplicationType;
-import androidx.wear.complications.data.DataKt;
-import androidx.wear.watchface.complications.rendering.ComplicationRenderer.OnInvalidateListener;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.Objects;
-
-/**
- * A styleable drawable object that draws complications. You can create a ComplicationDrawable from
- * XML inflation or by using one of the constructor methods.
- *
- * <h3>Constructing a ComplicationDrawable</h3>
- *
- * <p>To construct a ComplicationDrawable programmatically, use the {@link
- * #ComplicationDrawable(Context)} constructor. Afterwards, styling attributes you want to modify
- * can be set via set methods.
- *
- * <pre>
- * public void onCreate(SurfaceHolder holder) {
- *   ...
- *   ComplicationDrawable complicationDrawable = new ComplicationDrawable(WatchFaceService.this);
- *   complicationDrawable.setBackgroundColorActive(backgroundColor);
- *   complicationDrawable.setTextColorActive(textColor);
- *   ...
- * }</pre>
- *
- * <h3>Constructing a ComplicationDrawable from XML</h3>
- *
- * <p>Constructing a ComplicationDrawable from an XML file makes it easier to modify multiple
- * styling attributes at once without calling any set methods. You may also use different XML files
- * to switch between different styles your watch face supports.
- *
- * <p>To construct a ComplicationDrawable from a drawable XML file, you may create an XML file in
- * your project's {@code res/drawable} folder. A ComplicationDrawable with red text and white title
- * in active mode, and white text and white title in ambient mode would look like this:
- *
- * <pre>
- * &lt;?xml version="1.0" encoding="utf-8"?&gt;
- * &lt;android.support.wearable.complications.rendering.ComplicationDrawable
- *   xmlns:app="http://schemas.android.com/apk/res-auto"
- *   app:textColor="#FFFF0000"
- *   app:titleColor="#FFFFFFFF"&gt;
- *   &lt;ambient
- *     app:textColor="#FFFFFFFF" /&gt;
- * &lt;/android.support.wearable.complications.rendering.ComplicationDrawable&gt;
- * </pre>
- *
- * <p>A top-level {@code drawable} tag with the {@code class} attribute may also be used to
- * construct a ComplicationDrawable from an XML file:
- *
- * <pre>
- * &lt;?xml version="1.0" encoding="utf-8"?&gt;
- * &lt;drawable
- *   class="android.support.wearable.complications.rendering.ComplicationDrawable"
- *   xmlns:app="http://schemas.android.com/apk/res-auto"
- *   app:textColor="#FFFF0000"
- *   app:titleColor="#FFFFFFFF"&gt;
- *   &lt;ambient
- *     app:textColor="#FFFFFFFF" /&gt;
- * &lt;/drawable&gt;</pre>
- *
- * <p>To inflate a ComplicationDrawable from XML file, use the {@link #getDrawable(Context, int)}
- * method. ComplicationDrawable needs access to the current context in order to style and draw
- * the complication.
- *
- * <pre>
- * public void onCreate(SurfaceHolder holder) {
- *   ...
- *   ComplicationDrawable complicationDrawable = (ComplicationDrawable)
- *       getDrawable(R.drawable.complication);
- *   complicationDrawable.setContext(WatchFaceService.this);
- *   ...
- * }</pre>
- *
- * <h4>Syntax:</h4>
- *
- * <pre>
- * &lt;?xml version="1.0" encoding="utf-8"?&gt;
- * &lt;android.support.wearable.complications.rendering.ComplicationDrawable
- *   xmlns:app="http://schemas.android.com/apk/res-auto"
- *   app:backgroundColor="color"
- *   app:backgroundDrawable="drawable"
- *   app:borderColor="color"
- *   app:borderDashGap="dimension"
- *   app:borderDashWidth="dimension"
- *   app:borderRadius="dimension"
- *   app:borderStyle="none|solid|dashed"
- *   app:borderWidth="dimension"
- *   app:highlightColor="color"
- *   app:iconColor="color"
- *   app:rangedValuePrimaryColor="color"
- *   app:rangedValueProgressHidden="boolean"
- *   app:rangedValueRingWidth="dimension"
- *   app:rangedValueSecondaryColor="color"
- *   app:textColor="color"
- *   app:textSize="dimension"
- *   app:textTypeface="string"
- *   app:titleColor="color"
- *   app:titleSize="dimension"
- *   app:titleTypeface="string"&gt;
- *   &lt;ambient
- *     app:backgroundColor="color"
- *     app:backgroundDrawable="drawable"
- *     app:borderColor="color"
- *     app:borderDashGap="dimension"
- *     app:borderDashWidth="dimension"
- *     app:borderRadius="dimension"
- *     app:borderStyle="none|solid|dashed"
- *     app:borderWidth="dimension"
- *     app:highlightColor="color"
- *     app:iconColor="color"
- *     app:rangedValuePrimaryColor="color"
- *     app:rangedValueRingWidth="dimension"
- *     app:rangedValueSecondaryColor="color"
- *     app:textColor="color"
- *     app:textSize="dimension"
- *     app:textTypeface="string"
- *     app:titleColor="color"
- *     app:titleSize="dimension"
- *     app:titleTypeface="string" /&gt;
- * &lt;/android.support.wearable.complications.rendering.ComplicationDrawable&gt;
- * </pre>
- *
- * <p>Attributes of the top-level tag apply to both active and ambient modes while attributes of the
- * inner {@code ambient} tag only apply to ambient mode. As an exception, top-level only {@code
- * rangedValueProgressHidden} attribute applies to both modes, and cannot be overridden in ambient
- * mode. To hide ranged value in only one of the active or ambient modes, you may consider setting
- * {@code rangedValuePrimaryColor} and {@code rangedValueSecondaryColor} to {@link
- * android.graphics.Color#TRANSPARENT} instead.
- *
- * <h3>Drawing a ComplicationDrawable</h3>
- *
- * <p>Depending on the size and shape of the bounds, the layout of the complication may change. For
- * instance, a short text complication with an icon that is drawn on square bounds would draw the
- * icon above the short text, but a short text complication with an icon that is drawn on wide
- * rectangular bounds might draw the icon to the left of the short text instead.
- */
-public final class ComplicationDrawable extends Drawable {
-
-    private Context mContext;
-    private ComplicationRenderer mComplicationRenderer;
-
-    private final ComplicationStyle mActiveStyle;
-    private final ComplicationStyle mAmbientStyle;
-
-    private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
-
-    private final Runnable mUnhighlightRunnable =
-            () -> {
-                setHighlighted(false);
-                invalidateSelf();
-            };
-
-    private final OnInvalidateListener mRendererInvalidateListener = () -> invalidateSelf();
-
-    private CharSequence mNoDataText;
-    private long mHighlightDuration;
-    private long mCurrentTimeMillis;
-    private boolean mInAmbientMode;
-    private boolean mLowBitAmbient;
-    private boolean mBurnInProtection;
-    private boolean mHighlighted;
-    private boolean mRangedValueProgressHidden;
-
-    private boolean mIsInflatedFromXml;
-    private boolean mAlreadyStyled;
-
-    /** Default constructor. */
-    public ComplicationDrawable() {
-        mActiveStyle = new ComplicationStyle();
-        mAmbientStyle = new ComplicationStyle();
-    }
-
-    /**
-     * Creates a ComplicationDrawable using the given context. If this constructor is used, calling
-     * {@link #setContext(Context)} may not be necessary.
-     */
-    public ComplicationDrawable(@NonNull Context context) {
-        this();
-        setContext(context);
-    }
-
-    public ComplicationDrawable(@NonNull ComplicationDrawable drawable) {
-        mActiveStyle = new ComplicationStyle(drawable.mActiveStyle);
-        mAmbientStyle = new ComplicationStyle(drawable.mAmbientStyle);
-        mNoDataText = drawable.mNoDataText.subSequence(0, drawable.mNoDataText.length());
-        mHighlightDuration = drawable.mHighlightDuration;
-        mCurrentTimeMillis = drawable.mCurrentTimeMillis;
-        setBounds(drawable.getBounds());
-
-        mInAmbientMode = drawable.mInAmbientMode;
-        mLowBitAmbient = drawable.mLowBitAmbient;
-        mBurnInProtection = drawable.mBurnInProtection;
-        mHighlighted = false;
-        mRangedValueProgressHidden = drawable.mRangedValueProgressHidden;
-        mIsInflatedFromXml = drawable.mIsInflatedFromXml;
-        mAlreadyStyled = true;
-    }
-
-    /**
-     * Creates a ComplicationDrawable from a resource.
-     *
-     * @param context The {@link Context} to load the resource from
-     * @param id      The id of the resource to load
-     * @return The {@link ComplicationDrawable} loaded from the specified resource id or null if it
-     * doesn't exist.
-     */
-    @Nullable
-    public static ComplicationDrawable getDrawable(@NonNull Context context, int id) {
-        if (context == null) {
-            throw new IllegalArgumentException("Argument \"context\" should not be null.");
-        }
-        ComplicationDrawable drawable = (ComplicationDrawable) context.getDrawable(id);
-        if (drawable == null) {
-            return null;
-        }
-
-        drawable.setContext(context);
-        return drawable;
-    }
-
-    /** Sets the style to default values using resources. */
-    private static void setStyleToDefaultValues(ComplicationStyle style, Resources r) {
-        style.setBackgroundColor(
-                r.getColor(R.color.complicationDrawable_backgroundColor, null));
-        style.setTextColor(r.getColor(R.color.complicationDrawable_textColor, null));
-        style.setTitleColor(r.getColor(R.color.complicationDrawable_titleColor, null));
-        style.setTextTypeface(
-                Typeface.create(
-                        r.getString(R.string.complicationDrawable_textTypeface), Typeface.NORMAL));
-        style.setTitleTypeface(
-                Typeface.create(
-                        r.getString(R.string.complicationDrawable_titleTypeface), Typeface.NORMAL));
-        style.setTextSize(r.getDimensionPixelSize(R.dimen.complicationDrawable_textSize));
-        style.setTitleSize(r.getDimensionPixelSize(R.dimen.complicationDrawable_titleSize));
-        style.setIconColor(r.getColor(R.color.complicationDrawable_iconColor, null));
-        style.setBorderColor(r.getColor(R.color.complicationDrawable_borderColor, null));
-        style.setBorderWidth(r.getDimensionPixelSize(R.dimen.complicationDrawable_borderWidth));
-        style.setBorderRadius(r.getDimensionPixelSize(R.dimen.complicationDrawable_borderRadius));
-        style.setBorderStyle(r.getInteger(R.integer.complicationDrawable_borderStyle));
-        style.setBorderDashWidth(
-                r.getDimensionPixelSize(R.dimen.complicationDrawable_borderDashWidth));
-        style.setBorderDashGap(r.getDimensionPixelSize(R.dimen.complicationDrawable_borderDashGap));
-        style.setRangedValueRingWidth(
-                r.getDimensionPixelSize(R.dimen.complicationDrawable_rangedValueRingWidth));
-        style.setRangedValuePrimaryColor(
-                r.getColor(R.color.complicationDrawable_rangedValuePrimaryColor, null));
-        style.setRangedValueSecondaryColor(
-                r.getColor(R.color.complicationDrawable_rangedValueSecondaryColor, null));
-        style.setHighlightColor(r.getColor(R.color.complicationDrawable_highlightColor, null));
-    }
-
-    /**
-     * Sets the context used to render the complication. If a context is not set,
-     * ComplicationDrawable will throw an {@link IllegalStateException} if one of
-     * {@link #draw(Canvas)}, {@link #setBounds(Rect)}, or {@link
-     * #setComplicationData(ComplicationData, boolean)} is called.
-     *
-     * <p>While this can be called from any context, ideally, a
-     * androidx.wear.watchface.WatchFaceService object should be passed here to allow creating
-     * permission dialogs by the {@link #onTap(int, int)} method, in case current watch face
-     * doesn't have the permission to receive complication data.
-     *
-     * <p>If this ComplicationDrawable is retrieved using {@link Resources#getDrawable(int, Theme)},
-     * this method must be called before calling any of the methods mentioned above.
-     *
-     * <p>If this ComplicationDrawable is not inflated from an XML file, this method will reset the
-     * style to match the default values, so if {@link #ComplicationDrawable()} is used to construct
-     * a ComplicationDrawable, this method should be called right after.
-     */
-    public void setContext(@NonNull Context context) {
-        if (context == null) {
-            throw new IllegalArgumentException("Argument \"context\" should not be null.");
-        }
-        if (Objects.equals(context, mContext)) {
-            return;
-        }
-        mContext = context;
-
-        if (!mIsInflatedFromXml && !mAlreadyStyled) {
-            setStyleToDefaultValues(mActiveStyle, context.getResources());
-            setStyleToDefaultValues(mAmbientStyle, context.getResources());
-        }
-
-        if (!mAlreadyStyled) {
-            mHighlightDuration = context.getResources()
-                    .getInteger(R.integer.complicationDrawable_highlightDurationMs);
-        }
-
-        mComplicationRenderer = new ComplicationRenderer(mContext, mActiveStyle, mAmbientStyle);
-        mComplicationRenderer.setOnInvalidateListener(mRendererInvalidateListener);
-        if (mNoDataText == null) {
-            setNoDataText(context.getString(R.string.complicationDrawable_noDataText));
-        } else {
-            mComplicationRenderer.setNoDataText(mNoDataText);
-        }
-        mComplicationRenderer.setRangedValueProgressHidden(mRangedValueProgressHidden);
-        mComplicationRenderer.setBounds(getBounds());
-    }
-
-    /**
-     * Returns the {@link Context} used to render the complication.
-     */
-    @Nullable public Context getContext() {
-        return mContext;
-    }
-
-    private void inflateAttributes(Resources r, XmlPullParser parser) {
-        TypedArray a =
-                r.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.ComplicationDrawable);
-        setRangedValueProgressHidden(
-                a.getBoolean(R.styleable.ComplicationDrawable_rangedValueProgressHidden, false));
-        a.recycle();
-    }
-
-    private void inflateStyle(boolean isAmbient, Resources r, XmlPullParser parser) {
-        TypedArray a =
-                r.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.ComplicationDrawable);
-        ComplicationStyle complicationStyle = isAmbient ? mAmbientStyle : mActiveStyle;
-        if (a.hasValue(R.styleable.ComplicationDrawable_backgroundColor)) {
-            complicationStyle.setBackgroundColor(
-                    a.getColor(
-                            R.styleable.ComplicationDrawable_backgroundColor,
-                            r.getColor(R.color.complicationDrawable_backgroundColor, null)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_backgroundDrawable)) {
-            complicationStyle.setBackgroundDrawable(
-                    a.getDrawable(R.styleable.ComplicationDrawable_backgroundDrawable));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_textColor)) {
-            complicationStyle.setTextColor(
-                    a.getColor(
-                            R.styleable.ComplicationDrawable_textColor,
-                            r.getColor(R.color.complicationDrawable_textColor, null)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_titleColor)) {
-            complicationStyle.setTitleColor(
-                    a.getColor(
-                            R.styleable.ComplicationDrawable_titleColor,
-                            r.getColor(R.color.complicationDrawable_titleColor, null)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_textTypeface)) {
-            complicationStyle.setTextTypeface(
-                    Typeface.create(
-                            a.getString(R.styleable.ComplicationDrawable_textTypeface),
-                            Typeface.NORMAL));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_titleTypeface)) {
-            complicationStyle.setTitleTypeface(
-                    Typeface.create(
-                            a.getString(R.styleable.ComplicationDrawable_titleTypeface),
-                            Typeface.NORMAL));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_textSize)) {
-            complicationStyle.setTextSize(
-                    a.getDimensionPixelSize(
-                            R.styleable.ComplicationDrawable_textSize,
-                            r.getDimensionPixelSize(R.dimen.complicationDrawable_textSize)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_titleSize)) {
-            complicationStyle.setTitleSize(
-                    a.getDimensionPixelSize(
-                            R.styleable.ComplicationDrawable_titleSize,
-                            r.getDimensionPixelSize(R.dimen.complicationDrawable_titleSize)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_iconColor)) {
-            complicationStyle.setIconColor(
-                    a.getColor(
-                            R.styleable.ComplicationDrawable_iconColor,
-                            r.getColor(R.color.complicationDrawable_iconColor, null)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_borderColor)) {
-            complicationStyle.setBorderColor(
-                    a.getColor(
-                            R.styleable.ComplicationDrawable_borderColor,
-                            r.getColor(R.color.complicationDrawable_borderColor, null)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_borderRadius)) {
-            complicationStyle.setBorderRadius(
-                    a.getDimensionPixelSize(
-                            R.styleable.ComplicationDrawable_borderRadius,
-                            r.getDimensionPixelSize(R.dimen.complicationDrawable_borderRadius)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_borderStyle)) {
-            complicationStyle.setBorderStyle(
-                    a.getInt(
-                            R.styleable.ComplicationDrawable_borderStyle,
-                            r.getInteger(R.integer.complicationDrawable_borderStyle)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_borderDashWidth)) {
-            complicationStyle.setBorderDashWidth(
-                    a.getDimensionPixelSize(
-                            R.styleable.ComplicationDrawable_borderDashWidth,
-                            r.getDimensionPixelSize(R.dimen.complicationDrawable_borderDashWidth)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_borderDashGap)) {
-            complicationStyle.setBorderDashGap(
-                    a.getDimensionPixelSize(
-                            R.styleable.ComplicationDrawable_borderDashGap,
-                            r.getDimensionPixelSize(R.dimen.complicationDrawable_borderDashGap)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_borderWidth)) {
-            complicationStyle.setBorderWidth(
-                    a.getDimensionPixelSize(
-                            R.styleable.ComplicationDrawable_borderWidth,
-                            r.getDimensionPixelSize(R.dimen.complicationDrawable_borderWidth)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_rangedValueRingWidth)) {
-            complicationStyle.setRangedValueRingWidth(
-                    a.getDimensionPixelSize(
-                            R.styleable.ComplicationDrawable_rangedValueRingWidth,
-                            r.getDimensionPixelSize(
-                                    R.dimen.complicationDrawable_rangedValueRingWidth)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_rangedValuePrimaryColor)) {
-            complicationStyle.setRangedValuePrimaryColor(
-                    a.getColor(
-                            R.styleable.ComplicationDrawable_rangedValuePrimaryColor,
-                            r.getColor(
-                                    R.color.complicationDrawable_rangedValuePrimaryColor, null)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_rangedValueSecondaryColor)) {
-            complicationStyle.setRangedValueSecondaryColor(
-                    a.getColor(
-                            R.styleable.ComplicationDrawable_rangedValueSecondaryColor,
-                            r.getColor(
-                                    R.color.complicationDrawable_rangedValueSecondaryColor, null)));
-        }
-        if (a.hasValue(R.styleable.ComplicationDrawable_highlightColor)) {
-            complicationStyle.setHighlightColor(
-                    a.getColor(
-                            R.styleable.ComplicationDrawable_highlightColor,
-                            r.getColor(R.color.complicationDrawable_highlightColor, null)));
-        }
-        a.recycle();
-    }
-
-    /**
-     * Inflates this ComplicationDrawable from an XML resource. This can't be called more than once
-     * for each ComplicationDrawable. Note that framework may have called this once to create the
-     * ComplicationDrawable instance from an XML resource.
-     *
-     * @param r      Resources used to resolve attribute values
-     * @param parser XML parser from which to inflate this ComplicationDrawable
-     * @param attrs  Base set of attribute values
-     * @param theme  Ignored by ComplicationDrawable
-     */
-    @Override
-    @SuppressWarnings("ObjectToString")
-    public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
-            @NonNull AttributeSet attrs, @Nullable Theme theme)
-            throws XmlPullParserException, IOException {
-        if (mIsInflatedFromXml) {
-            throw new IllegalStateException("inflate may be called once only.");
-        }
-        mIsInflatedFromXml = true;
-        int type;
-        final int outerDepth = parser.getDepth();
-        // Inflate attributes always shared between active and ambient mode
-        inflateAttributes(r, parser);
-        // Reset both style builders to default values
-        setStyleToDefaultValues(mActiveStyle, r);
-        setStyleToDefaultValues(mAmbientStyle, r);
-        // Attributes of the outer tag applies to both active and ambient styles
-        inflateStyle(false, r, parser);
-        inflateStyle(true, r, parser);
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type != XmlPullParser.START_TAG) {
-                continue;
-            }
-
-            // Attributes of inner <ambient> tag applies to ambient style only
-            final String name = parser.getName();
-            if (TextUtils.equals(name, "ambient")) {
-                inflateStyle(true, r, parser);
-            } else {
-                Log.w(
-                        "ComplicationDrawable",
-                        "Unknown element: " + name + " for ComplicationDrawable " + this);
-            }
-        }
-    }
-
-    /**
-     * Draws the complication for the last known time. Last known time is derived from
-     * ComplicationDrawable#setCurrentTimeMillis(long)}.
-     *
-     * @param canvas Canvas for the complication to be drawn onto
-     */
-    @Override
-    public void draw(@NonNull Canvas canvas) {
-        assertInitialized();
-        updateStyleIfRequired();
-        mComplicationRenderer.draw(
-                canvas,
-                mCurrentTimeMillis,
-                mInAmbientMode,
-                mLowBitAmbient,
-                mBurnInProtection,
-                mHighlighted);
-    }
-
-    /** Does nothing. */
-    @Override
-    public void setAlpha(int alpha) {
-        // No op.
-    }
-
-    // TODO(b/186499115): In follow up patch, when this class is converted to Kotlin, make link
-    //  working.
-    /**
-     * Does nothing. Use {link ComplicationStyle#setImageColorFilter(ColorFilter)} instead to apply
-     * color filter to small and large images.
-     */
-    @Override
-    public void setColorFilter(@Nullable ColorFilter colorFilter) {
-        // No op.
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @deprecated This method is no longer used in graphics optimizations
-     */
-    @Override
-    @Deprecated
-    public int getOpacity() {
-        return PixelFormat.TRANSLUCENT;
-    }
-
-    @Override
-    protected void onBoundsChange(@NonNull Rect bounds) {
-        if (mComplicationRenderer != null) {
-            mComplicationRenderer.setBounds(bounds);
-        }
-    }
-
-    /**
-     * Sets the text to be rendered when {@link ComplicationData} is of type {@link
-     * ComplicationType#NO_DATA}. If {@code noDataText} is null, an empty text will be
-     * rendered.
-     */
-    public void setNoDataText(@Nullable CharSequence noDataText) {
-        if (noDataText == null) {
-            mNoDataText = "";
-        } else {
-            mNoDataText = noDataText.subSequence(0, noDataText.length());
-        }
-        if (mComplicationRenderer != null) {
-            mComplicationRenderer.setNoDataText(mNoDataText);
-        }
-    }
-
-    /**
-     * Sets if the ranged value progress should be hidden when {@link ComplicationData} is of type
-     * {@link ComplicationType#RANGED_VALUE}.
-     *
-     * @param rangedValueProgressHidden {@code true} if progress should be hidden, {@code false}
-     *                                  otherwise
-     * @attr ref androidx.wear.watchface.complications.rendering.R
-     *     .styleable#ComplicationDrawable_rangedValueProgressHidden
-     */
-    public void setRangedValueProgressHidden(boolean rangedValueProgressHidden) {
-        mRangedValueProgressHidden = rangedValueProgressHidden;
-        if (mComplicationRenderer != null) {
-            mComplicationRenderer.setRangedValueProgressHidden(rangedValueProgressHidden);
-        }
-    }
-
-    /** Returns {@code true} if the ranged value progress is hidden, {@code false} otherwise. */
-    public boolean isRangedValueProgressHidden() {
-        return mRangedValueProgressHidden;
-    }
-
-    /**
-     * Sets the complication data to be drawn. If {@code complicationData} is {@code null}, nothing
-     * will be drawn when {@link #draw(Canvas)} is called.
-     *
-     * @param complicationData The [ComplicationData] to set
-     * @param loadDrawablesAsync If true any drawables should be loaded asynchronously,
-     *      otherwise they will be loaded synchronously.
-     */
-    public void setComplicationData(
-            @Nullable ComplicationData complicationData,
-            boolean loadDrawablesAsync
-    ) {
-        assertInitialized();
-        mComplicationRenderer.setComplicationData(
-                complicationData != null ? complicationData.asWireComplicationData() : null,
-                loadDrawablesAsync
-        );
-    }
-
-    /**
-     * Returns the {@link ComplicationData} to be drawn by this ComplicationDrawable.
-     */
-    @Nullable
-    public ComplicationData getComplicationData() {
-        return (mComplicationRenderer.getComplicationData() != null)
-                ? DataKt.toApiComplicationData(mComplicationRenderer.getComplicationData()) : null;
-    }
-
-    /** Sets whether the complication should be rendered in ambient mode. */
-    public void setInAmbientMode(boolean inAmbientMode) {
-        mInAmbientMode = inAmbientMode;
-    }
-
-    /** Returns whether the complication is rendered in ambient mode. */
-    public boolean isInAmbientMode() {
-        return mInAmbientMode;
-    }
-
-    /**
-     * Sets whether the complication, when rendering in ambient mode, should apply a style suitable
-     * for low bit ambient mode.
-     */
-    public void setLowBitAmbient(boolean lowBitAmbient) {
-        mLowBitAmbient = lowBitAmbient;
-    }
-
-    /**
-     * Returns whether the complication, when rendering in ambient mode, should apply a style
-     * suitable for low bit ambient mode.
-     */
-    public boolean isLowBitAmbient() {
-        return mLowBitAmbient;
-    }
-
-    /**
-     * Sets whether the complication, when rendering in ambient mode, should apply a style suitable
-     * for display on devices with burn in protection.
-     */
-    public void setBurnInProtection(boolean burnInProtection) {
-        mBurnInProtection = burnInProtection;
-    }
-
-    /**
-     * Whether the complication, when rendering in ambient mode, should apply a style suitable for
-     * display on devices with burn in protection.
-     */
-    public boolean isBurnInProtectionOn() {
-        return mBurnInProtection;
-    }
-
-    /**
-     * Sets the current time in mulliseconds since the epoch. This will be used to render
-     * {@link ComplicationData} with time dependent text.
-     *
-     * @param currentTimeMillis time in milliseconds since the epoch
-     */
-    public void setCurrentTimeMillis(long currentTimeMillis) {
-        mCurrentTimeMillis = currentTimeMillis;
-    }
-
-    /**
-     * Returns the time in milliseconds since the epoch used for rendering {@link ComplicationData}
-     * with time dependent text.
-     */
-    public long getCurrentTimeMillis() {
-        return mCurrentTimeMillis;
-    }
-
-    /**
-     * Sets whether the complication is currently highlighted. This may be called by a watch face
-     * when a complication is tapped.
-     *
-     * <p>If watch face is in ambient mode, highlight will not be visible even if this is set to
-     * {@code true}, because it may cause burn-in or power inefficiency.
-     */
-    public void setHighlighted(boolean isHighlighted) {
-        mHighlighted = isHighlighted;
-    }
-
-    /**
-     * Returns whether the complication is currently highlighted.
-     */
-    public boolean isHighlighted() {
-        return mHighlighted;
-    }
-
-    /**
-     * Sends the tap action for the complication if tap coordinates are inside the complication
-     * bounds.
-     *
-     * <p>This method will also highlight the complication. The highlight duration is 300
-     * milliseconds by default but can be modified using the {@link #setHighlightDuration(long)}
-     * method.
-     *
-     * <p>If {@link ComplicationData} has the type {@link ComplicationType#NO_PERMISSION}, this
-     * method will launch an intent to request complication permission for the watch face. This will
-     * only work if the context set by {@link #getDrawable} or the constructor is an
-     * instance of WatchFaceService.
-     *
-     * @param x X coordinate of the tap relative to screen origin
-     * @param y Y coordinate of the tap relative to screen origin
-     * @return {@code true} if the action was successful, {@code false} if complication data is not
-     * set, the complication has no tap action, the tap action (i.e. {@link
-     * android.app.PendingIntent}) is cancelled, or the given x and y are not inside the
-     * complication bounds.
-     */
-    public boolean onTap(@Px int x, @Px int y) {
-        if (mComplicationRenderer == null) {
-            return false;
-        }
-        android.support.wearable.complications.ComplicationData data =
-                mComplicationRenderer.getComplicationData();
-        if (data == null) {
-            return false;
-        }
-        if (!data.hasTapAction() && data.getType()
-                != android.support.wearable.complications.ComplicationData.TYPE_NO_PERMISSION) {
-            return false;
-        }
-        if (!getBounds().contains(x, y)) {
-            return false;
-        }
-        if (data.getType()
-                == android.support.wearable.complications.ComplicationData.TYPE_NO_PERMISSION) {
-            // Check if mContext is an instance of WatchFaceService. We can't use the standard
-            // instanceof operator because WatchFaceService is defined in library which depends on
-            // this one, hence the reflection hack.
-            try {
-                if (Class.forName("androidx.wear.watchface.WatchFaceService")
-                        .isInstance(mContext)) {
-                    mContext.startActivity(
-                            ComplicationHelperActivity.createPermissionRequestHelperIntent(
-                                    mContext,
-                                    new ComponentName(mContext, mContext.getClass()))
-                                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
-                } else {
-                    return false;
-                }
-            } catch (ClassNotFoundException e) {
-                // If watchFaceServiceClass class isn't found we know mContext can't be an instance
-                // of WatchFaceService.
-                return false;
-            }
-        } else {
-            try {
-                data.getTapAction().send();
-            } catch (CanceledException e) {
-                return false;
-            }
-        }
-        if (getHighlightDuration() > 0) {
-            setHighlighted(true);
-            invalidateSelf();
-            mMainThreadHandler.removeCallbacks(mUnhighlightRunnable);
-            mMainThreadHandler.postDelayed(mUnhighlightRunnable, getHighlightDuration());
-        }
-        return true;
-    }
-
-    /**
-     * Sets the duration for the complication to stay highlighted after calling the {@link
-     * #onTap(int, int)} method. Default value is 300 milliseconds. Setting highlight duration to 0
-     * disables highlighting.
-     *
-     * @param highlightDurationMillis highlight duration in milliseconds
-     */
-    public void setHighlightDuration(@IntRange(from = 0) long highlightDurationMillis) {
-        if (highlightDurationMillis < 0) {
-            throw new IllegalArgumentException("Highlight duration should be non-negative.");
-        }
-        mHighlightDuration = highlightDurationMillis;
-    }
-
-    /** Returns the highlight duration. */
-    public long getHighlightDuration() {
-        return mHighlightDuration;
-    }
-
-    /** Builds styles and syncs them with the complication renderer. */
-    void updateStyleIfRequired() {
-        if (mActiveStyle.isDirty() || mAmbientStyle.isDirty()) {
-            mComplicationRenderer.updateStyle(mActiveStyle, mAmbientStyle);
-            mActiveStyle.clearDirtyFlag();
-            mAmbientStyle.clearDirtyFlag();
-        }
-    }
-
-    /**
-     * Throws an exception if the context is not set. This method should be called if any of the
-     * member methods do a context-dependent job.
-     */
-    private void assertInitialized() {
-        if (mContext == null) {
-            throw new IllegalStateException(
-                    "ComplicationDrawable does not have a context. Use setContext(Context) to set"
-                            + " it first.");
-        }
-    }
-
-    /** Returns complication style for active mode. */
-    @NonNull
-    public ComplicationStyle getActiveStyle() {
-        return mActiveStyle;
-    }
-
-    /** Returns complication style for ambient mode. */
-    @NonNull
-    public ComplicationStyle getAmbientStyle() {
-        return mAmbientStyle;
-    }
-
-    /** Returns complication renderer. */
-    @Nullable
-    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
-    public ComplicationRenderer getComplicationRenderer() {
-        return mComplicationRenderer;
-    }
-
-    /**
-     * Returns the text to be rendered when {@link ComplicationData} is of type {@link
-     * ComplicationType#NO_DATA}.
-     */
-    @Nullable
-    public CharSequence getNoDataText() {
-        return mNoDataText;
-    }
-}
diff --git a/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationDrawable.kt b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationDrawable.kt
new file mode 100644
index 0000000..0639d79
--- /dev/null
+++ b/wear/wear-watchface-complications-rendering/src/main/java/androidx/wear/watchface/complications/rendering/ComplicationDrawable.kt
@@ -0,0 +1,751 @@
+/*
+ * 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.wear.watchface.complications.rendering
+
+import android.app.PendingIntent
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.res.Resources
+import android.graphics.Canvas
+import android.graphics.ColorFilter
+import android.graphics.Rect
+import android.graphics.Typeface
+import android.graphics.drawable.Drawable
+import android.os.Handler
+import android.os.Looper
+import android.text.TextUtils
+import android.util.AttributeSet
+import android.util.Log
+import android.util.Xml
+import androidx.annotation.IntRange
+import androidx.annotation.Px
+import androidx.annotation.VisibleForTesting
+import androidx.wear.complications.ComplicationHelperActivity
+import androidx.wear.complications.data.ComplicationData
+import androidx.wear.complications.data.ComplicationType.NO_DATA
+import androidx.wear.complications.data.ComplicationType.NO_PERMISSION
+import androidx.wear.complications.data.ComplicationType.RANGED_VALUE
+import androidx.wear.complications.data.toApiComplicationData
+import androidx.wear.watchface.complications.rendering.ComplicationRenderer.OnInvalidateListener
+import org.xmlpull.v1.XmlPullParser
+import org.xmlpull.v1.XmlPullParserException
+import java.io.IOException
+
+/**
+ * A styleable drawable object that draws complications. You can create a ComplicationDrawable from
+ * XML inflation or by using one of the constructor methods.
+ *
+ * <h3>Constructing a ComplicationDrawable</h3>
+ *
+ * To construct a ComplicationDrawable programmatically, use the [ComplicationDrawable]
+ * constructor. Afterwards, styling attributes you want to modify
+ * can be set via set methods.
+ *
+ * ```
+ * public void onCreate(SurfaceHolder holder) {
+ * ...
+ * ComplicationDrawable complicationDrawable = new ComplicationDrawable(WatchFaceService.this);
+ * complicationDrawable.setBackgroundColorActive(backgroundColor);
+ * complicationDrawable.setTextColorActive(textColor);
+ * ...
+ * }
+ * ```
+ *
+ * <h3>Constructing a ComplicationDrawable from XML</h3>
+ *
+ * Constructing a ComplicationDrawable from an XML file makes it easier to modify multiple
+ * styling attributes at once without calling any set methods. You may also use different XML files
+ * to switch between different styles your watch face supports.
+ *
+ *
+ * To construct a ComplicationDrawable from a drawable XML file, you may create an XML file in
+ * your project's `res/drawable` folder. A ComplicationDrawable with red text and white title
+ * in active mode, and white text and white title in ambient mode would look like this:
+ *
+ * ```
+ * <?xml version="1.0" encoding="utf-8"?>
+ * <android.support.wearable.complications.rendering.ComplicationDrawable
+ * xmlns:app="http://schemas.android.com/apk/res-auto"
+ * app:textColor="#FFFF0000"
+ * app:titleColor="#FFFFFFFF">
+ * <ambient
+ * app:textColor="#FFFFFFFF" />
+ * </android.support.wearable.complications.rendering.ComplicationDrawable>
+ * ```
+ *
+ *
+ * A top-level `drawable` tag with the `class` attribute may also be used to
+ * construct a ComplicationDrawable from an XML file:
+ *
+ * ```
+ * <?xml version="1.0" encoding="utf-8"?>
+ * <drawable
+ * class="android.support.wearable.complications.rendering.ComplicationDrawable"
+ * xmlns:app="http://schemas.android.com/apk/res-auto"
+ * app:textColor="#FFFF0000"
+ * app:titleColor="#FFFFFFFF">
+ * <ambient
+ * app:textColor="#FFFFFFFF" />
+ * </drawable>
+ * ```
+ *
+ * To inflate a ComplicationDrawable from XML file, use the [.getDrawable]
+ * method. ComplicationDrawable needs access to the current context in order to style and draw
+ * the complication.
+ *
+ * ```
+ * public void onCreate(SurfaceHolder holder) {
+ * ...
+ * ComplicationDrawable complicationDrawable = (ComplicationDrawable)
+ * getDrawable(R.drawable.complication);
+ * complicationDrawable.setContext(WatchFaceService.this);
+ * ...
+ * }
+ * ```
+ *
+ * <h4>Syntax:</h4>
+ * ```
+ * <?xml version="1.0" encoding="utf-8"?>
+ * <android.support.wearable.complications.rendering.ComplicationDrawable
+ * xmlns:app="http://schemas.android.com/apk/res-auto"
+ * app:backgroundColor="color"
+ * app:backgroundDrawable="drawable"
+ * app:borderColor="color"
+ * app:borderDashGap="dimension"
+ * app:borderDashWidth="dimension"
+ * app:borderRadius="dimension"
+ * app:borderStyle="none|solid|dashed"
+ * app:borderWidth="dimension"
+ * app:highlightColor="color"
+ * app:iconColor="color"
+ * app:rangedValuePrimaryColor="color"
+ * app:rangedValueProgressHidden="boolean"
+ * app:rangedValueRingWidth="dimension"
+ * app:rangedValueSecondaryColor="color"
+ * app:textColor="color"
+ * app:textSize="dimension"
+ * app:textTypeface="string"
+ * app:titleColor="color"
+ * app:titleSize="dimension"
+ * app:titleTypeface="string">
+ * <ambient
+ * app:backgroundColor="color"
+ * app:backgroundDrawable="drawable"
+ * app:borderColor="color"
+ * app:borderDashGap="dimension"
+ * app:borderDashWidth="dimension"
+ * app:borderRadius="dimension"
+ * app:borderStyle="none|solid|dashed"
+ * app:borderWidth="dimension"
+ * app:highlightColor="color"
+ * app:iconColor="color"
+ * app:rangedValuePrimaryColor="color"
+ * app:rangedValueRingWidth="dimension"
+ * app:rangedValueSecondaryColor="color"
+ * app:textColor="color"
+ * app:textSize="dimension"
+ * app:textTypeface="string"
+ * app:titleColor="color"
+ * app:titleSize="dimension"
+ * app:titleTypeface="string" />
+ * </android.support.wearable.complications.rendering.ComplicationDrawable>
+ * ```
+ *
+ * Attributes of the top-level tag apply to both active and ambient modes while attributes of the
+ * inner `ambient` tag only apply to ambient mode. As an exception, top-level only
+ * `rangedValueProgressHidden` attribute applies to both modes, and cannot be overridden in ambient
+ * mode. To hide ranged value in only one of the active or ambient modes, you may consider setting
+ * `rangedValuePrimaryColor` and `rangedValueSecondaryColor` to [android.graphics.Color.TRANSPARENT]
+ * instead.
+ *
+ * <h3>Drawing a ComplicationDrawable</h3>
+ *
+ * Depending on the size and shape of the bounds, the layout of the complication may change. For
+ * instance, a short text complication with an icon that is drawn on square bounds would draw the
+ * icon above the short text, but a short text complication with an icon that is drawn on wide
+ * rectangular bounds might draw the icon to the left of the short text instead.
+ */
+public class ComplicationDrawable : Drawable {
+    /**
+     * Returns the [Context] used to render the complication.
+     */
+    public var context: Context? = null
+        private set
+
+    /** Returns complication renderer.  */
+    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+    @get:JvmName("getComplicationRenderer")
+    internal var complicationRenderer: ComplicationRenderer? = null
+        private set
+
+    /** Returns complication style for active mode.  */
+    public val activeStyle: ComplicationStyle
+
+    /** Returns complication style for ambient mode.  */
+    public val ambientStyle: ComplicationStyle
+
+    private val mainThreadHandler = Handler(Looper.getMainLooper())
+    private val unhighlightRunnable = Runnable {
+        isHighlighted = false
+        invalidateSelf()
+    }
+    private val rendererInvalidateListener = OnInvalidateListener { invalidateSelf() }
+
+    /**
+     * The time in milliseconds since the epoch used for rendering [ComplicationData]
+     * with time dependent text.
+     */
+    public var currentTimeMillis: Long = 0
+
+    /** Whether the complication is rendered in ambient mode.  */
+    public var isInAmbientMode: Boolean = false
+
+    /**
+     * Whether the complication, when rendering in ambient mode, should apply a style
+     * suitable for low bit ambient mode.
+     */
+    public var isLowBitAmbient: Boolean = false
+
+    /**
+     * Whether the complication, when rendering in ambient mode, should apply a style suitable for
+     * display on devices with burn in protection.
+     */
+    public var isBurnInProtectionOn: Boolean = false
+
+    /**
+     * Whether the complication is currently highlighted. This may be called by a watch face
+     * when a complication is tapped.
+     *
+     * If watch face is in ambient mode, highlight will not be visible even if this is set to
+     * `true`, because it may cause burn-in or power inefficiency.
+     */
+    public var isHighlighted: Boolean = false
+
+    private var isInflatedFromXml = false
+    private var alreadyStyled = false
+
+    /** Default constructor.  */
+    public constructor() {
+        activeStyle = ComplicationStyle()
+        ambientStyle = ComplicationStyle()
+    }
+
+    /**
+     * Creates a ComplicationDrawable using the given context. If this constructor is used, calling
+     * [.setContext] may not be necessary.
+     */
+    public constructor(context: Context) : this() {
+        setContext(context)
+    }
+
+    public constructor(drawable: ComplicationDrawable) {
+        activeStyle = ComplicationStyle(drawable.activeStyle)
+        ambientStyle = ComplicationStyle(drawable.ambientStyle)
+        noDataText = drawable.noDataText!!.subSequence(0, drawable.noDataText!!.length)
+        highlightDuration = drawable.highlightDuration
+        currentTimeMillis = drawable.currentTimeMillis
+        bounds = drawable.bounds
+        isInAmbientMode = drawable.isInAmbientMode
+        isLowBitAmbient = drawable.isLowBitAmbient
+        isBurnInProtectionOn = drawable.isBurnInProtectionOn
+        isHighlighted = false
+        isRangedValueProgressHidden = drawable.isRangedValueProgressHidden
+        isInflatedFromXml = drawable.isInflatedFromXml
+        alreadyStyled = true
+    }
+
+    /**
+     * Sets the context used to render the complication. If a context is not set,
+     * ComplicationDrawable will throw an [IllegalStateException] if one of [draw], [setBounds],
+     * or [setComplicationData] is called.
+     *
+     * While this can be called from any context, ideally, a
+     * androidx.wear.watchface.WatchFaceService object should be passed here to allow creating
+     * permission dialogs by the [onTap] method, in case current watch face doesn't have the
+     * permission to receive complication data.
+     *
+     * If this ComplicationDrawable is retrieved using [Resources.getDrawable], this method must
+     * be called before calling any of the methods mentioned above.
+     *
+     * If this ComplicationDrawable is not inflated from an XML file, this method will reset the
+     * style to match the default values, so if [ComplicationDrawable()] is used to construct a
+     * ComplicationDrawable, this method should be called right after.
+     */
+    public fun setContext(context: Context) {
+        if (context == this.context) {
+            return
+        }
+        this.context = context
+        if (!isInflatedFromXml && !alreadyStyled) {
+            setStyleToDefaultValues(activeStyle, context.resources)
+            setStyleToDefaultValues(ambientStyle, context.resources)
+        }
+        if (!alreadyStyled) {
+            highlightDuration = context.resources
+                .getInteger(R.integer.complicationDrawable_highlightDurationMs).toLong()
+        }
+        complicationRenderer = ComplicationRenderer(this.context, activeStyle, ambientStyle)
+        val nonNullComplicationRenderer = complicationRenderer!!
+        nonNullComplicationRenderer.setOnInvalidateListener(rendererInvalidateListener)
+        if (noDataText == null) {
+            noDataText = context.getString(R.string.complicationDrawable_noDataText)
+        } else {
+            nonNullComplicationRenderer.setNoDataText(noDataText)
+        }
+        nonNullComplicationRenderer.isRangedValueProgressHidden = isRangedValueProgressHidden
+        nonNullComplicationRenderer.bounds = bounds
+    }
+
+    private fun inflateAttributes(r: Resources, parser: XmlPullParser) {
+        val a = r.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.ComplicationDrawable)
+        isRangedValueProgressHidden =
+            a.getBoolean(R.styleable.ComplicationDrawable_rangedValueProgressHidden, false)
+        a.recycle()
+    }
+
+    private fun inflateStyle(isAmbient: Boolean, r: Resources, parser: XmlPullParser) {
+        val a = r.obtainAttributes(Xml.asAttributeSet(parser), R.styleable.ComplicationDrawable)
+        val complicationStyle = if (isAmbient) ambientStyle else activeStyle
+        if (a.hasValue(R.styleable.ComplicationDrawable_backgroundColor)) {
+            complicationStyle.backgroundColor = a.getColor(
+                R.styleable.ComplicationDrawable_backgroundColor,
+                r.getColor(R.color.complicationDrawable_backgroundColor, null)
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_backgroundDrawable)) {
+            complicationStyle.backgroundDrawable =
+                a.getDrawable(R.styleable.ComplicationDrawable_backgroundDrawable)
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_textColor)) {
+            complicationStyle.textColor = a.getColor(
+                R.styleable.ComplicationDrawable_textColor,
+                r.getColor(R.color.complicationDrawable_textColor, null)
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_titleColor)) {
+            complicationStyle.titleColor = a.getColor(
+                R.styleable.ComplicationDrawable_titleColor,
+                r.getColor(R.color.complicationDrawable_titleColor, null)
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_textTypeface)) {
+            complicationStyle.setTextTypeface(
+                Typeface.create(
+                    a.getString(R.styleable.ComplicationDrawable_textTypeface),
+                    Typeface.NORMAL
+                )
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_titleTypeface)) {
+            complicationStyle.setTitleTypeface(
+                Typeface.create(
+                    a.getString(R.styleable.ComplicationDrawable_titleTypeface),
+                    Typeface.NORMAL
+                )
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_textSize)) {
+            complicationStyle.textSize = a.getDimensionPixelSize(
+                R.styleable.ComplicationDrawable_textSize,
+                r.getDimensionPixelSize(R.dimen.complicationDrawable_textSize)
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_titleSize)) {
+            complicationStyle.titleSize = a.getDimensionPixelSize(
+                R.styleable.ComplicationDrawable_titleSize,
+                r.getDimensionPixelSize(R.dimen.complicationDrawable_titleSize)
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_iconColor)) {
+            complicationStyle.iconColor = a.getColor(
+                R.styleable.ComplicationDrawable_iconColor,
+                r.getColor(R.color.complicationDrawable_iconColor, null)
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_borderColor)) {
+            complicationStyle.borderColor = a.getColor(
+                R.styleable.ComplicationDrawable_borderColor,
+                r.getColor(R.color.complicationDrawable_borderColor, null)
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_borderRadius)) {
+            complicationStyle.borderRadius = a.getDimensionPixelSize(
+                R.styleable.ComplicationDrawable_borderRadius,
+                r.getDimensionPixelSize(R.dimen.complicationDrawable_borderRadius)
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_borderStyle)) {
+            complicationStyle.borderStyle = a.getInt(
+                R.styleable.ComplicationDrawable_borderStyle,
+                r.getInteger(R.integer.complicationDrawable_borderStyle)
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_borderDashWidth)) {
+            complicationStyle.borderDashWidth = a.getDimensionPixelSize(
+                R.styleable.ComplicationDrawable_borderDashWidth,
+                r.getDimensionPixelSize(R.dimen.complicationDrawable_borderDashWidth)
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_borderDashGap)) {
+            complicationStyle.borderDashGap = a.getDimensionPixelSize(
+                R.styleable.ComplicationDrawable_borderDashGap,
+                r.getDimensionPixelSize(R.dimen.complicationDrawable_borderDashGap)
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_borderWidth)) {
+            complicationStyle.borderWidth = a.getDimensionPixelSize(
+                R.styleable.ComplicationDrawable_borderWidth,
+                r.getDimensionPixelSize(R.dimen.complicationDrawable_borderWidth)
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_rangedValueRingWidth)) {
+            complicationStyle.rangedValueRingWidth = a.getDimensionPixelSize(
+                R.styleable.ComplicationDrawable_rangedValueRingWidth,
+                r.getDimensionPixelSize(
+                    R.dimen.complicationDrawable_rangedValueRingWidth
+                )
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_rangedValuePrimaryColor)) {
+            complicationStyle.rangedValuePrimaryColor = a.getColor(
+                R.styleable.ComplicationDrawable_rangedValuePrimaryColor,
+                r.getColor(
+                    R.color.complicationDrawable_rangedValuePrimaryColor, null
+                )
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_rangedValueSecondaryColor)) {
+            complicationStyle.rangedValueSecondaryColor = a.getColor(
+                R.styleable.ComplicationDrawable_rangedValueSecondaryColor,
+                r.getColor(
+                    R.color.complicationDrawable_rangedValueSecondaryColor, null
+                )
+            )
+        }
+        if (a.hasValue(R.styleable.ComplicationDrawable_highlightColor)) {
+            complicationStyle.highlightColor = a.getColor(
+                R.styleable.ComplicationDrawable_highlightColor,
+                r.getColor(R.color.complicationDrawable_highlightColor, null)
+            )
+        }
+        a.recycle()
+    }
+
+    /**
+     * Inflates this ComplicationDrawable from an XML resource. This can't be called more than once
+     * for each ComplicationDrawable. Note that framework may have called this once to create the
+     * ComplicationDrawable instance from an XML resource.
+     *
+     * @param r      Resources used to resolve attribute values
+     * @param parser XML parser from which to inflate this ComplicationDrawable
+     * @param attrs  Base set of attribute values
+     * @param theme  Ignored by ComplicationDrawable
+     */
+    @Throws(XmlPullParserException::class, IOException::class)
+    public override fun inflate(
+        r: Resources,
+        parser: XmlPullParser,
+        attrs: AttributeSet,
+        theme: Resources.Theme?
+    ) {
+        check(!isInflatedFromXml) { "inflate may be called once only." }
+        isInflatedFromXml = true
+        var type: Int
+        val outerDepth = parser.depth
+        // Inflate attributes always shared between active and ambient mode
+        inflateAttributes(r, parser)
+        // Reset both style builders to default values
+        setStyleToDefaultValues(activeStyle, r)
+        setStyleToDefaultValues(ambientStyle, r)
+        // Attributes of the outer tag applies to both active and ambient styles
+        inflateStyle(false, r, parser)
+        inflateStyle(true, r, parser)
+        while (
+            parser.next().also { type = it } != XmlPullParser.END_DOCUMENT &&
+            (type != XmlPullParser.END_TAG || parser.depth > outerDepth)
+        ) {
+            if (type != XmlPullParser.START_TAG) {
+                continue
+            }
+
+            // Attributes of inner <ambient> tag applies to ambient style only
+            val name = parser.name
+            if (TextUtils.equals(name, "ambient")) {
+                inflateStyle(true, r, parser)
+            } else {
+                Log.w(
+                    "ComplicationDrawable",
+                    "Unknown element: $name for ComplicationDrawable $this"
+                )
+            }
+        }
+    }
+
+    /**
+     * Draws the complication for the last known time. Last known time is derived from
+     * ComplicationDrawable#setCurrentTimeMillis(long)}.
+     *
+     * @param canvas Canvas for the complication to be drawn onto
+     */
+    public override fun draw(canvas: Canvas) {
+        assertInitialized()
+        updateStyleIfRequired()
+        complicationRenderer?.draw(
+            canvas,
+            currentTimeMillis,
+            isInAmbientMode,
+            isLowBitAmbient,
+            isBurnInProtectionOn,
+            isHighlighted
+        )
+    }
+
+    /**
+     * This function is not supported in [ComplicationDrawable].
+     *
+     * @throws [UnsupportedOperationException] when called.
+     */
+    public override fun setAlpha(@IntRange(from = 0, to = 255) alpha: Int) {
+        throw UnsupportedOperationException("setAlpha is not supported in ComplicationDrawable.")
+    }
+
+    /**
+     * This function is not supported in [ComplicationDrawable]. Use
+     * [ComplicationStyle.imageColorFilter] instead to apply color filter to small and large images.
+     *
+     * @throws [UnsupportedOperationException] when called.
+     */
+    public override fun setColorFilter(colorFilter: ColorFilter?) {
+        throw UnsupportedOperationException(
+            "setColorFilter is not supported in ComplicationDrawable."
+        )
+    }
+
+    /** @throws [UnsupportedOperationException] when called. */
+    @Deprecated("This method is no longer used in graphics optimizations")
+    override fun getOpacity(): Int =
+        throw UnsupportedOperationException("getOpacity is not supported in ComplicationDrawable.")
+
+    protected override fun onBoundsChange(bounds: Rect) {
+        if (complicationRenderer != null) {
+            complicationRenderer!!.bounds = bounds
+        }
+    }
+
+    /** If the ranged value progress should be hidden when [ComplicationData] is of type
+     * [RANGED_VALUE].
+     *
+     * @attr ref androidx.wear.watchface.complications.rendering.R
+     * .styleable#ComplicationDrawable_rangedValueProgressHidden
+     */
+    public var isRangedValueProgressHidden: Boolean = false
+        set(rangedValueProgressHidden) {
+            field = rangedValueProgressHidden
+            complicationRenderer?.isRangedValueProgressHidden = rangedValueProgressHidden
+        }
+
+    /**
+     * Sets the complication data to be drawn. If `complicationData` is `null`, nothing
+     * will be drawn when [draw] is called.
+     *
+     * @param complicationData The [ComplicationData] to set
+     * @param loadDrawablesAsync If true any drawables should be loaded asynchronously,
+     * otherwise they will be loaded synchronously.
+     */
+    public fun setComplicationData(
+        complicationData: ComplicationData?,
+        loadDrawablesAsync: Boolean
+    ) {
+        assertInitialized()
+        complicationRenderer?.setComplicationData(
+            complicationData?.asWireComplicationData(),
+            loadDrawablesAsync
+        )
+    }
+
+    /**
+     * Returns the [ComplicationData] to be drawn by this ComplicationDrawable.
+     */
+    public val complicationData: ComplicationData?
+        get() = if (complicationRenderer?.complicationData != null)
+            complicationRenderer!!.complicationData.toApiComplicationData()
+        else null
+
+    /**
+     * Sends the tap action for the complication if tap coordinates are inside the complication
+     * bounds.
+     *
+     * This method will also highlight the complication. The highlight duration is 300
+     * milliseconds by default but can be modified using the [.setHighlightDuration]
+     * method.
+     *
+     * If [ComplicationData] has the type [NO_PERMISSION], this method will launch an intent to
+     * request complication permission for the watch face. This will only work if the context set
+     * by [getDrawable] or the constructor is an instance of WatchFaceService.
+     *
+     * @param x X coordinate of the tap relative to screen origin
+     * @param y Y coordinate of the tap relative to screen origin
+     * @return `true` if the action was successful, `false` if complication data is not set, the
+     * complication has no tap action, the tap action (i.e. [android.app.PendingIntent]) is
+     * cancelled, or the given x and y are not inside the complication bounds.
+     */
+    public fun onTap(@Px x: Int, @Px y: Int): Boolean {
+        if (complicationRenderer == null) {
+            return false
+        }
+        val data = complicationRenderer!!.complicationData ?: return false
+        if (!data.hasTapAction() && data.type
+            != android.support.wearable.complications.ComplicationData.TYPE_NO_PERMISSION
+        ) {
+            return false
+        }
+        if (!bounds.contains(x, y)) {
+            return false
+        }
+        if (data.type
+            == android.support.wearable.complications.ComplicationData.TYPE_NO_PERMISSION
+        ) {
+            // Check if context is an instance of WatchFaceService. We can't use the standard
+            // instanceof operator because WatchFaceService is defined in library which depends on
+            // this one, hence the reflection hack.
+            try {
+                if (context!!::class.java.name == "androidx.wear.watchface.WatchFaceService") {
+                    context!!.startActivity(
+                        ComplicationHelperActivity.createPermissionRequestHelperIntent(
+                            context!!,
+                            ComponentName(context!!, context!!.javaClass)
+                        )
+                            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                    )
+                } else {
+                    return false
+                }
+            } catch (e: ClassNotFoundException) {
+                // If watchFaceServiceClass class isn't found we know context can't be an instance
+                // of WatchFaceService.
+                return false
+            }
+        } else {
+            try {
+                data.tapAction!!.send()
+            } catch (e: PendingIntent.CanceledException) {
+                return false
+            }
+        }
+        if (highlightDuration > 0) {
+            isHighlighted = true
+            invalidateSelf()
+            mainThreadHandler.removeCallbacks(unhighlightRunnable)
+            mainThreadHandler.postDelayed(unhighlightRunnable, highlightDuration)
+        }
+        return true
+    }
+
+    /** The duration for the complication to stay highlighted after calling the [onTap] method.
+     * Default value is 300 milliseconds. Setting highlight duration to 0 disables highlighting.
+     */
+    public var highlightDuration: Long = 0
+        set(@IntRange(from = 0) highlightDurationMillis: Long) {
+            require(highlightDurationMillis >= 0) { "Highlight duration should be non-negative." }
+            field = highlightDurationMillis
+        }
+
+    /** Builds styles and syncs them with the complication renderer.  */
+    @JvmName(name = "updateStyleIfRequired")
+    internal fun updateStyleIfRequired() {
+        if (activeStyle.isDirty || ambientStyle.isDirty) {
+            complicationRenderer!!.updateStyle(activeStyle, ambientStyle)
+            activeStyle.clearDirtyFlag()
+            ambientStyle.clearDirtyFlag()
+        }
+    }
+
+    /**
+     * Throws an exception if the context is not set. This method should be called if any of the
+     * member methods do a context-dependent job.
+     */
+    private fun assertInitialized() {
+        checkNotNull(context) {
+            "ComplicationDrawable does not have a context. Use setContext(Context) to set it first."
+        }
+    }
+    /**
+     * The text to be rendered when [ComplicationData] is of type [NO_DATA]. If `noDataText` is
+     * null, an empty text will be
+     * rendered.
+     */
+    public var noDataText: CharSequence? = null
+        set(noDataText) {
+            field = noDataText?.subSequence(0, noDataText.length) ?: ""
+            if (complicationRenderer != null) {
+                complicationRenderer!!.setNoDataText(field)
+            }
+        }
+
+    public companion object {
+        /**
+         * Creates a ComplicationDrawable from a resource.
+         *
+         * @param context The [Context] to load the resource from
+         * @param id      The id of the resource to load
+         * @return The [ComplicationDrawable] loaded from the specified resource id or null if it
+         * doesn't exist.
+         */
+        @JvmStatic
+        public fun getDrawable(context: Context, id: Int): ComplicationDrawable? {
+            val drawable = context.getDrawable(id) as ComplicationDrawable? ?: return null
+            drawable.setContext(context)
+            return drawable
+        }
+
+        /** Sets the style to default values using resources.  */
+        @JvmStatic
+        internal fun setStyleToDefaultValues(style: ComplicationStyle, r: Resources) {
+            style.backgroundColor = r.getColor(R.color.complicationDrawable_backgroundColor, null)
+            style.textColor = r.getColor(R.color.complicationDrawable_textColor, null)
+            style.titleColor = r.getColor(R.color.complicationDrawable_titleColor, null)
+            style.setTextTypeface(
+                Typeface.create(
+                    r.getString(R.string.complicationDrawable_textTypeface), Typeface.NORMAL
+                )
+            )
+            style.setTitleTypeface(
+                Typeface.create(
+                    r.getString(R.string.complicationDrawable_titleTypeface), Typeface.NORMAL
+                )
+            )
+            style.textSize = r.getDimensionPixelSize(R.dimen.complicationDrawable_textSize)
+            style.titleSize = r.getDimensionPixelSize(R.dimen.complicationDrawable_titleSize)
+            style.iconColor = r.getColor(R.color.complicationDrawable_iconColor, null)
+            style.borderColor = r.getColor(R.color.complicationDrawable_borderColor, null)
+            style.borderWidth = r.getDimensionPixelSize(R.dimen.complicationDrawable_borderWidth)
+            style.borderRadius = r.getDimensionPixelSize(R.dimen.complicationDrawable_borderRadius)
+            style.borderStyle = r.getInteger(R.integer.complicationDrawable_borderStyle)
+            style.borderDashWidth =
+                r.getDimensionPixelSize(R.dimen.complicationDrawable_borderDashWidth)
+            style.borderDashGap =
+                r.getDimensionPixelSize(R.dimen.complicationDrawable_borderDashGap)
+            style.rangedValueRingWidth =
+                r.getDimensionPixelSize(R.dimen.complicationDrawable_rangedValueRingWidth)
+            style.rangedValuePrimaryColor =
+                r.getColor(R.color.complicationDrawable_rangedValuePrimaryColor, null)
+            style.rangedValueSecondaryColor =
+                r.getColor(R.color.complicationDrawable_rangedValueSecondaryColor, null)
+            style.highlightColor = r.getColor(R.color.complicationDrawable_highlightColor, null)
+        }
+    }
+}
\ No newline at end of file
diff --git a/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/ComplicationDrawableTest.java b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/ComplicationDrawableTest.java
index 223c731..ed6f874c 100644
--- a/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/ComplicationDrawableTest.java
+++ b/wear/wear-watchface-complications-rendering/src/test/java/androidx/wear/watchface/complications/rendering/ComplicationDrawableTest.java
@@ -120,11 +120,6 @@
     }
 
     @Test
-    public void callingSetContextWithNullThrowsIllegalArgumentException() {
-        assertThrows(IllegalArgumentException.class, () -> mComplicationDrawable.setContext(null));
-    }
-
-    @Test
     public void callingDrawOnCanvasBeforeSetContextThrowsAnException() {
         assertThrows(IllegalStateException.class, () -> mComplicationDrawable.draw(mMockCanvas));
     }
diff --git a/wear/wear-watchface-data/api/restricted_current.txt b/wear/wear-watchface-data/api/restricted_current.txt
index 98430d9..16f5ad0 100644
--- a/wear/wear-watchface-data/api/restricted_current.txt
+++ b/wear/wear-watchface-data/api/restricted_current.txt
@@ -308,7 +308,7 @@
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.VersionedParcelize public class ComplicationOverlayWireFormat implements android.os.Parcelable androidx.versionedparcelable.VersionedParcelable {
-    ctor public ComplicationOverlayWireFormat(int, Boolean?, java.util.Map<androidx.wear.complications.data.ComplicationType!,android.graphics.RectF!>?, Integer?);
+    ctor public ComplicationOverlayWireFormat(int, Boolean?, java.util.Map<java.lang.Integer!,android.graphics.RectF!>?, Integer?);
     method public int describeContents();
     method public Integer? getAccessibilityTraversalIndex();
     method public void writeToParcel(android.os.Parcel, int);
@@ -319,7 +319,7 @@
     field public static final long NULL_ACCESSIBILITY_TRAVERSAL_INDEX = 4294967296L; // 0x100000000L
     field @androidx.versionedparcelable.ParcelField(1) public int mComplicationId;
     field @androidx.versionedparcelable.ParcelField(2) public int mEnabled;
-    field @androidx.versionedparcelable.ParcelField(3) public java.util.Map<androidx.wear.complications.data.ComplicationType!,android.graphics.RectF!>? mPerComplicationTypeBounds;
+    field @androidx.versionedparcelable.ParcelField(3) public java.util.Map<java.lang.Integer!,android.graphics.RectF!>? mPerComplicationTypeBounds;
   }
 
   @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @androidx.versionedparcelable.VersionedParcelize public class ComplicationsOptionWireFormat extends androidx.wear.watchface.style.data.OptionWireFormat {
diff --git a/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/style/data/ComplicationOverlayWireFormat.java b/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/style/data/ComplicationOverlayWireFormat.java
index 71ebc33..e63e83b 100644
--- a/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/style/data/ComplicationOverlayWireFormat.java
+++ b/wear/wear-watchface-data/src/main/java/androidx/wear/watchface/style/data/ComplicationOverlayWireFormat.java
@@ -28,7 +28,6 @@
 import androidx.versionedparcelable.ParcelUtils;
 import androidx.versionedparcelable.VersionedParcelable;
 import androidx.versionedparcelable.VersionedParcelize;
-import androidx.wear.complications.data.ComplicationType;
 
 import java.util.Map;
 
@@ -54,7 +53,7 @@
 
     @ParcelField(3)
     @Nullable
-    public Map<ComplicationType, RectF> mPerComplicationTypeBounds;
+    public Map<Integer, RectF> mPerComplicationTypeBounds;
 
     /** Ideally this would be Integer but VersionedParcelable doesn't support that. */
     @ParcelField(4)
@@ -66,7 +65,7 @@
     public ComplicationOverlayWireFormat(
             int complicationId,
             @Nullable Boolean enabled,
-            @Nullable Map<ComplicationType, RectF> perComplicationTypeBounds,
+            @Nullable Map<Integer, RectF> perComplicationTypeBounds,
             @Nullable Integer accessibilityTraversalIndex
     ) {
         mComplicationId = complicationId;
diff --git a/wear/wear-watchface-editor/lint-baseline.xml b/wear/wear-watchface-editor/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/wear-watchface-editor/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-watchface-editor/samples/lint-baseline.xml b/wear/wear-watchface-editor/samples/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/wear-watchface-editor/samples/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-watchface-style/lint-baseline.xml b/wear/wear-watchface-style/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/wear-watchface-style/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleSetting.kt b/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleSetting.kt
index 55a881d..d3169ac 100644
--- a/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleSetting.kt
+++ b/wear/wear-watchface-style/src/main/java/androidx/wear/watchface/style/UserStyleSetting.kt
@@ -19,6 +19,7 @@
 import android.graphics.drawable.Icon
 import androidx.annotation.RestrictTo
 import androidx.wear.complications.ComplicationBounds
+import androidx.wear.complications.data.ComplicationType
 import androidx.wear.watchface.style.UserStyleSetting.ComplicationsUserStyleSetting.ComplicationOverlay
 import androidx.wear.watchface.style.UserStyleSetting.ComplicationsUserStyleSetting.ComplicationsOption
 import androidx.wear.watchface.style.UserStyleSetting.Id.Companion.MAX_LENGTH
@@ -438,7 +439,11 @@
                         "Unrecognised wireFormat.mEnabled " + wireFormat.mEnabled
                     )
                 },
-                wireFormat.mPerComplicationTypeBounds?.let { ComplicationBounds(it) },
+                wireFormat.mPerComplicationTypeBounds?.let {
+                    ComplicationBounds(
+                        it.mapKeys { ComplicationType.fromWireType(it.key) }
+                    )
+                },
                 wireFormat.accessibilityTraversalIndex
             )
 
@@ -446,7 +451,9 @@
                 ComplicationOverlayWireFormat(
                     complicationId,
                     enabled,
-                    complicationBounds?.perComplicationTypeBounds,
+                    complicationBounds?.perComplicationTypeBounds?.mapKeys {
+                        it.key.toWireComplicationType()
+                    },
                     accessibilityTraversalIndex
                 )
         }
diff --git a/wear/wear-watchface/samples/lint-baseline.xml b/wear/wear-watchface/samples/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/wear/wear-watchface/samples/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/BroadcastReceivers.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/BroadcastReceivers.kt
deleted file mode 100644
index 322a004..0000000
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/BroadcastReceivers.kt
+++ /dev/null
@@ -1,215 +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.wear.watchface
-
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
-import androidx.annotation.UiThread
-import androidx.annotation.VisibleForTesting
-
-/**
- * All watchface instances share the same [Context] which is a problem for broadcast receivers
- * because the OS will mistakenly believe we're leaking them if there's more than one instance. So
- * we need to use this class to share them.
- */
-internal class BroadcastReceivers private constructor(private val context: Context) {
-
-    interface BroadcastEventObserver {
-        /** Called when we receive [Intent.ACTION_TIME_TICK]. */
-        @UiThread
-        fun onActionTimeTick()
-
-        /** Called when we receive [Intent.ACTION_TIMEZONE_CHANGED]. */
-        @UiThread
-        fun onActionTimeZoneChanged()
-
-        /** Called when we receive [Intent.ACTION_TIME_CHANGED]. */
-        @UiThread
-        fun onActionTimeChanged()
-
-        /** Called when we receive [Intent.ACTION_BATTERY_LOW]. */
-        @UiThread
-        fun onActionBatteryLow()
-
-        /** Called when we receive [Intent.ACTION_BATTERY_OKAY]. */
-        @UiThread
-        fun onActionBatteryOkay()
-
-        /** Called when we receive [Intent.ACTION_POWER_CONNECTED]. */
-        @UiThread
-        fun onActionPowerConnected()
-
-        /** Called when we receive [WatchFaceImpl.MOCK_TIME_INTENT]. */
-        @UiThread
-        fun onMockTime(intent: Intent)
-    }
-
-    companion object {
-        val broadcastEventObservers = HashSet<BroadcastEventObserver>()
-
-        /**
-         * We don't leak due to balanced calls to [addBroadcastEventObserver] and
-         * [removeBroadcastEventObserver] which sets this back to null.
-         */
-        @SuppressWarnings("StaticFieldLeak")
-        var broadcastReceivers: BroadcastReceivers? = null
-
-        @UiThread
-        fun addBroadcastEventObserver(context: Context, observer: BroadcastEventObserver) {
-            broadcastEventObservers.add(observer)
-            if (broadcastReceivers == null) {
-                broadcastReceivers = BroadcastReceivers(context)
-            }
-        }
-
-        @UiThread
-        fun removeBroadcastEventObserver(observer: BroadcastEventObserver) {
-            if (broadcastEventObservers.remove(observer) && broadcastEventObservers.isEmpty()) {
-                broadcastReceivers!!.onDestroy()
-                broadcastReceivers = null
-            }
-        }
-
-        @VisibleForTesting
-        fun sendOnActionBatteryLowForTesting(intent: Intent) {
-            require(intent.action == Intent.ACTION_BATTERY_LOW)
-            require(broadcastEventObservers.isNotEmpty())
-            for (observer in broadcastEventObservers) {
-                observer.onActionBatteryLow()
-            }
-        }
-
-        @VisibleForTesting
-        fun sendOnActionBatteryOkayForTesting(intent: Intent) {
-            require(intent.action == Intent.ACTION_BATTERY_OKAY)
-            require(broadcastEventObservers.isNotEmpty())
-            for (observer in broadcastEventObservers) {
-                observer.onActionBatteryOkay()
-            }
-        }
-
-        @VisibleForTesting
-        fun sendOnActionPowerConnectedForTesting(intent: Intent) {
-            require(intent.action == Intent.ACTION_POWER_CONNECTED)
-            require(broadcastEventObservers.isNotEmpty())
-            for (observer in broadcastEventObservers) {
-                observer.onActionPowerConnected()
-            }
-        }
-
-        @VisibleForTesting
-        fun sendOnMockTimeForTesting(intent: Intent) {
-            require(intent.action == WatchFaceImpl.MOCK_TIME_INTENT)
-            require(broadcastEventObservers.isNotEmpty())
-            for (observer in broadcastEventObservers) {
-                observer.onMockTime(intent)
-            }
-        }
-    }
-
-    private val actionTimeTickReceiver: BroadcastReceiver = object : BroadcastReceiver() {
-        @SuppressWarnings("SyntheticAccessor")
-        override fun onReceive(context: Context, intent: Intent) {
-            for (observer in broadcastEventObservers) {
-                observer.onActionTimeTick()
-            }
-        }
-    }
-
-    private val actionTimeZoneReceiver: BroadcastReceiver = object : BroadcastReceiver() {
-        override fun onReceive(context: Context, intent: Intent) {
-            for (observer in broadcastEventObservers) {
-                observer.onActionTimeZoneChanged()
-            }
-        }
-    }
-
-    private val actionTimeReceiver: BroadcastReceiver = object : BroadcastReceiver() {
-        override fun onReceive(context: Context?, intent: Intent?) {
-            for (observer in broadcastEventObservers) {
-                observer.onActionTimeChanged()
-            }
-        }
-    }
-
-    private val actionBatteryLowReceiver: BroadcastReceiver = object : BroadcastReceiver() {
-        @SuppressWarnings("SyntheticAccessor")
-        override fun onReceive(context: Context, intent: Intent) {
-            for (observer in broadcastEventObservers) {
-                observer.onActionBatteryLow()
-            }
-        }
-    }
-
-    private val actionBatteryOkayReceiver: BroadcastReceiver = object : BroadcastReceiver() {
-        @SuppressWarnings("SyntheticAccessor")
-        override fun onReceive(context: Context, intent: Intent) {
-            for (observer in broadcastEventObservers) {
-                observer.onActionBatteryOkay()
-            }
-        }
-    }
-
-    private val actionPowerConnectedReceiver: BroadcastReceiver = object : BroadcastReceiver() {
-        @SuppressWarnings("SyntheticAccessor")
-        override fun onReceive(context: Context, intent: Intent) {
-            for (observer in broadcastEventObservers) {
-                observer.onActionPowerConnected()
-            }
-        }
-    }
-
-    private val mockTimeReceiver: BroadcastReceiver = object : BroadcastReceiver() {
-        @SuppressWarnings("SyntheticAccessor")
-        override fun onReceive(context: Context, intent: Intent) {
-            for (observer in broadcastEventObservers) {
-                observer.onMockTime(intent)
-            }
-        }
-    }
-
-    init {
-        context.registerReceiver(actionTimeTickReceiver, IntentFilter(Intent.ACTION_TIME_TICK))
-        context.registerReceiver(
-            actionTimeZoneReceiver,
-            IntentFilter(Intent.ACTION_TIMEZONE_CHANGED)
-        )
-        context.registerReceiver(actionTimeReceiver, IntentFilter(Intent.ACTION_TIME_CHANGED))
-        context.registerReceiver(actionBatteryLowReceiver, IntentFilter(Intent.ACTION_BATTERY_LOW))
-        context.registerReceiver(
-            actionBatteryOkayReceiver,
-            IntentFilter(Intent.ACTION_BATTERY_OKAY)
-        )
-        context.registerReceiver(
-            actionPowerConnectedReceiver,
-            IntentFilter(Intent.ACTION_POWER_CONNECTED)
-        )
-        context.registerReceiver(mockTimeReceiver, IntentFilter(WatchFaceImpl.MOCK_TIME_INTENT))
-    }
-
-    fun onDestroy() {
-        context.unregisterReceiver(actionTimeTickReceiver)
-        context.unregisterReceiver(actionTimeZoneReceiver)
-        context.unregisterReceiver(actionTimeReceiver)
-        context.unregisterReceiver(actionBatteryLowReceiver)
-        context.unregisterReceiver(actionBatteryOkayReceiver)
-        context.unregisterReceiver(actionPowerConnectedReceiver)
-        context.unregisterReceiver(mockTimeReceiver)
-    }
-}
\ No newline at end of file
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/BroadcastsReceiver.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/BroadcastsReceiver.kt
new file mode 100644
index 0000000..cc6675a
--- /dev/null
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/BroadcastsReceiver.kt
@@ -0,0 +1,139 @@
+/*
+ * 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.wear.watchface
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import androidx.annotation.UiThread
+
+/**
+ * This class decouples [BroadcastEventObserver]s from the actual broadcast event receivers to make
+ * testing easier.
+ */
+internal class BroadcastsReceiver constructor(
+    private val context: Context,
+    private val observer: BroadcastEventObserver
+) {
+
+    interface BroadcastEventObserver {
+        /** Called when we receive [Intent.ACTION_TIME_TICK]. */
+        @UiThread
+        fun onActionTimeTick()
+
+        /** Called when we receive [Intent.ACTION_TIMEZONE_CHANGED]. */
+        @UiThread
+        fun onActionTimeZoneChanged()
+
+        /** Called when we receive [Intent.ACTION_TIME_CHANGED]. */
+        @UiThread
+        fun onActionTimeChanged()
+
+        /** Called when we receive [Intent.ACTION_BATTERY_LOW]. */
+        @UiThread
+        fun onActionBatteryLow()
+
+        /** Called when we receive [Intent.ACTION_BATTERY_OKAY]. */
+        @UiThread
+        fun onActionBatteryOkay()
+
+        /** Called when we receive [Intent.ACTION_POWER_CONNECTED]. */
+        @UiThread
+        fun onActionPowerConnected()
+
+        /** Called when we receive [WatchFaceImpl.MOCK_TIME_INTENT]. */
+        @UiThread
+        fun onMockTime(intent: Intent)
+    }
+
+    internal val actionTimeTickReceiver: BroadcastReceiver = object : BroadcastReceiver() {
+        @SuppressWarnings("SyntheticAccessor")
+        override fun onReceive(context: Context, intent: Intent) {
+            observer.onActionTimeTick()
+        }
+    }
+
+    internal val actionTimeZoneReceiver: BroadcastReceiver = object : BroadcastReceiver() {
+        override fun onReceive(context: Context, intent: Intent) {
+            observer.onActionTimeZoneChanged()
+        }
+    }
+
+    internal val actionTimeReceiver: BroadcastReceiver = object : BroadcastReceiver() {
+        override fun onReceive(context: Context?, intent: Intent?) {
+            observer.onActionTimeChanged()
+        }
+    }
+
+    internal val actionBatteryLowReceiver: BroadcastReceiver = object : BroadcastReceiver() {
+        @SuppressWarnings("SyntheticAccessor")
+        override fun onReceive(context: Context, intent: Intent) {
+            observer.onActionBatteryLow()
+        }
+    }
+
+    internal val actionBatteryOkayReceiver: BroadcastReceiver = object : BroadcastReceiver() {
+        @SuppressWarnings("SyntheticAccessor")
+        override fun onReceive(context: Context, intent: Intent) {
+            observer.onActionBatteryOkay()
+        }
+    }
+
+    internal val actionPowerConnectedReceiver: BroadcastReceiver = object : BroadcastReceiver() {
+        @SuppressWarnings("SyntheticAccessor")
+        override fun onReceive(context: Context, intent: Intent) {
+            observer.onActionPowerConnected()
+        }
+    }
+
+    internal val mockTimeReceiver: BroadcastReceiver = object : BroadcastReceiver() {
+        @SuppressWarnings("SyntheticAccessor")
+        override fun onReceive(context: Context, intent: Intent) {
+            observer.onMockTime(intent)
+        }
+    }
+
+    init {
+        context.registerReceiver(actionTimeTickReceiver, IntentFilter(Intent.ACTION_TIME_TICK))
+        context.registerReceiver(
+            actionTimeZoneReceiver,
+            IntentFilter(Intent.ACTION_TIMEZONE_CHANGED)
+        )
+        context.registerReceiver(actionTimeReceiver, IntentFilter(Intent.ACTION_TIME_CHANGED))
+        context.registerReceiver(actionBatteryLowReceiver, IntentFilter(Intent.ACTION_BATTERY_LOW))
+        context.registerReceiver(
+            actionBatteryOkayReceiver,
+            IntentFilter(Intent.ACTION_BATTERY_OKAY)
+        )
+        context.registerReceiver(
+            actionPowerConnectedReceiver,
+            IntentFilter(Intent.ACTION_POWER_CONNECTED)
+        )
+        context.registerReceiver(mockTimeReceiver, IntentFilter(WatchFaceImpl.MOCK_TIME_INTENT))
+    }
+
+    fun onDestroy() {
+        context.unregisterReceiver(actionTimeTickReceiver)
+        context.unregisterReceiver(actionTimeZoneReceiver)
+        context.unregisterReceiver(actionTimeReceiver)
+        context.unregisterReceiver(actionBatteryLowReceiver)
+        context.unregisterReceiver(actionBatteryOkayReceiver)
+        context.unregisterReceiver(actionPowerConnectedReceiver)
+        context.unregisterReceiver(mockTimeReceiver)
+    }
+}
\ No newline at end of file
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/Complication.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/Complication.kt
index 27a58d2..09eca33 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/Complication.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/Complication.kt
@@ -445,7 +445,9 @@
 
             // The caller might modify a number of complications. For efficiency we need to coalesce
             // these into one update task.
-            complicationsManager.scheduleUpdate()
+            if (this::complicationsManager.isInitialized) {
+                complicationsManager.scheduleUpdate()
+            }
         }
 
     internal var enabledDirty = true
diff --git a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
index 2153570..8dbc10c 100644
--- a/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
+++ b/wear/wear-watchface/src/main/java/androidx/wear/watchface/WatchFace.kt
@@ -435,7 +435,7 @@
     private var mockTime = MockTime(1.0, 0, Long.MAX_VALUE)
 
     private var lastTappedComplicationId: Int? = null
-    private var registeredReceivers = false
+    internal var broadcastsReceiver: BroadcastsReceiver? = null
 
     // True if 'Do Not Disturb' mode is on.
     private var muteMode = false
@@ -465,7 +465,7 @@
         legacyWatchFaceStyle.tapEventsAccepted
     )
 
-    private val broadcastEventObserver = object : BroadcastReceivers.BroadcastEventObserver {
+    private val broadcastEventObserver = object : BroadcastsReceiver.BroadcastEventObserver {
         override fun onActionTimeTick() {
             if (!watchState.isAmbient.value) {
                 renderer.invalidate()
@@ -759,14 +759,12 @@
         require(watchFaceHostApi.getHandler().looper.isCurrentThread) {
             "registerReceivers must be called the UiThread"
         }
-        if (registeredReceivers) {
-            return
+
+        // There's no point registering BroadcastsReceiver for headless instances.
+        if (broadcastsReceiver == null && !watchState.isHeadless) {
+            broadcastsReceiver =
+                BroadcastsReceiver(watchFaceHostApi.getContext(), broadcastEventObserver)
         }
-        registeredReceivers = true
-        BroadcastReceivers.addBroadcastEventObserver(
-            watchFaceHostApi.getContext(),
-            broadcastEventObserver
-        )
     }
 
     @UiThread
@@ -774,11 +772,8 @@
         require(watchFaceHostApi.getHandler().looper.isCurrentThread) {
             "unregisterReceivers must be called the UiThread"
         }
-        if (!registeredReceivers) {
-            return
-        }
-        registeredReceivers = false
-        BroadcastReceivers.removeBroadcastEventObserver(broadcastEventObserver)
+        broadcastsReceiver?.onDestroy()
+        broadcastsReceiver = null
     }
 
     private fun scheduleDraw() {
diff --git a/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt b/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
index fd55a85..118cb31 100644
--- a/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
+++ b/wear/wear-watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
@@ -624,7 +624,8 @@
         watchState.isAmbient.value = false
         testWatchFaceService.mockSystemTimeMillis = 1000L
 
-        BroadcastReceivers.sendOnMockTimeForTesting(
+        watchFaceImpl.broadcastsReceiver!!.mockTimeReceiver.onReceive(
+            context,
             Intent(WatchFaceImpl.MOCK_TIME_INTENT).apply {
                 putExtra(WatchFaceImpl.EXTRA_MOCK_TIME_SPEED_MULTIPLIER, 2.0f)
                 putExtra(WatchFaceImpl.EXTRA_MOCK_TIME_WRAPPING_MIN_TIME, -1L)
@@ -651,7 +652,8 @@
         watchState.isAmbient.value = false
         testWatchFaceService.mockSystemTimeMillis = 1000L
 
-        BroadcastReceivers.sendOnMockTimeForTesting(
+        watchFaceImpl.broadcastsReceiver!!.mockTimeReceiver.onReceive(
+            context,
             Intent(WatchFaceImpl.MOCK_TIME_INTENT).apply {
                 putExtra(WatchFaceImpl.EXTRA_MOCK_TIME_SPEED_MULTIPLIER, 2.0f)
                 putExtra(WatchFaceImpl.EXTRA_MOCK_TIME_WRAPPING_MIN_TIME, 1000L)
@@ -857,13 +859,19 @@
         )
 
         // The delay should change when battery is low.
-        BroadcastReceivers.sendOnActionBatteryLowForTesting(Intent(Intent.ACTION_BATTERY_LOW))
+        watchFaceImpl.broadcastsReceiver!!.actionBatteryLowReceiver.onReceive(
+            context,
+            Intent(Intent.ACTION_BATTERY_LOW)
+        )
         assertThat(watchFaceImpl.computeDelayTillNextFrame(0, 0)).isEqualTo(
             WatchFaceImpl.MAX_LOW_POWER_INTERACTIVE_UPDATE_RATE_MS
         )
 
         // And go back to normal when battery is OK.
-        BroadcastReceivers.sendOnActionBatteryOkayForTesting(Intent(Intent.ACTION_BATTERY_OKAY))
+        watchFaceImpl.broadcastsReceiver!!.actionBatteryOkayReceiver.onReceive(
+            context,
+            Intent(Intent.ACTION_BATTERY_OKAY)
+        )
         assertThat(watchFaceImpl.computeDelayTillNextFrame(0, 0)).isEqualTo(
             INTERACTIVE_UPDATE_RATE_MS
         )
@@ -882,13 +890,17 @@
         )
 
         // The delay should change when battery is low.
-        BroadcastReceivers.sendOnActionBatteryLowForTesting(Intent(Intent.ACTION_BATTERY_LOW))
+        watchFaceImpl.broadcastsReceiver!!.actionBatteryLowReceiver.onReceive(
+            context,
+            Intent(Intent.ACTION_BATTERY_LOW)
+        )
         assertThat(watchFaceImpl.computeDelayTillNextFrame(0, 0)).isEqualTo(
             WatchFaceImpl.MAX_LOW_POWER_INTERACTIVE_UPDATE_RATE_MS
         )
 
         // And go back to normal when power is connected.
-        BroadcastReceivers.sendOnActionPowerConnectedForTesting(
+        watchFaceImpl.broadcastsReceiver!!.actionPowerConnectedReceiver.onReceive(
+            context,
             Intent(Intent.ACTION_POWER_CONNECTED)
         )
         assertThat(watchFaceImpl.computeDelayTillNextFrame(0, 0)).isEqualTo(
@@ -2536,13 +2548,35 @@
     }
 
     @Test
-    public fun double_BroadcastReceivers_removeBroadcastEventObserver() {
-        val observer = mock<BroadcastReceivers.BroadcastEventObserver>()
-        BroadcastReceivers.addBroadcastEventObserver(context, observer)
-        BroadcastReceivers.removeBroadcastEventObserver(observer)
+    public fun complicationsUserStyleSetting_with_setComplicationBounds() {
+        val complicationsStyleSetting = ComplicationsUserStyleSetting(
+            UserStyleSetting.Id("complications_style_setting"),
+            "AllComplications",
+            "Number and position",
+            icon = null,
+            complicationConfig = listOf(
+                ComplicationsOption(
+                    Option.Id(RIGHT_COMPLICATION),
+                    "Right",
+                    null,
+                    listOf(
+                        ComplicationOverlay.Builder(LEFT_COMPLICATION_ID)
+                            .setComplicationBounds(
+                                ComplicationBounds(RectF(10f, 10f, 20f, 20f))
+                            ).build()
+                    )
+                )
+            ),
+            affectsWatchFaceLayers = listOf(WatchFaceLayer.COMPLICATIONS)
+        )
 
-        // This shouldn't throw an exception.
-        BroadcastReceivers.removeBroadcastEventObserver(observer)
+        // This should not crash.
+        initEngine(
+            WatchFaceType.DIGITAL,
+            listOf(leftComplication, rightComplication),
+            UserStyleSchema(listOf(complicationsStyleSetting)),
+            apiVersion = 4
+        )
     }
 
     @Suppress("DEPRECATION")
diff --git a/window/window-extensions/lint-baseline.xml b/window/window-extensions/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/window/window-extensions/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/window/window-samples/lint-baseline.xml b/window/window-samples/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/window/window-samples/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/window/window-sidecar/lint-baseline.xml b/window/window-sidecar/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/window/window-sidecar/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/window/window/api/current.txt b/window/window/api/current.txt
index 5c30487..c82eaa4 100644
--- a/window/window/api/current.txt
+++ b/window/window/api/current.txt
@@ -40,6 +40,12 @@
     method public void unregisterLayoutChangeCallback(androidx.core.util.Consumer<androidx.window.WindowLayoutInfo> callback);
   }
 
+  public interface WindowInfoRepo {
+    method public androidx.window.WindowMetrics currentWindowMetrics();
+    method public androidx.window.WindowMetrics maximumWindowMetrics();
+    method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> windowLayoutInfo();
+  }
+
   public final class WindowLayoutInfo {
     method public java.util.List<androidx.window.DisplayFeature> getDisplayFeatures();
     property public final java.util.List<androidx.window.DisplayFeature> displayFeatures;
@@ -66,5 +72,8 @@
     property public final android.graphics.Rect bounds;
   }
 
+  public final class WindowServices {
+  }
+
 }
 
diff --git a/window/window/api/public_plus_experimental_current.txt b/window/window/api/public_plus_experimental_current.txt
index 5c30487..c6788d2 100644
--- a/window/window/api/public_plus_experimental_current.txt
+++ b/window/window/api/public_plus_experimental_current.txt
@@ -40,6 +40,12 @@
     method public void unregisterLayoutChangeCallback(androidx.core.util.Consumer<androidx.window.WindowLayoutInfo> callback);
   }
 
+  public interface WindowInfoRepo {
+    method public androidx.window.WindowMetrics currentWindowMetrics();
+    method public androidx.window.WindowMetrics maximumWindowMetrics();
+    method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> windowLayoutInfo();
+  }
+
   public final class WindowLayoutInfo {
     method public java.util.List<androidx.window.DisplayFeature> getDisplayFeatures();
     property public final java.util.List<androidx.window.DisplayFeature> displayFeatures;
@@ -66,5 +72,9 @@
     property public final android.graphics.Rect bounds;
   }
 
+  public final class WindowServices {
+    method @kotlinx.coroutines.ExperimentalCoroutinesApi public static androidx.window.WindowInfoRepo windowInfoRepository(android.app.Activity);
+  }
+
 }
 
diff --git a/window/window/api/restricted_current.txt b/window/window/api/restricted_current.txt
index 5c30487..c82eaa4 100644
--- a/window/window/api/restricted_current.txt
+++ b/window/window/api/restricted_current.txt
@@ -40,6 +40,12 @@
     method public void unregisterLayoutChangeCallback(androidx.core.util.Consumer<androidx.window.WindowLayoutInfo> callback);
   }
 
+  public interface WindowInfoRepo {
+    method public androidx.window.WindowMetrics currentWindowMetrics();
+    method public androidx.window.WindowMetrics maximumWindowMetrics();
+    method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> windowLayoutInfo();
+  }
+
   public final class WindowLayoutInfo {
     method public java.util.List<androidx.window.DisplayFeature> getDisplayFeatures();
     property public final java.util.List<androidx.window.DisplayFeature> displayFeatures;
@@ -66,5 +72,8 @@
     property public final android.graphics.Rect bounds;
   }
 
+  public final class WindowServices {
+  }
+
 }
 
diff --git a/window/window/build.gradle b/window/window/build.gradle
index 2fe4f79..cfb74ad 100644
--- a/window/window/build.gradle
+++ b/window/window/build.gradle
@@ -17,19 +17,9 @@
 import androidx.build.LibraryGroups
 import androidx.build.LibraryVersions
 import androidx.build.Publish
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
-import static androidx.build.dependencies.DependenciesKt.ANDROIDX_TEST_CORE
-import static androidx.build.dependencies.DependenciesKt.ANDROIDX_TEST_EXT_JUNIT
-import static androidx.build.dependencies.DependenciesKt.ANDROIDX_TEST_RULES
-import static androidx.build.dependencies.DependenciesKt.ANDROIDX_TEST_RUNNER
-import static androidx.build.dependencies.DependenciesKt.DEXMAKER_MOCKITO
-import static androidx.build.dependencies.DependenciesKt.JUNIT
-import static androidx.build.dependencies.DependenciesKt.MOCKITO_CORE
-import static androidx.build.dependencies.DependenciesKt.MOCKITO_KOTLIN
-import static androidx.build.dependencies.DependenciesKt.ROBOLECTRIC
-import static androidx.build.dependencies.DependenciesKt.TRUTH
-import static androidx.build.dependencies.DependenciesKt.getKOTLIN_COROUTINES_ANDROID
-import static androidx.build.dependencies.DependenciesKt.getKOTLIN_STDLIB
+import static androidx.build.dependencies.DependenciesKt.*
 
 plugins {
     id("AndroidXPlugin")
@@ -38,6 +28,9 @@
 }
 
 android {
+    defaultConfig {
+        multiDexEnabled = true
+    }
     buildTypes.all {
         consumerProguardFiles "proguard-rules.pro"
     }
@@ -69,6 +62,7 @@
     testImplementation(ROBOLECTRIC)
     testImplementation(MOCKITO_CORE)
     testImplementation(MOCKITO_KOTLIN)
+    testImplementation(KOTLIN_COROUTINES_TEST)
     testImplementation(compileOnly(project(":window:window-extensions")))
     testImplementation(compileOnly(project(":window:window-sidecar")))
 
@@ -78,6 +72,8 @@
     androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy)
     androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy)
     androidTestImplementation(MOCKITO_KOTLIN, excludes.bytebuddy)
+    androidTestImplementation(KOTLIN_COROUTINES_TEST)
+    androidTestImplementation(MULTIDEX)
     androidTestImplementation(TRUTH)
     androidTestImplementation(compileOnly(project(":window:window-extensions")))
     androidTestImplementation(compileOnly(project(":window:window-sidecar")))
@@ -95,3 +91,10 @@
     // Sidecar interface.
     failOnDeprecationWarnings = false
 }
+
+// Allow usage of Kotlin's @OptIn.
+tasks.withType(KotlinCompile).configureEach {
+    kotlinOptions {
+        freeCompilerArgs += ["-Xopt-in=kotlin.RequiresOptIn"]
+    }
+}
diff --git a/window/window/src/androidTest/java/androidx/window/WindowInfoRepoImpTest.kt b/window/window/src/androidTest/java/androidx/window/WindowInfoRepoImpTest.kt
new file mode 100644
index 0000000..724e6e3
--- /dev/null
+++ b/window/window/src/androidTest/java/androidx/window/WindowInfoRepoImpTest.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window
+
+import android.app.Activity
+import androidx.core.util.Consumer
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.TestCoroutineScope
+import kotlinx.coroutines.test.runBlockingTest
+import org.junit.Assert.assertEquals
+import org.junit.Rule
+import org.junit.Test
+import java.util.concurrent.Executor
+
+@OptIn(ExperimentalCoroutinesApi::class)
+public class WindowInfoRepoImpTest {
+
+    @get:Rule
+    public val activityScenario: ActivityScenarioRule<TestActivity> =
+        ActivityScenarioRule(TestActivity::class.java)
+
+    private val testScope = TestCoroutineScope()
+
+    @Test
+    public fun testGetCurrentWindowMetrics() {
+        activityScenario.scenario.onActivity { testActivity ->
+            val windowBoundsHelper = WindowBoundsHelper.instance
+            val repo = WindowInfoRepoImp(
+                testActivity,
+                windowBoundsHelper,
+                FakeWindowBackend()
+            )
+            val expectedBounds = windowBoundsHelper.computeCurrentWindowBounds(testActivity)
+            val expected = WindowMetrics(expectedBounds)
+            val actual = repo.currentWindowMetrics()
+            assertEquals(expected, actual)
+        }
+    }
+
+    @Test
+    public fun testGetMaximumWindowMetrics() {
+        activityScenario.scenario.onActivity { testActivity ->
+            val windowBoundsHelper = WindowBoundsHelper.instance
+            val repo = WindowInfoRepoImp(
+                testActivity,
+                windowBoundsHelper,
+                FakeWindowBackend()
+            )
+            val expectedBounds = windowBoundsHelper.computeMaximumWindowBounds(testActivity)
+            val expected = WindowMetrics(expectedBounds)
+            val actual = repo.maximumWindowMetrics()
+            assertEquals(expected, actual)
+        }
+    }
+
+    @Test
+    public fun testWindowLayoutFeatures(): Unit = testScope.runBlockingTest {
+        activityScenario.scenario.onActivity { testActivity ->
+            val windowBoundsHelper = WindowBoundsHelper.instance
+            val fakeBackend = FakeWindowBackend()
+            val repo = WindowInfoRepoImp(
+                testActivity,
+                windowBoundsHelper,
+                fakeBackend
+            )
+            val collector = TestConsumer<WindowLayoutInfo>()
+            testScope.launch {
+                repo.windowLayoutInfo().collect(collector::accept)
+            }
+            fakeBackend.triggerSignal(WindowLayoutInfo(emptyList()))
+            collector.assertValue(WindowLayoutInfo(emptyList()))
+        }
+    }
+
+    private class FakeWindowBackend : WindowBackend {
+
+        private class CallbackHolder(
+            val executor: Executor,
+            val callback: Consumer<WindowLayoutInfo>
+        ) : Consumer<WindowLayoutInfo> {
+
+            override fun accept(t: WindowLayoutInfo?) {
+                executor.execute { callback.accept(t) }
+            }
+        }
+
+        private val consumers = mutableListOf<CallbackHolder>()
+
+        fun triggerSignal(info: WindowLayoutInfo) {
+            consumers.forEach { consumer -> consumer.accept(info) }
+        }
+
+        override fun registerLayoutChangeCallback(
+            activity: Activity,
+            executor: Executor,
+            callback: Consumer<WindowLayoutInfo>
+        ) {
+            consumers.add(CallbackHolder(executor, callback))
+        }
+
+        override fun unregisterLayoutChangeCallback(callback: Consumer<WindowLayoutInfo>) {
+            consumers.removeIf { it.callback == callback }
+        }
+    }
+}
\ No newline at end of file
diff --git a/window/window/src/main/java/androidx/window/WindowInfoRepo.kt b/window/window/src/main/java/androidx/window/WindowInfoRepo.kt
new file mode 100644
index 0000000..32ea8e3
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/WindowInfoRepo.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window
+
+import android.content.Context
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * An interface to provide all the relevant info about a [android.view.Window].
+ */
+public interface WindowInfoRepo {
+
+    /**
+     * Returns the [WindowMetrics] according to the current system state.
+     *
+     *
+     * The metrics describe the size of the area the window would occupy with
+     * [MATCH_PARENT][android.view.WindowManager.LayoutParams.MATCH_PARENT] width and height
+     * and any combination of flags that would allow the window to extend behind display cutouts.
+     *
+     *
+     * The value of this is based on the **current** windowing state of the system. For
+     * example, for activities in multi-window mode, the metrics returned are based on the
+     * current bounds that the user has selected for the [Activity][android.app.Activity]'s
+     * window.
+     *
+     * @see maximumWindowMetrics
+     * @see android.view.WindowManager.getCurrentWindowMetrics
+     */
+    public fun currentWindowMetrics(): WindowMetrics
+
+    /**
+     * Returns the largest [WindowMetrics] an app may expect in the current system state.
+     *
+     *
+     * The metrics describe the size of the largest potential area the window might occupy with
+     * [MATCH_PARENT][android.view.WindowManager.LayoutParams.MATCH_PARENT] width and height
+     * and any combination of flags that would allow the window to extend behind display cutouts.
+     *
+     *
+     * The value of this is based on the largest **potential** windowing state of the system.
+     * For example, for activities in multi-window mode the metrics returned are based on what the
+     * bounds would be if the user expanded the window to cover the entire screen.
+     *
+     *
+     * Note that this might still be smaller than the size of the physical display if certain
+     * areas of the display are not available to windows created for the associated [Context].
+     * For example, devices with foldable displays that wrap around the enclosure may split the
+     * physical display into different regions, one for the front and one for the back, each acting
+     * as different logical displays. In this case [.getMaximumWindowMetrics] would return
+     * the region describing the side of the device the associated [context&#39;s][Context]
+     * window is placed.
+     *
+     * @see currentWindowMetrics
+     * @see android.view.WindowManager.getMaximumWindowMetrics
+     */
+    public fun maximumWindowMetrics(): WindowMetrics
+
+    /**
+     * A [Flow] of [WindowLayoutInfo] that contains all the available features.
+     */
+    public fun windowLayoutInfo(): Flow<WindowLayoutInfo>
+}
diff --git a/window/window/src/main/java/androidx/window/WindowInfoRepoImp.kt b/window/window/src/main/java/androidx/window/WindowInfoRepoImp.kt
new file mode 100644
index 0000000..817459f
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/WindowInfoRepoImp.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window
+
+import android.app.Activity
+import android.content.Context
+import androidx.core.util.Consumer
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.buffer
+import kotlinx.coroutines.flow.callbackFlow
+
+/**
+ * An implementation of [WindowInfoRepo] that provides the [WindowLayoutInfo] and
+ * [WindowMetrics] for the given [Activity].
+ *
+ * @param activity that the provided window is based on.
+ * @param windowBoundsHelper a helper to calculate the [WindowMetrics] for the [Activity].
+ * @param windowBackend a helper to provide the [WindowLayoutInfo].
+ */
+@ExperimentalCoroutinesApi
+internal class WindowInfoRepoImp(
+    private val activity: Activity,
+    private val windowBoundsHelper: WindowBoundsHelper,
+    private val windowBackend: WindowBackend
+) : WindowInfoRepo {
+
+    /**
+     * Returns the [WindowMetrics] according to the current system state.
+     *
+     *
+     * The metrics describe the size of the area the window would occupy with
+     * [MATCH_PARENT][android.view.WindowManager.LayoutParams.MATCH_PARENT] width and height
+     * and any combination of flags that would allow the window to extend behind display cutouts.
+     *
+     *
+     * The value of this is based on the **current** windowing state of the system. For
+     * example, for activities in multi-window mode, the metrics returned are based on the
+     * current bounds that the user has selected for the [Activity][android.app.Activity]'s
+     * window.
+     *
+     * @see maximumWindowMetrics
+     * @see android.view.WindowManager.getCurrentWindowMetrics
+     */
+    override fun currentWindowMetrics(): WindowMetrics {
+        return WindowMetrics(windowBoundsHelper.computeCurrentWindowBounds(activity))
+    }
+
+    /**
+     * Returns the largest [WindowMetrics] an app may expect in the current system state.
+     *
+     *
+     * The metrics describe the size of the largest potential area the window might occupy with
+     * [MATCH_PARENT][android.view.WindowManager.LayoutParams.MATCH_PARENT] width and height
+     * and any combination of flags that would allow the window to extend behind display cutouts.
+     *
+     *
+     * The value of this is based on the largest **potential** windowing state of the system.
+     * For example, for activities in multi-window mode the metrics returned are based on what the
+     * bounds would be if the user expanded the window to cover the entire screen.
+     *
+     *
+     * Note that this might still be smaller than the size of the physical display if certain
+     * areas of the display are not available to windows created for the associated [Context].
+     * For example, devices with foldable displays that wrap around the enclosure may split the
+     * physical display into different regions, one for the front and one for the back, each acting
+     * as different logical displays. In this case [.getMaximumWindowMetrics] would return
+     * the region describing the side of the device the associated [context&#39;s][Context]
+     * window is placed.
+     *
+     * @see currentWindowMetrics
+     * @see android.view.WindowManager.getMaximumWindowMetrics
+     */
+    override fun maximumWindowMetrics(): WindowMetrics {
+        return WindowMetrics(windowBoundsHelper.computeMaximumWindowBounds(activity))
+    }
+
+    /**
+     * A [Flow] of window layout changes in the current visual [Context].
+     *
+     * @see Activity.onAttachedToWindow
+     */
+    override fun windowLayoutInfo(): Flow<WindowLayoutInfo> = callbackFlow {
+        val callback = Consumer<WindowLayoutInfo> { info -> offer(info) }
+        windowBackend.registerLayoutChangeCallback(activity, Runnable::run, callback)
+        awaitClose { windowBackend.unregisterLayoutChangeCallback(callback) }
+    }.buffer(capacity = UNLIMITED)
+}
diff --git a/window/window/src/main/java/androidx/window/WindowServices.kt b/window/window/src/main/java/androidx/window/WindowServices.kt
new file mode 100644
index 0000000..fd3881d
--- /dev/null
+++ b/window/window/src/main/java/androidx/window/WindowServices.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@file:JvmName("WindowServices")
+
+package androidx.window
+
+import android.app.Activity
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+/**
+ * Provide an instance of [WindowInfoRepo] that is associated to the given [Activity]
+ */
+@ExperimentalCoroutinesApi
+public fun Activity.windowInfoRepository(): WindowInfoRepo {
+    return WindowInfoRepoImp(
+        this,
+        WindowBoundsHelper.instance,
+        ExtensionWindowBackend.getInstance(this)
+    )
+}
diff --git a/window/window/src/testUtil/java/androidx/window/TestConsumer.kt b/window/window/src/testUtil/java/androidx/window/TestConsumer.kt
new file mode 100644
index 0000000..6976014
--- /dev/null
+++ b/window/window/src/testUtil/java/androidx/window/TestConsumer.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.window
+
+import androidx.core.util.Consumer
+import org.junit.Assert.assertEquals
+
+/**
+ * A test [Consumer] to hold all the values and make assertions based on the values.
+ */
+public class TestConsumer<T> : Consumer<T> {
+
+    private val values: MutableList<T> = mutableListOf()
+
+    /**
+     * Add the value to the list of seen values.
+     */
+    override fun accept(t: T) {
+        values.add(t)
+    }
+
+    /**
+     * Assert that there have been a fixed number of values
+     */
+    public fun assertValueCount(count: Int) {
+        assertEquals(count, values.size)
+    }
+
+    /**
+     * Assert that there has been exactly one value.
+     */
+    public fun assertValue(t: T) {
+        assertValueCount(1)
+        assertEquals(t, values[0])
+    }
+}
diff --git a/work/workmanager-benchmark/lint-baseline.xml b/work/workmanager-benchmark/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/work/workmanager-benchmark/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/work/workmanager-inspection/lint-baseline.xml b/work/workmanager-inspection/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/work/workmanager-inspection/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/work/workmanager-ktx/lint-baseline.xml b/work/workmanager-ktx/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/work/workmanager-ktx/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/work/workmanager-lint/lint-baseline.xml b/work/workmanager-lint/lint-baseline.xml
deleted file mode 100644
index 8794ae8..0000000
--- a/work/workmanager-lint/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" version="4.2.0-beta06">
-
-</issues>
diff --git a/work/workmanager-multiprocess/lint-baseline.xml b/work/workmanager-multiprocess/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/work/workmanager-multiprocess/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/work/workmanager-rxjava2/lint-baseline.xml b/work/workmanager-rxjava2/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/work/workmanager-rxjava2/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>
diff --git a/work/workmanager-rxjava3/lint-baseline.xml b/work/workmanager-rxjava3/lint-baseline.xml
deleted file mode 100644
index aaebb86..0000000
--- a/work/workmanager-rxjava3/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta06" client="gradle" variant="debug" version="4.2.0-beta06">
-
-</issues>